Project

General

Profile

Download (10.3 KB) Statistics
| Branch: | Revision:

library / src / main / java / org / distorted / library / mesh / MeshPolygon.java @ 97b6c85e

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.library.mesh;
21

    
22
///////////////////////////////////////////////////////////////////////////////////////////////////
23
/**
24
 * Create a polygon of any shape and varying elevations from the edges towards the center.
25
 * <p>
26
 * Specify a list of vertices. Any two adjacent vertices + the center (0,0,0) form a triangle. The
27
 * polygon is going to be split into such triangles, and each triange is split into adjustable number
28
 * of 'bands' form the outer edge towards the center. Edges of each band can can at any elevation.
29
 */
30
public class MeshPolygon extends MeshBase
31
  {
32
  private float[] mPolygonVertices;
33
  private int mNumPolygonVertices;
34
  private float[] mPolygonBands;
35
  private int mNumPolygonBands;
36

    
37
  private int remainingVert;
38
  private int numVertices;
39
  private int extraIndex, extraVertices;
40

    
41
  private float[] mBandQuot;
42

    
43
///////////////////////////////////////////////////////////////////////////////////////////////////
44
// polygonVertices>=3 , polygonBands>=2
45

    
46
  private void computeNumberOfVertices()
47
     {
48
     numVertices = (mNumPolygonVertices*mNumPolygonBands+2)*(mNumPolygonBands-1) - 1;
49
     numVertices+= 2*mNumPolygonVertices*(2*extraIndex*extraVertices);
50

    
51
     remainingVert = numVertices;
52
     }
53

    
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55

    
56
  private void computeCache()
57
    {
58
    mBandQuot = new float[mNumPolygonBands];
59

    
60
    int next, prev;
61

    
62
    for(int band=0; band<mNumPolygonBands; band++)
63
      {
64
      next = (band==mNumPolygonBands-1 ? band : band+1);
65
      prev = (band==                 0 ? band : band-1);
66

    
67
      mBandQuot[band] = (mPolygonBands[2*prev+1]-mPolygonBands[2*next+1]) / (mPolygonBands[2*next]-mPolygonBands[2*prev]);
68
      }
69
    }
70

    
71
///////////////////////////////////////////////////////////////////////////////////////////////////
72

    
73
  private float getQuot(int index, int band, boolean isExtra)
74
    {
75
    int num = mNumPolygonBands-1-band;
76

    
77
    if( num>0 )
78
      {
79
      if( isExtra )
80
        {
81
        int extra = extraIndex-band+extraVertices;
82

    
83
        if( index < extra )
84
          {
85
          float quot = ((float)extraIndex-band)/(extra*num);
86
          return index*quot;
87
          }
88
        else if( index > num+2*extraVertices-extra )
89
          {
90
          float quot = ((float)extraIndex-band)/(extra*num);
91
          return (1.0f-((float)extraIndex-band)/num) + (index-num-2*extraVertices+extra)*quot;
92
          }
93
        else
94
          {
95
          return ((float)(index-extraVertices))/num;
96
          }
97
        }
98

    
99
      return (float)index/num;
100
      }
101

    
102
    return 1.0f;
103
    }
104

    
105
///////////////////////////////////////////////////////////////////////////////////////////////////
106

    
107
  private int addVertex(int vertex, int polyBand, int polyVertex, int polyEndVer, float quot, float[] attribs1, float[] attribs2)
108
    {
109
    remainingVert--;
110

    
111
    float vx,vy,vz;
112
    float Xfirst= mPolygonVertices[2*polyVertex  ];
113
    float Yfirst= mPolygonVertices[2*polyVertex+1];
114
    float Xlast = mPolygonVertices[2*polyEndVer  ];
115
    float Ylast = mPolygonVertices[2*polyEndVer+1];
116

    
117
    float xEdge = Xfirst + quot*(Xlast-Xfirst);
118
    float yEdge = Yfirst + quot*(Ylast-Yfirst);
119

    
120
    float x = mPolygonBands[2*polyBand]*xEdge;
121
    float y = mPolygonBands[2*polyBand]*yEdge;
122

    
123
    if( quot==0.0f || quot==1.0f )
124
      {
125
      vx = mBandQuot[polyBand]*xEdge;
126
      vy = mBandQuot[polyBand]*yEdge;
127
      vz = xEdge*xEdge + yEdge*yEdge;
128
      }
129
    else
130
      {
131
      vx = mBandQuot[polyBand]*(Ylast-Yfirst);
132
      vy = mBandQuot[polyBand]*(Xfirst-Xlast);
133
      float tmp = Xfirst*Ylast - Xlast*Yfirst;
134
      vz = (tmp<0 ? -tmp:tmp);
135
      }
136

    
137
    float len = (float)Math.sqrt(vx*vx + vy*vy + vz*vz);
138

    
139
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB  ] = x;
140
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+1] = y;
141
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+2] = mPolygonBands[2*polyBand+1];
142

    
143
    attribs1[VERT1_ATTRIBS*vertex + NOR_ATTRIB  ] = vx/len;
144
    attribs1[VERT1_ATTRIBS*vertex + NOR_ATTRIB+1] = vy/len;
145
    attribs1[VERT1_ATTRIBS*vertex + NOR_ATTRIB+2] = vz/len;
146

    
147
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB  ] = x+0.5f;
148
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB+1] = y+0.5f;
149

    
150
    return vertex+1;
151
    }
152

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

    
155
  private int createBandStrip(int vertex, int polyBand, int polyVertex, float[] attribs1, float[] attribs2)
156
    {
157
    if( polyVertex==0 )
158
      {
159
      vertex = addVertex(vertex,polyBand,0,1,0,attribs1,attribs2);
160

    
161
      if( polyBand>0 )
162
        {
163
        vertex = addVertex(vertex,polyBand,0,1,0,attribs1,attribs2);
164
        }
165
      }
166

    
167
    int numPairs = mNumPolygonBands-1-polyBand;
168
    boolean isExtra = polyBand<extraIndex;
169

    
170
    if( isExtra )
171
      {
172
      numPairs += 2*extraVertices;
173
      }
174

    
175
    int polyEndVer = polyVertex==mNumPolygonVertices-1 ? 0 : polyVertex+1;
176
    float quot1, quot2;
177

    
178
    for(int index=0; index<numPairs; index++)
179
      {
180
      quot1 = getQuot(index  ,polyBand+1, isExtra);
181
      quot2 = getQuot(index+1,polyBand  , isExtra);
182

    
183
      vertex = addVertex(vertex,polyBand+1,polyVertex,polyEndVer,quot1,attribs1,attribs2);
184
      vertex = addVertex(vertex,polyBand  ,polyVertex,polyEndVer,quot2,attribs1,attribs2);
185
      }
186

    
187
    return vertex;
188
    }
189

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191

    
192
  private void buildGrid(float[] attribs1, float[] attribs2)
193
    {
194
    int vertex=0;
195

    
196
    for(int polyBand=0; polyBand<mNumPolygonBands-1; polyBand++)
197
      for(int polyVertex=0; polyVertex<mNumPolygonVertices; polyVertex++)
198
        {
199
        vertex = createBandStrip(vertex,polyBand,polyVertex,attribs1,attribs2);
200
        }
201
    }
202

    
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204
// PUBLIC API
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206
/**
207
 * Create a polygon of any shape and varying elevations from the edges towards the center.
208
 * Optionally make it more dense at the vertices.
209
 *
210
 * @param verticesXY 2N floats - packed description of polygon vertices. N pairs (x,y).
211
 *                   Vertices HAVE TO be specified in a COUNTERCLOCKWISE order (starting from any).
212
 * @param bands      2K floats; K pairs of two floats each describing a single band.
213
 *                   From (1.0,Z[0]) (outer edge, its Z elevation) to (0.0,Z[K]) (the center,
214
 *                   its elevation). The polygon is split into such concentric bands.
215
 *                   Must be band[2*i] > band[2*(i+1)] !
216
 * @param exIndex    This and the next parameter describe how to make the mesh denser at the
217
 *                   polyVertices. If e.g. exIndex=3 and exVertices=2, then 3 triangles of the
218
 *                   outermost band (and 2 triangles of the next band, and 1 triange of the third
219
 *                   band) get denser - the 3 triangles become 3+2 = 5.
220
 * @param exVertices See above.
221
 */
222
  public MeshPolygon(float[] verticesXY, float[] bands, int exIndex, int exVertices)
223
    {
224
    super();
225

    
226
    mPolygonVertices   = verticesXY;
227
    mPolygonBands      = bands;
228
    mNumPolygonVertices= mPolygonVertices.length /2;
229
    mNumPolygonBands   = mPolygonBands.length /2;
230
    extraIndex         = exIndex;
231
    extraVertices      = exVertices;
232

    
233
    computeNumberOfVertices();
234
    computeCache();
235

    
236
    float[] attribs1= new float[VERT1_ATTRIBS*numVertices];
237
    float[] attribs2= new float[VERT2_ATTRIBS*numVertices];
238

    
239
    buildGrid(attribs1,attribs2);
240

    
241
    if( remainingVert!=0 )
242
      android.util.Log.d("MeshPolygon", "remainingVert " +remainingVert );
243

    
244
    setAttribs(attribs1,attribs2);
245
    }
246

    
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248
/**
249
 * Create a polygon of any shape and varying elevations from the edges towards the center.
250
 * Equivalent of the previous with exIndex=0 or exVertices=0.
251
 */
252
  public MeshPolygon(float[] verticesXY, float[] bands)
253
    {
254
    this(verticesXY,bands,0,0);
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258
/**
259
 * Copy constructor.
260
 */
261
  public MeshPolygon(MeshPolygon mesh, boolean deep)
262
    {
263
    super(mesh,deep);
264
    }
265

    
266
///////////////////////////////////////////////////////////////////////////////////////////////////
267
/**
268
 * Copy the Mesh.
269
 *
270
 * @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices,
271
 *             normals and inflates (the rest, in particular the mVertAttribs2 containing texture
272
 *             coordinates and effect associations, is always deep copied)
273
 */
274
  public MeshPolygon copy(boolean deep)
275
    {
276
    return new MeshPolygon(this,deep);
277
    }
278
 }
(6-6/10)