Project

General

Profile

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

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

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski  leszek@koltunski.pl                                          //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// 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
//                                                                                               //
11
// This library 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 GNU                             //
14
// Lesser General Public License for more details.                                               //
15
//                                                                                               //
16
// 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
///////////////////////////////////////////////////////////////////////////////////////////////////
20

    
21
package org.distorted.library.mesh;
22

    
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

    
25
import org.distorted.library.main.DistortedLibrary;
26

    
27
/**
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
 * polygon is going to be split into such triangles, and each triangle is split into adjustable number
32
 * 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
  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
  private float[] mPolygonVertices;
43
  private int mNumPolygonVertices;
44
  private float[] mPolygonBands;
45
  private int mNumPolygonBands;
46
  private boolean[] mEdgeUp;
47

    
48
  private int remainingVert;
49
  private int numVertices;
50
  private int extraIndex, extraVertices;
51

    
52
  //private float[] mBandQuot;
53

    
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55
// polygonVertices>=3 , polygonBands>=2
56

    
57
  private void computeNumberOfVertices()
58
     {
59
     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

    
69
     remainingVert = numVertices;
70
     }
71
/*
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73

    
74
  private void computeCache()
75
    {
76
    mBandQuot = new float[mNumPolygonBands];
77

    
78
    int next, prev;
79

    
80
    for(int band=0; band<mNumPolygonBands; band++)
81
      {
82
      next = (band==mNumPolygonBands-1 ? band : band+1);
83
      prev = (band==                 0 ? band : band-1);
84

    
85
      mBandQuot[band] = (mPolygonBands[2*prev+1]-mPolygonBands[2*next+1]) / (mPolygonBands[2*next]-mPolygonBands[2*prev]);
86
      }
87
    }
88
*/
89
///////////////////////////////////////////////////////////////////////////////////////////////////
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
///////////////////////////////////////////////////////////////////////////////////////////////////
104

    
105
  private float getQuot(int index, int band, boolean isExtra)
106
    {
107
    int num = mNumPolygonBands-1-band;
108

    
109
    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

    
131
      return (float)index/num;
132
      }
133

    
134
    return 1.0f;
135
    }
136

    
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

    
139
  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
    {
167
    remainingVert--;
168

    
169
    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

    
174
    float xEdge = Xfirst + quot*(Xlast-Xfirst);
175
    float yEdge = Yfirst + quot*(Ylast-Yfirst);
176
    float zEdge;
177

    
178
    switch(edgeShape)
179
      {
180
      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
      }
191

    
192
    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

    
198
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB  ] = x;
199
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+1] = y;
200
    attribs1[VERT1_ATTRIBS*vertex + POS_ATTRIB+2] = z;
201

    
202
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB  ] = x+0.5f;
203
    attribs2[VERT2_ATTRIBS*vertex + TEX_ATTRIB+1] = y+0.5f;
204

    
205
    return vertex+1;
206
    }
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

    
210
  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
    {
255
    int initVertex = vertex;
256

    
257
    if( polyVertex==0 )
258
      {
259
      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
      }
262

    
263
    boolean specialCase = mNumPolygonBands==2 && polyBand==0 && extraIndex>0;
264
    boolean isExtra = polyBand<extraIndex;
265
    int numPairs = specialCase ? extraIndex+1 : mNumPolygonBands-1-polyBand;
266
    if( isExtra ) numPairs += 2*extraVertices;
267

    
268
    int polyEndVer = polyVertex==mNumPolygonVertices-1 ? 0 : polyVertex+1;
269
    float quot1, quot2;
270

    
271
    for(int index=0; index<numPairs; index++)
272
      {
273
      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

    
284
      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
      }
305

    
306
    addVertexNormal(vertex-1,vertex-2,vertex-3,attribs1);
307

    
308
    return vertex;
309
    }
310

    
311
///////////////////////////////////////////////////////////////////////////////////////////////////
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
///////////////////////////////////////////////////////////////////////////////////////////////////
327

    
328
  private void buildGrid(float[] attribs1, float[] attribs2)
329
    {
330
    int vertex=0;
331

    
332
    int[] edgeShape = new int[mNumPolygonVertices];
333

    
334
    for(int polyVertex=0; polyVertex<mNumPolygonVertices; polyVertex++)
335
      edgeShape[polyVertex] = computeEdgeShape(polyVertex);
336

    
337
    for(int polyBand=0; polyBand<mNumPolygonBands-1; polyBand++)
338
      for(int polyVertex=0; polyVertex<mNumPolygonVertices; polyVertex++)
339
        {
340
        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
        }
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
 * Optionally make it more dense at the vertices.
352
 *
353
 * @param verticesXY 2N floats - packed description of polygon vertices. N pairs (x,y).
354
 *                   Vertices HAVE TO be specified in a COUNTERCLOCKWISE order (starting from any).
355
 * @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
 *                   Must be band[2*i] > band[2*(i+1)] !
359
 * @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
 * @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
 *                   outermost band (and 2 triangles of the next band, and 1 triangle of the third
370
 *                   band) get denser - the 3 triangles become 3+2 = 5.
371
 * @param exVertices See above.
372
 * @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
 */
376
  public MeshPolygon(float[] verticesXY, float[] bands, boolean[] edgeUp, int exIndex, int exVertices, float centerX, float centerY)
377
    {
378
    super();
379

    
380
    mPolygonVertices   = verticesXY;
381
    mPolygonBands      = bands;
382
    mNumPolygonVertices= mPolygonVertices.length /2;
383
    mNumPolygonBands   = mPolygonBands.length /2;
384
    mEdgeUp            = edgeUp;
385
    extraIndex         = exIndex;
386
    extraVertices      = exVertices;
387

    
388
    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
    computeNumberOfVertices();
398
    //computeCache();
399

    
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
      DistortedLibrary.logMessage("MeshPolygon: remainingVert " +remainingVert );
407

    
408
    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
    setAttribs(attribs1,attribs2);
420
    }
421

    
422
///////////////////////////////////////////////////////////////////////////////////////////////////
423

    
424
  public MeshPolygon(float[] verticesXY, float[] bands, int exIndex, int exVertices)
425
    {
426
    this(verticesXY,bands,null,exIndex,exVertices,0.0f,0.0f);
427
    }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
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
    this(verticesXY,bands,null,0,0,0.0f,0.0f);
437
    }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
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
 }
(6-6/10)