Project

General

Profile

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

library / src / main / java / org / distorted / library / mesh / MeshPolygon.java @ b2913a86

1 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2 c4d06f90 Leszek Koltunski
// Copyright 2020 Leszek Koltunski  leszek@koltunski.pl                                          //
3 808ef3aa Leszek Koltunski
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6 c4d06f90 Leszek Koltunski
// This library is free software; you can redistribute it and/or                                 //
7
// modify it under the terms of the GNU Lesser General Public                                    //
8
// License as published by the Free Software Foundation; either                                  //
9
// version 2.1 of the License, or (at your option) any later version.                            //
10 808ef3aa Leszek Koltunski
//                                                                                               //
11 c4d06f90 Leszek Koltunski
// This library is distributed in the hope that it will be useful,                               //
12 808ef3aa Leszek Koltunski
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13 c4d06f90 Leszek Koltunski
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU                             //
14
// Lesser General Public License for more details.                                               //
15 808ef3aa Leszek Koltunski
//                                                                                               //
16 c4d06f90 Leszek Koltunski
// You should have received a copy of the GNU Lesser General Public                              //
17
// License along with this library; if not, write to the Free Software                           //
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA                //
19 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
20
21
package org.distorted.library.mesh;
22
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24 8c57d77b Leszek Koltunski
25
import org.distorted.library.main.DistortedLibrary;
26
27 808ef3aa Leszek Koltunski
/**
28
 * Create a polygon of any shape and varying elevations from the edges towards the center.
29
 * <p>
30
 * Specify a list of vertices. Any two adjacent vertices + the center (0,0,0) form a triangle. The
31 2d732361 Leszek Koltunski
 * polygon is going to be split into such triangles, and each triangle is split into adjustable number
32 808ef3aa Leszek Koltunski
 * of 'bands' form the outer edge towards the center. Edges of each band can can at any elevation.
33
 */
34
public class MeshPolygon extends MeshBase
35
  {
36 b2913a86 Leszek Koltunski
  private static final int SHAPE_DD = 0;
37
  private static final int SHAPE_DU = 1;
38
  private static final int SHAPE_UD = 2;
39
  private static final int SHAPE_UU = 3;
40
  private static final int SHAPE_DUD= 4;
41
42 808ef3aa Leszek Koltunski
  private float[] mPolygonVertices;
43
  private int mNumPolygonVertices;
44
  private float[] mPolygonBands;
45
  private int mNumPolygonBands;
46 b2913a86 Leszek Koltunski
  private boolean[] mEdgeUp;
47 808ef3aa Leszek Koltunski
48
  private int remainingVert;
49
  private int numVertices;
50 d456b075 Leszek Koltunski
  private int extraIndex, extraVertices;
51 808ef3aa Leszek Koltunski
52 b2913a86 Leszek Koltunski
  //private float[] mBandQuot;
53 eeb5d115 Leszek Koltunski
54 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
55
// polygonVertices>=3 , polygonBands>=2
56
57 d456b075 Leszek Koltunski
  private void computeNumberOfVertices()
58 808ef3aa Leszek Koltunski
     {
59 fa640198 Leszek Koltunski
     if( mNumPolygonBands==2 && extraIndex>0 )
60
       {
61
       numVertices = 1 + 2*mNumPolygonVertices*(1+extraIndex+2*extraVertices);
62
       }
63
     else
64
       {
65
       numVertices = (mNumPolygonVertices*mNumPolygonBands+2)*(mNumPolygonBands-1) - 1;
66
       numVertices+= 2*mNumPolygonVertices*(2*extraIndex*extraVertices);
67
       }
68 d456b075 Leszek Koltunski
69 ac6a08e7 Leszek Koltunski
     remainingVert = numVertices;
70 808ef3aa Leszek Koltunski
     }
71 b2913a86 Leszek Koltunski
/*
72 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
73
74 eeb5d115 Leszek Koltunski
  private void computeCache()
75 808ef3aa Leszek Koltunski
    {
76 eeb5d115 Leszek Koltunski
    mBandQuot = new float[mNumPolygonBands];
77 ac6a08e7 Leszek Koltunski
78 eeb5d115 Leszek Koltunski
    int next, prev;
79 ac6a08e7 Leszek Koltunski
80 eeb5d115 Leszek Koltunski
    for(int band=0; band<mNumPolygonBands; band++)
81
      {
82
      next = (band==mNumPolygonBands-1 ? band : band+1);
83
      prev = (band==                 0 ? band : band-1);
84 ac6a08e7 Leszek Koltunski
85 eeb5d115 Leszek Koltunski
      mBandQuot[band] = (mPolygonBands[2*prev+1]-mPolygonBands[2*next+1]) / (mPolygonBands[2*next]-mPolygonBands[2*prev]);
86
      }
87
    }
88 b2913a86 Leszek Koltunski
*/
89 fa640198 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
90
91
  private float getSpecialQuot(int index)
92
    {
93
    int num = 1 + extraIndex + 2*extraVertices;
94
    int change1 = extraVertices+1;
95
    int change2 = num-change1;
96
    float quot = 1.0f/(extraIndex+1);
97
98
    if( index<change1 )      return index*quot/change1;
99
    else if( index>change2 ) return 1-quot + (index-change2)*quot/change1;
100
    else                     return (index-change1+1)*quot;
101
    }
102
103 eeb5d115 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
104 808ef3aa Leszek Koltunski
105 d456b075 Leszek Koltunski
  private float getQuot(int index, int band, boolean isExtra)
106 eeb5d115 Leszek Koltunski
    {
107 d456b075 Leszek Koltunski
    int num = mNumPolygonBands-1-band;
108 808ef3aa Leszek Koltunski
109 d456b075 Leszek Koltunski
    if( num>0 )
110
      {
111
      if( isExtra )
112
        {
113
        int extra = extraIndex-band+extraVertices;
114
115
        if( index < extra )
116
          {
117
          float quot = ((float)extraIndex-band)/(extra*num);
118
          return index*quot;
119
          }
120
        else if( index > num+2*extraVertices-extra )
121
          {
122
          float quot = ((float)extraIndex-band)/(extra*num);
123
          return (1.0f-((float)extraIndex-band)/num) + (index-num-2*extraVertices+extra)*quot;
124
          }
125
        else
126
          {
127
          return ((float)(index-extraVertices))/num;
128
          }
129
        }
130 808ef3aa Leszek Koltunski
131 d456b075 Leszek Koltunski
      return (float)index/num;
132
      }
133 808ef3aa Leszek Koltunski
134 d456b075 Leszek Koltunski
    return 1.0f;
135
    }
136
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138
139 b2913a86 Leszek Koltunski
  private float computeZEdge(float quot)
140
    {
141
    if( quot>=1.0f ) return 0.0f;
142
143
    for(int band=1; band<mNumPolygonBands; band++)
144
      {
145
      float curr = mPolygonBands[2*band];
146
147
      if( curr<=quot )
148
        {
149
        float prev = mPolygonBands[2*band-2];
150
        float prevH= mPolygonBands[2*band-1];
151
        float currH= mPolygonBands[2*band+1];
152
153
        float A = (prev-quot)/(prev-curr);
154
155
        return A*currH + (1-A)*prevH;
156
        }
157
      }
158
159
    return 0.0f;
160
    }
161
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163
164
  private int addVertex(int vertex, int polyBand, int polyVertex, int polyEndVer, float quot,
165
                        int edgeShape, float[] attribs1, float[] attribs2)
166 d456b075 Leszek Koltunski
    {
167
    remainingVert--;
168
169 eeb5d115 Leszek Koltunski
    float Xfirst= mPolygonVertices[2*polyVertex  ];
170
    float Yfirst= mPolygonVertices[2*polyVertex+1];
171
    float Xlast = mPolygonVertices[2*polyEndVer  ];
172
    float Ylast = mPolygonVertices[2*polyEndVer+1];
173 808ef3aa Leszek Koltunski
174 eeb5d115 Leszek Koltunski
    float xEdge = Xfirst + quot*(Xlast-Xfirst);
175
    float yEdge = Yfirst + quot*(Ylast-Yfirst);
176 b2913a86 Leszek Koltunski
    float zEdge;
177 808ef3aa Leszek Koltunski
178 b2913a86 Leszek Koltunski
    switch(edgeShape)
179 ac6a08e7 Leszek Koltunski
      {
180 b2913a86 Leszek Koltunski
      case SHAPE_DD : zEdge = 0.0f;
181
                      break;
182
      case SHAPE_UU : zEdge = mPolygonBands[2*mNumPolygonBands-1];
183
                      break;
184
      case SHAPE_DU : zEdge = quot>=0.5f ? mPolygonBands[2*mNumPolygonBands-1] : computeZEdge(1-2*quot);
185
                      break;
186
      case SHAPE_UD : zEdge = quot<=0.5f ? mPolygonBands[2*mNumPolygonBands-1] : computeZEdge(2*quot-1);
187
                      break;
188
      default       : zEdge = quot<=0.5f ? computeZEdge(1-2*quot) : computeZEdge(2*quot-1);
189
                      break;
190 eeb5d115 Leszek Koltunski
      }
191 ac6a08e7 Leszek Koltunski
192 b2913a86 Leszek Koltunski
    float q =  mPolygonBands[2*polyBand];
193
194
    float x = q*xEdge;
195
    float y = q*yEdge;
196
    float z = q*zEdge + mPolygonBands[2*polyBand+1];
197 ac6a08e7 Leszek Koltunski
198 eeb5d115 Leszek Koltunski
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB  ] = x;
199
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+1] = y;
200 b2913a86 Leszek Koltunski
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+2] = z;
201 eeb5d115 Leszek Koltunski
202
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB  ] = x+0.5f;
203
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB+1] = y+0.5f;
204 808ef3aa Leszek Koltunski
205
    return vertex+1;
206
    }
207
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209
210 b2913a86 Leszek Koltunski
  private void addVertexNormal(int vertex, int end1, int end2, float[] attribs1)
211
    {
212
    android.util.Log.e("D", "vertex="+vertex+" end1="+end1+" end2="+end2);
213
214
    int iv = VERT1_ATTRIBS*vertex + POS_ATTRIB;
215
    int i1 = VERT1_ATTRIBS*end1   + POS_ATTRIB;
216
    int i2 = VERT1_ATTRIBS*end2   + POS_ATTRIB;
217
218
    float vx = attribs1[iv  ];
219
    float vy = attribs1[iv+1];
220
    float vz = attribs1[iv+2];
221
222
    float x1 = attribs1[i1  ];
223
    float y1 = attribs1[i1+1];
224
    float z1 = attribs1[i1+2];
225
226
    float x2 = attribs1[i2  ];
227
    float y2 = attribs1[i2+1];
228
    float z2 = attribs1[i2+2];
229
230
    float dx1 = vx-x1;
231
    float dy1 = vy-y1;
232
    float dz1 = vz-z1;
233
234
    float dx2 = vx-x2;
235
    float dy2 = vy-y2;
236
    float dz2 = vz-z2;
237
238
    float cx = dy1*dz2 - dz1*dy2;
239
    float cy = dz1*dx2 - dx1*dz2;
240
    float cz = dx1*dy2 - dy1*dx2;
241
242
    float len = (float)Math.sqrt(cx*cx + cy*cy + cz*cz);
243
244
    int index = VERT1_ATTRIBS*vertex + NOR_ATTRIB;
245
246
    attribs1[index  ] = cx/len;
247
    attribs1[index+1] = cy/len;
248
    attribs1[index+2] = cz/len;
249
    }
250
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252
253
  private int createBandStrip(int vertex, int polyBand, int polyVertex, int edgeShape, float[] attribs1, float[] attribs2)
254 808ef3aa Leszek Koltunski
    {
255 b2913a86 Leszek Koltunski
    int initVertex = vertex;
256
257 808ef3aa Leszek Koltunski
    if( polyVertex==0 )
258
      {
259 b2913a86 Leszek Koltunski
      vertex = addVertex(vertex,polyBand,0,1,0,edgeShape,attribs1,attribs2);
260
      if( polyBand>0 ) vertex = addVertex(vertex,polyBand,0,1,0,edgeShape,attribs1,attribs2);
261 808ef3aa Leszek Koltunski
      }
262
263 fa640198 Leszek Koltunski
    boolean specialCase = mNumPolygonBands==2 && polyBand==0 && extraIndex>0;
264 d456b075 Leszek Koltunski
    boolean isExtra = polyBand<extraIndex;
265 fa640198 Leszek Koltunski
    int numPairs = specialCase ? extraIndex+1 : mNumPolygonBands-1-polyBand;
266
    if( isExtra ) numPairs += 2*extraVertices;
267 d456b075 Leszek Koltunski
268 eeb5d115 Leszek Koltunski
    int polyEndVer = polyVertex==mNumPolygonVertices-1 ? 0 : polyVertex+1;
269 d456b075 Leszek Koltunski
    float quot1, quot2;
270 808ef3aa Leszek Koltunski
271 eeb5d115 Leszek Koltunski
    for(int index=0; index<numPairs; index++)
272 808ef3aa Leszek Koltunski
      {
273 fa640198 Leszek Koltunski
      if( specialCase )
274
        {
275
        quot1 = 1.0f;
276
        quot2 = getSpecialQuot(index+1);
277
        }
278
      else
279
        {
280
        quot1 = getQuot(index  ,polyBand+1, isExtra);
281
        quot2 = getQuot(index+1,polyBand  , isExtra);
282
        }
283 d456b075 Leszek Koltunski
284 b2913a86 Leszek Koltunski
      vertex = addVertex(vertex,polyBand+1,polyVertex,polyEndVer,quot1,edgeShape,attribs1,attribs2);
285
      vertex = addVertex(vertex,polyBand  ,polyVertex,polyEndVer,quot2,edgeShape,attribs1,attribs2);
286
      }
287
288
    if( polyVertex==0 )
289
      {
290
      if( polyBand>0 ) addVertexNormal(initVertex,initVertex+3,initVertex+2,attribs1);
291
      else             addVertexNormal(initVertex,initVertex+2,initVertex+1,attribs1);
292
      }
293
    else
294
      {
295
      addVertexNormal(initVertex,initVertex-1,initVertex+1,attribs1);
296
      }
297
298
    boolean lower = (polyVertex>0 || polyBand>0);
299
300
    for(int index=initVertex+1; index<vertex-1; index++)
301
      {
302
      addVertexNormal(index,(lower ? index+2 : index-1),index+1,attribs1);
303
      lower = !lower;
304 808ef3aa Leszek Koltunski
      }
305
306 b2913a86 Leszek Koltunski
    addVertexNormal(vertex-1,vertex-2,vertex-3,attribs1);
307
308 808ef3aa Leszek Koltunski
    return vertex;
309
    }
310
311 b2913a86 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
312
313
  private int computeEdgeShape(int curr)
314
    {
315
    if( mEdgeUp==null || !mEdgeUp[curr] ) return SHAPE_DD;
316
317
    int prev = (curr==0 ? mNumPolygonVertices-1 : curr-1);
318
    int next = (curr==mNumPolygonVertices-1 ? 0 : curr+1);
319
320
    boolean l = mEdgeUp[prev];
321
    boolean r = mEdgeUp[next];
322
323
    return l ? (r ? SHAPE_UU : SHAPE_UD) : (r ? SHAPE_DU : SHAPE_DUD);
324
    }
325
326 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
327
328
  private void buildGrid(float[] attribs1, float[] attribs2)
329
    {
330
    int vertex=0;
331
332 b2913a86 Leszek Koltunski
    int[] edgeShape = new int[mNumPolygonVertices];
333
334
    for(int polyVertex=0; polyVertex<mNumPolygonVertices; polyVertex++)
335
      edgeShape[polyVertex] = computeEdgeShape(polyVertex);
336
337 ac6a08e7 Leszek Koltunski
    for(int polyBand=0; polyBand<mNumPolygonBands-1; polyBand++)
338 808ef3aa Leszek Koltunski
      for(int polyVertex=0; polyVertex<mNumPolygonVertices; polyVertex++)
339
        {
340 b2913a86 Leszek Koltunski
        android.util.Log.e("D", "creating strip polyBand="+polyBand+" polyVertex="+polyVertex+" : "+vertex);
341
        vertex = createBandStrip(vertex,polyBand,polyVertex,edgeShape[polyVertex],attribs1,attribs2);
342
        android.util.Log.e("D", "  "+vertex);
343 808ef3aa Leszek Koltunski
        }
344
    }
345
346
///////////////////////////////////////////////////////////////////////////////////////////////////
347
// PUBLIC API
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349
/**
350
 * Create a polygon of any shape and varying elevations from the edges towards the center.
351 d456b075 Leszek Koltunski
 * Optionally make it more dense at the vertices.
352 808ef3aa Leszek Koltunski
 *
353
 * @param verticesXY 2N floats - packed description of polygon vertices. N pairs (x,y).
354 8b082b9f Leszek Koltunski
 *                   Vertices HAVE TO be specified in a COUNTERCLOCKWISE order (starting from any).
355 808ef3aa Leszek Koltunski
 * @param bands      2K floats; K pairs of two floats each describing a single band.
356
 *                   From (1.0,Z[0]) (outer edge, its Z elevation) to (0.0,Z[K]) (the center,
357
 *                   its elevation). The polygon is split into such concentric bands.
358 ac6a08e7 Leszek Koltunski
 *                   Must be band[2*i] > band[2*(i+1)] !
359 b2913a86 Leszek Koltunski
 * @param edgeUp     N booleans - one for each edge; the first connects vertices (0,1) and (2,3);
360
 *                   then just like 'verticesXY', i.e. counterclockwise.
361
 *                   If this is null, all edges are by default 'down'.
362
 *                   'Down' means that edge's Z is equal to 0; 'up' means that its Z, at least in its
363
 *                   middle, is equal to the highest elevation in the middle of the mesh.
364
 *                   If the 'previous' edge is also up, then the Z is up horizontally from its middle
365
 *                   to the left vertex; else it goes down along the same function it goes along the bands.
366
 *                   Same with the right half of the edge.
367 d456b075 Leszek Koltunski
 * @param exIndex    This and the next parameter describe how to make the mesh denser at the
368
 *                   polyVertices. If e.g. exIndex=3 and exVertices=2, then 3 triangles of the
369 f4a2d97e Leszek Koltunski
 *                   outermost band (and 2 triangles of the next band, and 1 triangle of the third
370 d456b075 Leszek Koltunski
 *                   band) get denser - the 3 triangles become 3+2 = 5.
371
 * @param exVertices See above.
372 0b732630 Leszek Koltunski
 * @param centerX    the X coordinate of the 'center' of the Polygon, i.e. point of the mesh
373
 *                   all bands go to.
374
 * @param centerY    Y coordinate of the center.
375 808ef3aa Leszek Koltunski
 */
376 b2913a86 Leszek Koltunski
  public MeshPolygon(float[] verticesXY, float[] bands, boolean[] edgeUp, int exIndex, int exVertices, float centerX, float centerY)
377 808ef3aa Leszek Koltunski
    {
378
    super();
379
380 d456b075 Leszek Koltunski
    mPolygonVertices   = verticesXY;
381
    mPolygonBands      = bands;
382
    mNumPolygonVertices= mPolygonVertices.length /2;
383
    mNumPolygonBands   = mPolygonBands.length /2;
384 b2913a86 Leszek Koltunski
    mEdgeUp            = edgeUp;
385 d456b075 Leszek Koltunski
    extraIndex         = exIndex;
386
    extraVertices      = exVertices;
387 808ef3aa Leszek Koltunski
388 0b732630 Leszek Koltunski
    if( centerX!=0.0f || centerY!=0.0f )
389
      {
390
      for(int v=0; v<mNumPolygonVertices; v++)
391
        {
392
        mPolygonVertices[2*v  ] -= centerX;
393
        mPolygonVertices[2*v+1] -= centerY;
394
        }
395
      }
396
397 d456b075 Leszek Koltunski
    computeNumberOfVertices();
398 b2913a86 Leszek Koltunski
    //computeCache();
399 808ef3aa Leszek Koltunski
400
    float[] attribs1= new float[VERT1_ATTRIBS*numVertices];
401
    float[] attribs2= new float[VERT2_ATTRIBS*numVertices];
402
403
    buildGrid(attribs1,attribs2);
404
405
    if( remainingVert!=0 )
406 8c57d77b Leszek Koltunski
      DistortedLibrary.logMessage("MeshPolygon: remainingVert " +remainingVert );
407 808ef3aa Leszek Koltunski
408 0b732630 Leszek Koltunski
    if( centerX!=0.0f || centerY!=0.0f )
409
      {
410
      for(int v=0; v<numVertices; v++)
411
        {
412
        attribs1[VERT1_ATTRIBS*v + POS_ATTRIB  ] += centerX;
413
        attribs1[VERT1_ATTRIBS*v + POS_ATTRIB+1] += centerY;
414
        attribs2[VERT2_ATTRIBS*v + TEX_ATTRIB  ] += centerX;
415
        attribs2[VERT2_ATTRIBS*v + TEX_ATTRIB+1] += centerY;
416
        }
417
      }
418
419 808ef3aa Leszek Koltunski
    setAttribs(attribs1,attribs2);
420
    }
421
422 0b732630 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
423
424
  public MeshPolygon(float[] verticesXY, float[] bands, int exIndex, int exVertices)
425
    {
426 b2913a86 Leszek Koltunski
    this(verticesXY,bands,null,exIndex,exVertices,0.0f,0.0f);
427 0b732630 Leszek Koltunski
    }
428
429 d456b075 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
430
/**
431
 * Create a polygon of any shape and varying elevations from the edges towards the center.
432
 * Equivalent of the previous with exIndex=0 or exVertices=0.
433
 */
434
  public MeshPolygon(float[] verticesXY, float[] bands)
435
    {
436 b2913a86 Leszek Koltunski
    this(verticesXY,bands,null,0,0,0.0f,0.0f);
437 d456b075 Leszek Koltunski
    }
438
439 808ef3aa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
440
/**
441
 * Copy constructor.
442
 */
443
  public MeshPolygon(MeshPolygon mesh, boolean deep)
444
    {
445
    super(mesh,deep);
446
    }
447
448
///////////////////////////////////////////////////////////////////////////////////////////////////
449
/**
450
 * Copy the Mesh.
451
 *
452
 * @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices,
453
 *             normals and inflates (the rest, in particular the mVertAttribs2 containing texture
454
 *             coordinates and effect associations, is always deep copied)
455
 */
456
  public MeshPolygon copy(boolean deep)
457
    {
458
    return new MeshPolygon(this,deep);
459
    }
460
 }