Project

General

Profile

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

library / src / main / java / org / distorted / library / mesh / MeshMultigon.java @ bc6adbb5

1 b1bfcdc7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 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 a60f7acf Leszek Koltunski
import java.util.ArrayList;
24
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26
27 b1bfcdc7 Leszek Koltunski
/**
28
 * Create a 'multigon' mesh - a union of several polygons.
29
 *
30
 * <p>
31
 * Specify several lists of vertices. Each list defines one polygon. (@see MeshPolygon).
32
 * If two such polygons share an edge (or several edges) then the edge in both of them is
33
 * marked 'up'.
34
 */
35
public class MeshMultigon extends MeshBase
36
  {
37 898ff658 leszek
  private static final float MAX_ERROR = 0.000001f;
38 9ee850c5 leszek
  private float[][][] mOuterAndHoleVertices;
39
  private float[][][] mEdgeVectors;
40 b1bfcdc7 Leszek Koltunski
41 a60f7acf Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
42
43 9ee850c5 leszek
  private static boolean isSame(float dx, float dy)
44 b1bfcdc7 Leszek Koltunski
    {
45
    return (dx*dx + dy*dy < MAX_ERROR);
46
    }
47
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49
50 bc6adbb5 leszek
  private static int isUp(float[][][] vertices, int polygon, int edge)
51 b1bfcdc7 Leszek Koltunski
    {
52 bc6adbb5 leszek
    float[][] p= vertices[polygon];
53
    int lenP = p.length;
54 b1bfcdc7 Leszek Koltunski
    int len  = vertices.length;
55
    int next = (edge==lenP-1 ? 0 : edge+1);
56
57 bc6adbb5 leszek
    float v1x = p[edge][0];
58
    float v1y = p[edge][1];
59
    float v2x = p[next][0];
60
    float v2y = p[next][1];
61 a60f7acf Leszek Koltunski
62 b1bfcdc7 Leszek Koltunski
    for(int i=0; i<len; i++)
63
      if( i!=polygon )
64
        {
65 bc6adbb5 leszek
        int num = vertices[i].length;
66 b1bfcdc7 Leszek Koltunski
67
        for(int j=0; j<num; j++)
68
          {
69
          int n = (j==num-1 ? 0 : j+1);
70 bc6adbb5 leszek
          float[][] v = vertices[i];
71
          float x1 = v[j][0];
72
          float y1 = v[j][1];
73
          float x2 = v[n][0];
74
          float y2 = v[n][1];
75 a60f7acf Leszek Koltunski
76 46ef24e5 leszek
          if( isSame(v2x-x1,v2y-y1) && isSame(v1x-x2,v1y-y2) ) return i;
77 b1bfcdc7 Leszek Koltunski
          }
78
        }
79
80 46ef24e5 leszek
    return -1;
81 b1bfcdc7 Leszek Koltunski
    }
82
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84
85 bc6adbb5 leszek
  private static float[] detectFirstOuterVertex(float[][][] vertices)
86 a60f7acf Leszek Koltunski
    {
87
    float X = -Float.MAX_VALUE;
88
    int I=0,J=0, len = vertices.length;
89
90
    for(int i=0; i<len; i++ )
91 b1bfcdc7 Leszek Koltunski
      {
92 bc6adbb5 leszek
      float[][] v = vertices[i];
93
      int num = v.length;
94 a60f7acf Leszek Koltunski
95
      for(int j=0; j<num; j++)
96 bc6adbb5 leszek
        if( v[j][0]>X )
97 a60f7acf Leszek Koltunski
          {
98 bc6adbb5 leszek
          X = v[j][0];
99 a60f7acf Leszek Koltunski
          I = i;
100
          J = j;
101
          }
102
      }
103
104 bc6adbb5 leszek
    float[] v = vertices[I][J];
105
    return new float[] {v[0],v[1]};
106 a60f7acf Leszek Koltunski
    }
107
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109
110 9ee850c5 leszek
  private static double computeAngle(float x1,float y1, float x2, float y2)
111 a60f7acf Leszek Koltunski
    {
112
    double diff = Math.atan2(y2,x2)-Math.atan2(y1,x1);
113
    return diff<0 ? diff+(2*Math.PI) : diff;
114
    }
115
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117
118 bc6adbb5 leszek
  private static float[] detectNextOuterVertex(float[][][] vertices, float[] curr, float[] vect, int[][] edgesUp)
119 a60f7acf Leszek Koltunski
    {
120 9ee850c5 leszek
    double maxAngle = 0;
121 a60f7acf Leszek Koltunski
    float x=0, y=0;
122 9ee850c5 leszek
    int numC = vertices.length;
123 a60f7acf Leszek Koltunski
124 9ee850c5 leszek
    for( int c=0; c<numC; c++ )
125 a60f7acf Leszek Koltunski
      {
126 bc6adbb5 leszek
      float[][] vert = vertices[c];
127
      int numV = vert.length;
128 a60f7acf Leszek Koltunski
129 9ee850c5 leszek
      for( int v=0; v<numV; v++)
130 fceaa116 Leszek Koltunski
        {
131 bc6adbb5 leszek
        float xc = vert[v][0];
132
        float yc = vert[v][1];
133 a60f7acf Leszek Koltunski
134 9ee850c5 leszek
        if( edgesUp[c][v]<0 && isSame(xc-curr[0],yc-curr[1]) )
135 a60f7acf Leszek Koltunski
          {
136 9ee850c5 leszek
          int n = (v==numV-1 ? 0 : v+1);
137 bc6adbb5 leszek
          float xn = vert[n][0];
138
          float yn = vert[n][1];
139 a60f7acf Leszek Koltunski
140
          double angle = computeAngle(vect[0], vect[1], xn-xc, yn-yc);
141
142 9ee850c5 leszek
          if (angle > maxAngle)
143 a60f7acf Leszek Koltunski
            {
144 9ee850c5 leszek
            maxAngle = angle;
145 a60f7acf Leszek Koltunski
            x = xn;
146
            y = yn;
147
            }
148 fceaa116 Leszek Koltunski
149 a60f7acf Leszek Koltunski
          break;
150
          }
151 fceaa116 Leszek Koltunski
        }
152 b1bfcdc7 Leszek Koltunski
      }
153
154 a60f7acf Leszek Koltunski
    return new float[] {x,y};
155
    }
156
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158
159 bc6adbb5 leszek
  private static int getNextIndex(float[][][] vertices, int[][] unclaimedEdges, int currIndex, int numHoleVerts)
160 f835cc50 leszek
    {
161 9ee850c5 leszek
    int[] currEdge = unclaimedEdges[currIndex];
162
    int currP = currEdge[0];
163
    int currE = currEdge[1];
164 bc6adbb5 leszek
    float[][] polygon = vertices[currP];
165
    int numV = polygon.length;
166 9ee850c5 leszek
    int nextE= currE<numV-1 ? currE+1 : 0;
167 f835cc50 leszek
168 bc6adbb5 leszek
    float x = polygon[nextE][0];
169
    float y = polygon[nextE][1];
170 9ee850c5 leszek
171
    for(int e=0; e<numHoleVerts; e++)
172 f835cc50 leszek
      {
173 9ee850c5 leszek
      int[] edge = unclaimedEdges[e];
174 f835cc50 leszek
175 9ee850c5 leszek
      if( edge[2]==1 )
176
        {
177
        int po = edge[0];
178
        int ed = edge[1];
179 f835cc50 leszek
180 bc6adbb5 leszek
        float cx = vertices[po][ed][0];
181
        float cy = vertices[po][ed][1];
182 f835cc50 leszek
183 9ee850c5 leszek
        if( isSame(cx-x,cy-y) )
184
          {
185
          edge[2] = 0;
186
          return e;
187
          }
188
        }
189 f835cc50 leszek
      }
190 9ee850c5 leszek
191
    return -1;
192 f835cc50 leszek
    }
193
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195
196 bc6adbb5 leszek
  private static int generateHole(float[][][] vertices, int[][] unclaimedEdges, float[][] output, int[][] edgesUp, int holeNumber, int numHoleVerts)
197 a60f7acf Leszek Koltunski
    {
198 9ee850c5 leszek
    int firstIndex=-1;
199 a60f7acf Leszek Koltunski
200 9ee850c5 leszek
    for(int e=0; e<numHoleVerts; e++)
201
      if( unclaimedEdges[e][2]==1 )
202
        {
203
        firstIndex = e;
204
        break;
205
        }
206 a60f7acf Leszek Koltunski
207 9ee850c5 leszek
    int currIndex = firstIndex;
208
    int nextIndex=-1;
209
    int numAdded = 0;
210
211
    while( nextIndex!=firstIndex )
212 a60f7acf Leszek Koltunski
      {
213 9ee850c5 leszek
      nextIndex = getNextIndex(vertices,unclaimedEdges,currIndex,numHoleVerts);
214
215
      int p = unclaimedEdges[nextIndex][0];
216
      int v = unclaimedEdges[nextIndex][1];
217
      edgesUp[p][v] = -holeNumber-2;
218
      currIndex = nextIndex;
219
      int[] e = unclaimedEdges[nextIndex];
220 bc6adbb5 leszek
      float[] ve = vertices[e[0]][e[1]];
221
      output[numAdded][0] = ve[0];
222
      output[numAdded][1] = ve[1];
223 9ee850c5 leszek
      numAdded++;
224 a60f7acf Leszek Koltunski
      }
225
226 9ee850c5 leszek
    return numAdded;
227
    }
228
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230
231
  private static boolean doesNotBelongToOuter(float x, float y, float[][] outer)
232
    {
233
    for(float[] v : outer)
234
      if(isSame(x-v[0], y-v[1])) return false;
235
236
    return true;
237
    }
238
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240
241 bc6adbb5 leszek
  private static float[][][] computeHoles(float[][][] vertices, int[][] edgesUp, float[][] outer, int numHoleVerts)
242 9ee850c5 leszek
    {
243
    int[][] unclaimedEdges = new int[numHoleVerts][];
244
    int index = 0;
245
    int numPoly = vertices.length;
246
247
    for(int p=0; p<numPoly; p++)
248
      {
249 bc6adbb5 leszek
      float[][] ve = vertices[p];
250
      int numEdges = ve.length;
251 9ee850c5 leszek
252
      for(int e=0; e<numEdges; e++)
253
        if( edgesUp[p][e]<0 )
254
          {
255 bc6adbb5 leszek
          float x1 = ve[e][0];
256
          float y1 = ve[e][1];
257 9ee850c5 leszek
258
          int n = e<numEdges-1 ? e+1 : 0;
259 bc6adbb5 leszek
          float x2 = ve[n][0];
260
          float y2 = ve[n][1];
261 9ee850c5 leszek
262
          // yes, we need to check both ends of the edge - otherwise the
263
          // following 3x3 situation (x - wall, o - hole ) does not work:
264
          // x x x
265
          // x o x
266
          // o x x
267
268
          if( doesNotBelongToOuter(x1,y1,outer) || doesNotBelongToOuter(x2,y2,outer) )
269
            {
270
            unclaimedEdges[index]=new int[] {p, e, 1};
271
            index++;
272
            }
273
          }
274
      }
275
276
    int remaining = numHoleVerts;
277
    ArrayList<float[][]> holes = new ArrayList<>();
278
    float[][] output = new float[numHoleVerts][2];
279
    int numHoles = 0;
280
281
    while(remaining>0)
282
      {
283
      int num = generateHole(vertices,unclaimedEdges,output,edgesUp,numHoles,numHoleVerts);
284
      remaining -= num;
285
      numHoles++;
286
287
      float[][] hole = new float[num][2];
288
      for(int h=0; h<num; h++)
289
        {
290
        hole[h][0] = output[h][0];
291
        hole[h][1] = output[h][1];
292
        }
293
294
      holes.add(hole);
295
      }
296
297
    float[][][] ret = new float[numHoles][][];
298
    for(int h=0; h<numHoles; h++) ret[h] = holes.remove(0);
299
300
    return ret;
301
    }
302
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304
305
  private static int countEdgesDown(int[][] edgesUp)
306
    {
307
    int numEdgesDown = 0;
308
309
    for(int[] edgeUp : edgesUp)
310
      for(int edge : edgeUp)
311
        if( edge<0 ) numEdgesDown++;
312
313
    return numEdgesDown;
314
    }
315
316
///////////////////////////////////////////////////////////////////////////////////////////////////
317
318 bc6adbb5 leszek
  private float[] produceNormalVector(float[][] outerAndHole, float xs, float ys)
319 9ee850c5 leszek
    {
320 bc6adbb5 leszek
    int vCurr,len = outerAndHole.length;
321 9ee850c5 leszek
322
    for(vCurr=0; vCurr<len; vCurr++)
323
      {
324 bc6adbb5 leszek
      float[] vs = outerAndHole[vCurr];
325 9ee850c5 leszek
      if( isSame(vs[0]-xs,vs[1]-ys) ) break;
326
      }
327
328
    if( vCurr==len ) android.util.Log.e("D", "ERROR in produceNormalVector!!");
329
330
    int vPrev = vCurr==0 ? len-1 : vCurr-1;
331
    int vNext = vCurr>=len-1 ? 0 : vCurr+1;
332 bc6adbb5 leszek
    float[] vp = outerAndHole[vPrev];
333
    float[] vn = outerAndHole[vNext];
334 9ee850c5 leszek
335
    return new float[] { vp[1]-vn[1], vn[0]-vp[0] };
336 a60f7acf Leszek Koltunski
    }
337
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339
340 bc6adbb5 leszek
  private float[] produceNormalVector(float[][] outerAndHole, float xs, float ys, float xe, float ye)
341 a60f7acf Leszek Koltunski
    {
342 bc6adbb5 leszek
    int vCurr,len = outerAndHole.length;
343 9ee850c5 leszek
344
    for(vCurr=0; vCurr<len; vCurr++)
345 f835cc50 leszek
      {
346 bc6adbb5 leszek
      float[] vs = outerAndHole[vCurr];
347 9ee850c5 leszek
348
      if( isSame(vs[0]-xs,vs[1]-ys) )
349
        {
350
        int vNext = vCurr==len-1 ? 0 : vCurr+1;
351 bc6adbb5 leszek
        float[] ve = outerAndHole[vNext];
352 9ee850c5 leszek
        if( isSame(ve[0]-xe,ve[1]-ye) ) break;
353
        }
354
      }
355
356
    int vPrev = vCurr==0 ? len-1 : vCurr-1;
357
    int vNext = vCurr>=len-1 ? 0 : vCurr+1;
358 bc6adbb5 leszek
    float[] vp = outerAndHole[vPrev];
359
    float[] vn = outerAndHole[vNext];
360 9ee850c5 leszek
361
    return new float[] { vp[1]-vn[1], vn[0]-vp[0] };
362
    }
363
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365
366 bc6adbb5 leszek
  private void computeEdgeVectors(float[][][] vertices, int[][] edgesUp)
367 9ee850c5 leszek
    {
368 bc6adbb5 leszek
    int numPoly = vertices.length;
369
    mEdgeVectors = new float[numPoly][][];
370 9ee850c5 leszek
371 bc6adbb5 leszek
    for(int c=0; c<numPoly; c++)
372 9ee850c5 leszek
      {
373 bc6adbb5 leszek
      float[][] polygon = vertices[c];
374
      int numV = polygon.length;
375 9ee850c5 leszek
      mEdgeVectors[c] = new float[numV][];
376
377
      for(int v=0; v<numV; v++)
378
        {
379
        int edgeUp = edgesUp[c][v];
380 bc6adbb5 leszek
        float xs = polygon[v][0];
381
        float ys = polygon[v][1];
382 9ee850c5 leszek
        int n = v==numV-1 ? 0 : v+1;
383 bc6adbb5 leszek
        float xe = polygon[n][0];
384
        float ye = polygon[n][1];
385 9ee850c5 leszek
386
        if( edgeUp<0 ) // external edge, normal vector
387
          {
388
          float[][] verts = mOuterAndHoleVertices[-edgeUp-1];
389
          mEdgeVectors[c][v] = produceNormalVector(verts,xs,ys,xe,ye);
390
          }
391
        else // internal edge - but the vertex that begins it might still be outer!
392
          {
393
          int numComp = retIndexBelongs(xs,ys);
394
395
          if( numComp<0 ) mEdgeVectors[c][v] = null;
396
          else
397
            {
398
            float[][] verts = mOuterAndHoleVertices[numComp];
399
            mEdgeVectors[c][v] = produceNormalVector(verts,xs,ys);
400
            }
401
          }
402
        }
403
      }
404
    }
405
406
///////////////////////////////////////////////////////////////////////////////////////////////////
407
// ret:
408
// -1  : vertex (x,y) is 'inner' (does not belong to outer vertices or any hole)
409
// N>=0: vertex (x,y) is outer [ N==0 --> outer, 1--> 1sr hole, 2 --> 2nd hole, etc ]
410
411
  private int retIndexBelongs(float x, float y)
412
    {
413
    int numOuterComponents = mOuterAndHoleVertices.length;
414
415
    for(int c=0; c<numOuterComponents; c++)
416
      {
417
      float[][] comp = mOuterAndHoleVertices[c];
418
419
      for(float[] v : comp)
420
        if( isSame(x-v[0],y-v[1]) ) return c;
421 f835cc50 leszek
      }
422 a60f7acf Leszek Koltunski
423 f835cc50 leszek
    return -1;
424 a60f7acf Leszek Koltunski
    }
425
426 9ee850c5 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
427
428
  private float[] retOuterVector(int component, int vert)
429
    {
430
    return mEdgeVectors[component][vert];
431
    }
432
433 a60f7acf Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
434
435 bc6adbb5 leszek
  private boolean[][] computeVertsUp(float[][][] vertices)
436 a60f7acf Leszek Koltunski
    {
437 bc6adbb5 leszek
    int numPoly = vertices.length;
438
    boolean[][] up = new boolean[numPoly][];
439 a60f7acf Leszek Koltunski
440 bc6adbb5 leszek
    for(int i=0; i<numPoly; i++)
441 a60f7acf Leszek Koltunski
      {
442 bc6adbb5 leszek
      float[][] v = vertices[i];
443
      int len = v.length;
444 a60f7acf Leszek Koltunski
      up[i] = new boolean[len];
445 f835cc50 leszek
446
      for(int j=0; j<len; j++)
447
        {
448 9ee850c5 leszek
        float[] vect = retOuterVector(i,j);
449
        up[i][j] = (vect==null);
450 f835cc50 leszek
        }
451 a60f7acf Leszek Koltunski
      }
452
453 b1bfcdc7 Leszek Koltunski
    return up;
454
    }
455
456 46ef24e5 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
457
458 bc6adbb5 leszek
  private float[] computeCenter(float[][] vertices)
459 46ef24e5 leszek
    {
460 bc6adbb5 leszek
    int num = vertices.length;
461 46ef24e5 leszek
    float[] ret = new float[2];
462
463 bc6adbb5 leszek
    for(float[] vertex : vertices)
464 46ef24e5 leszek
      {
465 bc6adbb5 leszek
      ret[0] += vertex[0];
466
      ret[1] += vertex[1];
467 46ef24e5 leszek
      }
468
469
    ret[0] /= num;
470
    ret[1] /= num;
471
472
    return ret;
473
    }
474
475
///////////////////////////////////////////////////////////////////////////////////////////////////
476
477 bc6adbb5 leszek
  private float[][] computeCenters(float[][][] vertices)
478 46ef24e5 leszek
    {
479
    int num = vertices.length;
480
    float[][] ret = new float[num][];
481
    for(int i=0; i<num; i++) ret[i] = computeCenter(vertices[i]);
482
    return ret;
483
    }
484
485
///////////////////////////////////////////////////////////////////////////////////////////////////
486
487
  private int computeMode(float[] vL, float[] vR, float[] vT, float[] normL, float[] normR,
488 bc6adbb5 leszek
                          int[][] edgesUp, boolean[][] vertsUp, float[][][] vertices, float[][] centers, int component, int curr)
489 46ef24e5 leszek
    {
490 bc6adbb5 leszek
    float[][] v = vertices[component];
491 46ef24e5 leszek
    int[] edges = edgesUp[component];
492 bc6adbb5 leszek
    int numPoly = v.length;
493
    int next= curr==numPoly-1 ? 0 : curr+1;
494
    int prev= curr==0 ? numPoly-1 : curr-1;
495 46ef24e5 leszek
    int eupc = edges[curr];
496
497
    if( eupc<0 )
498
      {
499 bc6adbb5 leszek
      vL[0] = v[curr][0];
500
      vL[1] = v[curr][1];
501
      vR[0] = v[next][0];
502
      vR[1] = v[next][1];
503 46ef24e5 leszek
      vT[0] = centers[component][0];
504
      vT[1] = centers[component][1];
505
506 9ee850c5 leszek
      float[] outerL = retOuterVector(component,curr);
507
      float[] outerR = retOuterVector(component,next);
508 46ef24e5 leszek
509 9ee850c5 leszek
      if( outerL!=null && outerR!=null )
510 1ad1c158 leszek
        {
511 9ee850c5 leszek
        normL[0] = -outerL[0];
512
        normL[1] = -outerL[1];
513
        normR[0] = -outerR[0];
514
        normR[1] = -outerR[1];
515 1ad1c158 leszek
        }
516
      else
517
        {
518
        int eupp = edges[prev];
519
        int eupn = edges[next];
520 f835cc50 leszek
521 1ad1c158 leszek
        if( eupp<0 )
522
          {
523 bc6adbb5 leszek
          normL[0]= vL[0]-vT[0];
524
          normL[1]= vL[1]-vT[1];
525 1ad1c158 leszek
          }
526
        else
527
          {
528 bc6adbb5 leszek
          normL[0]= v[curr][0] - v[prev][0];
529
          normL[1]= v[curr][1] - v[prev][1];
530 1ad1c158 leszek
          }
531
532
        if( eupn<0 )
533
          {
534 bc6adbb5 leszek
          normR[0]= vR[0]-vT[0];
535
          normR[1]= vR[1]-vT[1];
536 1ad1c158 leszek
          }
537
        else
538
          {
539 bc6adbb5 leszek
          int nnxt= next==numPoly-1 ? 0 : next+1;
540
          normR[0]= v[next][0] - v[nnxt][0];
541
          normR[1]= v[next][1] - v[nnxt][1];
542 1ad1c158 leszek
          }
543
        }
544 46ef24e5 leszek
545
      return MeshBandedTriangle.MODE_NORMAL;
546
      }
547
    else
548
      {
549
      vL[0] = centers[eupc][0];
550
      vL[1] = centers[eupc][1];
551
      vR[0] = centers[component][0];
552
      vR[1] = centers[component][1];
553 bc6adbb5 leszek
      vT[0] = v[curr][0];
554
      vT[1] = v[curr][1];
555 46ef24e5 leszek
556
      boolean vup = vertsUp[component][curr];
557
558
      if( vup )
559
        {
560 45b73b1a leszek
        normL[0]=0;
561
        normL[1]=1;
562
        normR[0]=0;
563
        normR[1]=1;
564
565 46ef24e5 leszek
        return MeshBandedTriangle.MODE_FLAT;
566
        }
567
      else
568
        {
569 9ee850c5 leszek
        float[] outerT = retOuterVector(component,curr);
570 1ad1c158 leszek
571 9ee850c5 leszek
        if( outerT!=null )
572 1ad1c158 leszek
          {
573 9ee850c5 leszek
          normL[0]= outerT[0];
574
          normL[1]= outerT[1];
575
          normR[0]= outerT[0];
576
          normR[1]= outerT[1];
577 1ad1c158 leszek
          }
578
        else
579
          {
580 bc6adbb5 leszek
          float dx = v[next][0]-v[curr][0];
581
          float dy = v[next][1]-v[curr][1];
582 1ad1c158 leszek
          normL[0]= dx;
583
          normL[1]= dy;
584
          normR[0]= dx;
585
          normR[1]= dy;
586
          }
587 46ef24e5 leszek
588
        return MeshBandedTriangle.MODE_INVERTED;
589
        }
590
      }
591
    }
592
593 b1bfcdc7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
594
// PUBLIC API
595 9ee850c5 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
596
597 bc6adbb5 leszek
  public static int[][] computeEdgesUp(float[][][] vertices)
598 9ee850c5 leszek
    {
599
    int numPoly = vertices.length;
600
    int[][] up = new int[numPoly][];
601
602
    for(int p=0; p<numPoly; p++)
603
      {
604 bc6adbb5 leszek
      int numEdges = vertices[p].length;
605 9ee850c5 leszek
      up[p] = new int[numEdges];
606 bc6adbb5 leszek
      for(int e=0; e<numEdges; e++) up[p][e] = isUp(vertices,p,e);
607 9ee850c5 leszek
      }
608
609
    return up;
610
    }
611
612
///////////////////////////////////////////////////////////////////////////////////////////////////
613
614 bc6adbb5 leszek
  public static float[][][] computeOuterAndHoleVertices(float[][][] vertices, int[][] edgesUp)
615 9ee850c5 leszek
    {
616
    ArrayList<float[]> tmp = new ArrayList<>();
617
618
    float[] vect = new float[] {1,0};
619
    float[] first= detectFirstOuterVertex(vertices);
620
    float[] next = first;
621
622
    do
623
      {
624
      float[] prev = next;
625
      next = detectNextOuterVertex(vertices,next,vect,edgesUp);
626
      vect[0] = prev[0]-next[0];
627
      vect[1] = prev[1]-next[1];
628
      tmp.add(next);
629
      }
630
    while( !isSame(next[0]-first[0],next[1]-first[1]) );
631
632
    int numOuterVerts= tmp.size();
633
    float[][] outerVertices = new float[numOuterVerts][];
634 efcbfe8e leszek
    for(int i=0; i<numOuterVerts; i++) outerVertices[i] = tmp.remove(0);
635 9ee850c5 leszek
636
    int numEdgesDown = countEdgesDown(edgesUp);
637
    int numHoleVerts= numEdgesDown-numOuterVerts;
638
    float[][][] holeVertices=null;
639 efcbfe8e leszek
    if( numHoleVerts>0 ) holeVertices = computeHoles(vertices,edgesUp,outerVertices,numHoleVerts);
640 9ee850c5 leszek
    int numHoles = holeVertices==null ? 0 : holeVertices.length;
641
    float[][][] ret = new float[1+numHoles][][];
642
    ret[0] = outerVertices;
643
    for(int i=0; i<numHoles; i++) ret[i+1] = holeVertices[i];
644
645
    return ret;
646
    }
647
648 b1bfcdc7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
649
/**
650
 * Specify several lists of vertices. Each list defines one polygon. (@see MeshPolygon).
651
 * If two such polygons share an edge (or several edges) then the edge in both of them is
652
 * marked 'up'.
653
 *
654 bc6adbb5 leszek
 * @param vertices   an array float[][]s, each specifying vertices of a single polygon.
655 b1bfcdc7 Leszek Koltunski
 * @param band       see MeshPolygon. Shared among all polygons.
656 46ef24e5 leszek
 * @param exBands    see MeshPolygon. Shared among all polygons.
657 b1bfcdc7 Leszek Koltunski
 * @param exVertices see MeshPolygon. Shared among all polygons.
658
 */
659 bc6adbb5 leszek
  public MeshMultigon(float[][][] vertices, float[] band, int exBands, int exVertices)
660 b1bfcdc7 Leszek Koltunski
    {
661
    super();
662
663 46ef24e5 leszek
    int numTriangles=0;
664 bc6adbb5 leszek
    for(float[][] vertex : vertices) numTriangles+=vertex.length;
665 46ef24e5 leszek
    MeshBandedTriangle[] triangles = new MeshBandedTriangle[numTriangles];
666 a60f7acf Leszek Koltunski
667 46ef24e5 leszek
    int[][] edgesUp = computeEdgesUp(vertices);
668 1ce7e2f6 leszek
    mOuterAndHoleVertices = computeOuterAndHoleVertices(vertices,edgesUp);
669 9ee850c5 leszek
670
    computeEdgeVectors(vertices,edgesUp);
671
672 46ef24e5 leszek
    boolean[][] vertsUp = computeVertsUp(vertices);
673
    float[][] centers = computeCenters(vertices);
674 a60f7acf Leszek Koltunski
675 46ef24e5 leszek
    float[] vL = new float[2];
676
    float[] vR = new float[2];
677
    float[] vT = new float[2];
678
    float[] normL = new float[2];
679
    float[] normR = new float[2];
680 a60f7acf Leszek Koltunski
681 46ef24e5 leszek
    int index=0,len = vertices.length;
682 b1bfcdc7 Leszek Koltunski
683 46ef24e5 leszek
    for(int i=0; i<len; i++)
684 a60f7acf Leszek Koltunski
      {
685 bc6adbb5 leszek
      int num=vertices[i].length;
686 a60f7acf Leszek Koltunski
687
      for(int j=0; j<num; j++)
688
        {
689 ef4a9bab leszek
        int mode=computeMode(vL, vR, vT, normL, normR, edgesUp, vertsUp,vertices,centers, i,j);
690 46ef24e5 leszek
        triangles[index++] = new MeshBandedTriangle(vL, vR, vT, band, normL, normR, mode, exBands, exVertices);
691 a60f7acf Leszek Koltunski
        }
692
      }
693 b1bfcdc7 Leszek Koltunski
694 46ef24e5 leszek
    join(triangles);
695 d45273cd Leszek Koltunski
    mergeEffComponents();
696
    mergeTexComponents();
697 b1bfcdc7 Leszek Koltunski
    }
698
699
///////////////////////////////////////////////////////////////////////////////////////////////////
700
/**
701
 * Copy constructor.
702
 */
703
  public MeshMultigon(MeshMultigon mesh, boolean deep)
704
    {
705
    super(mesh,deep);
706
    }
707
708
///////////////////////////////////////////////////////////////////////////////////////////////////
709
/**
710
 * Copy the Mesh.
711
 *
712
 * @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices,
713
 *             normals and inflates (the rest, in particular the mVertAttribs2 containing texture
714
 *             coordinates and effect associations, is always deep copied)
715
 */
716
  public MeshMultigon copy(boolean deep)
717
    {
718
    return new MeshMultigon(this,deep);
719
    }
720
 }