Project

General

Profile

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

library / src / main / java / org / distorted / library / mesh / MeshMultigon.java @ 9ee850c5

1
///////////////////////////////////////////////////////////////////////////////////////////////////
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
import java.util.ArrayList;
24

    
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

    
27
/**
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
  private static final float MAX_ERROR = 0.000001f;
38
  private float[][][] mOuterAndHoleVertices;
39
  private float[][][] mEdgeVectors;
40

    
41
///////////////////////////////////////////////////////////////////////////////////////////////////
42

    
43
  private static boolean isSame(float dx, float dy)
44
    {
45
    return (dx*dx + dy*dy < MAX_ERROR);
46
    }
47

    
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49

    
50
  private static int isUp(float[][] vertices, int polygon, int edge)
51
    {
52
    float[] p= vertices[polygon];
53
    int lenP = p.length/2;
54
    int len  = vertices.length;
55
    int next = (edge==lenP-1 ? 0 : edge+1);
56

    
57
    float v1x = p[2*edge  ];
58
    float v1y = p[2*edge+1];
59
    float v2x = p[2*next  ];
60
    float v2y = p[2*next+1];
61

    
62
    for(int i=0; i<len; i++)
63
      if( i!=polygon )
64
        {
65
        int num = vertices[i].length/2;
66

    
67
        for(int j=0; j<num; j++)
68
          {
69
          int n = (j==num-1 ? 0 : j+1);
70
          float[] v = vertices[i];
71
          float x1 = v[2*j  ];
72
          float y1 = v[2*j+1];
73
          float x2 = v[2*n  ];
74
          float y2 = v[2*n+1];
75

    
76
          if( isSame(v2x-x1,v2y-y1) && isSame(v1x-x2,v1y-y2) ) return i;
77
          }
78
        }
79

    
80
    return -1;
81
    }
82

    
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84

    
85
  private static float[] detectFirstOuterVertex(float[][] vertices)
86
    {
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
      {
92
      float[] v = vertices[i];
93
      int num = v.length/2;
94

    
95
      for(int j=0; j<num; j++)
96
        if(v[2*j]>X)
97
          {
98
          X = v[2*j];
99
          I = i;
100
          J = j;
101
          }
102
      }
103

    
104
    float[] v = vertices[I];
105
    return new float[] {v[2*J],v[2*J+1]};
106
    }
107

    
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109

    
110
  private static double computeAngle(float x1,float y1, float x2, float y2)
111
    {
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
  private static float[] detectNextOuterVertex(float[][] vertices, float[] curr, float[] vect, int[][] edgesUp)
119
    {
120
    double maxAngle = 0;
121
    float x=0, y=0;
122
    int numC = vertices.length;
123

    
124
    for( int c=0; c<numC; c++ )
125
      {
126
      float[] vert = vertices[c];
127
      int numV = vert.length/2;
128

    
129
      for( int v=0; v<numV; v++)
130
        {
131
        float xc = vert[2*v];
132
        float yc = vert[2*v+1];
133

    
134
        if( edgesUp[c][v]<0 && isSame(xc-curr[0],yc-curr[1]) )
135
          {
136
          int n = (v==numV-1 ? 0 : v+1);
137
          float xn = vert[2*n];
138
          float yn = vert[2*n+1];
139

    
140
          double angle = computeAngle(vect[0], vect[1], xn-xc, yn-yc);
141

    
142
          if (angle > maxAngle)
143
            {
144
            maxAngle = angle;
145
            x = xn;
146
            y = yn;
147
            }
148

    
149
          break;
150
          }
151
        }
152
      }
153

    
154
    //android.util.Log.e("D", "curr vert: "+curr[0]+" "+curr[1]+" vect "+vect[0]+" "+vect[1]+" : "+x+" "+y);
155

    
156
    return new float[] {x,y};
157
    }
158

    
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160

    
161
  private static int getNextIndex(float[][] vertices, int[][] unclaimedEdges, int currIndex, int numHoleVerts)
162
    {
163
    int[] currEdge = unclaimedEdges[currIndex];
164
    int currP = currEdge[0];
165
    int currE = currEdge[1];
166
    float[] polygon = vertices[currP];
167
    int numV = polygon.length/2;
168
    int nextE= currE<numV-1 ? currE+1 : 0;
169

    
170
    float x = polygon[2*nextE];
171
    float y = polygon[2*nextE+1];
172

    
173
    for(int e=0; e<numHoleVerts; e++)
174
      {
175
      int[] edge = unclaimedEdges[e];
176

    
177
      if( edge[2]==1 )
178
        {
179
        int po = edge[0];
180
        int ed = edge[1];
181

    
182
        float cx = vertices[po][2*ed];
183
        float cy = vertices[po][2*ed+1];
184

    
185
        if( isSame(cx-x,cy-y) )
186
          {
187
          edge[2] = 0;
188
          return e;
189
          }
190
        }
191
      }
192

    
193
    return -1;
194
    }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

    
198
  private static int generateHole(float[][] vertices, int[][] unclaimedEdges, float[][] output, int[][] edgesUp, int holeNumber, int numHoleVerts)
199
    {
200
    int firstIndex=-1;
201

    
202
    for(int e=0; e<numHoleVerts; e++)
203
      if( unclaimedEdges[e][2]==1 )
204
        {
205
        firstIndex = e;
206
        break;
207
        }
208

    
209
    int currIndex = firstIndex;
210
    int nextIndex=-1;
211
    int numAdded = 0;
212

    
213
    while( nextIndex!=firstIndex )
214
      {
215
      nextIndex = getNextIndex(vertices,unclaimedEdges,currIndex,numHoleVerts);
216

    
217
      int p = unclaimedEdges[nextIndex][0];
218
      int v = unclaimedEdges[nextIndex][1];
219
      edgesUp[p][v] = -holeNumber-2;
220

    
221
      //printEdgeEnds("HOLE "+holeNumber,vertices, p, v);
222

    
223
      currIndex = nextIndex;
224
      int[] e = unclaimedEdges[nextIndex];
225
      float[] polygon = vertices[e[0]];
226
      output[numAdded][0] = polygon[2*e[1]];
227
      output[numAdded][1] = polygon[2*e[1]+1];
228
      numAdded++;
229
      }
230

    
231
    return numAdded;
232
    }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235

    
236
  private static boolean doesNotBelongToOuter(float x, float y, float[][] outer)
237
    {
238
    for(float[] v : outer)
239
      if(isSame(x-v[0], y-v[1])) return false;
240

    
241
    return true;
242
    }
243

    
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245

    
246
  private static float[][][] computeHoles(float[][] vertices, int[][] edgesUp, float[][] outer, int numHoleVerts)
247
    {
248
    int[][] unclaimedEdges = new int[numHoleVerts][];
249
    int index = 0;
250
    int numPoly = vertices.length;
251

    
252
    for(int p=0; p<numPoly; p++)
253
      {
254
      float[] ve = vertices[p];
255
      int numEdges = ve.length/2;
256

    
257
      for(int e=0; e<numEdges; e++)
258
        if( edgesUp[p][e]<0 )
259
          {
260
          float x1 = ve[2*e];
261
          float y1 = ve[2*e+1];
262

    
263
          int n = e<numEdges-1 ? e+1 : 0;
264
          float x2 = ve[2*n];
265
          float y2 = ve[2*n+1];
266

    
267
          // yes, we need to check both ends of the edge - otherwise the
268
          // following 3x3 situation (x - wall, o - hole ) does not work:
269
          // x x x
270
          // x o x
271
          // o x x
272

    
273
          if( doesNotBelongToOuter(x1,y1,outer) || doesNotBelongToOuter(x2,y2,outer) )
274
            {
275
            unclaimedEdges[index]=new int[] {p, e, 1};
276
            index++;
277
            }
278
          }
279
      }
280

    
281
    int remaining = numHoleVerts;
282
    ArrayList<float[][]> holes = new ArrayList<>();
283
    float[][] output = new float[numHoleVerts][2];
284
    int numHoles = 0;
285

    
286
    while(remaining>0)
287
      {
288
      int num = generateHole(vertices,unclaimedEdges,output,edgesUp,numHoles,numHoleVerts);
289
      remaining -= num;
290
      numHoles++;
291

    
292
      float[][] hole = new float[num][2];
293
      for(int h=0; h<num; h++)
294
        {
295
        hole[h][0] = output[h][0];
296
        hole[h][1] = output[h][1];
297
        }
298

    
299
      holes.add(hole);
300
      }
301

    
302
    float[][][] ret = new float[numHoles][][];
303
    for(int h=0; h<numHoles; h++) ret[h] = holes.remove(0);
304

    
305
    //android.util.Log.e("D", "Holes: "+numHoles+" HoleVertices: "+mNumHoleVerts+" numOuterVerts: "+mNumOuterVerts);
306

    
307
    return ret;
308
    }
309

    
310
///////////////////////////////////////////////////////////////////////////////////////////////////
311

    
312
  private static int countEdgesDown(int[][] edgesUp)
313
    {
314
    int numEdgesDown = 0;
315

    
316
    for(int[] edgeUp : edgesUp)
317
      for(int edge : edgeUp)
318
        if( edge<0 ) numEdgesDown++;
319

    
320
    return numEdgesDown;
321
    }
322

    
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324

    
325
  private float[] produceNormalVector(float[][] verts, float xs, float ys)
326
    {
327
    int vCurr,len = verts.length;
328

    
329
    for(vCurr=0; vCurr<len; vCurr++)
330
      {
331
      float[] vs = verts[vCurr];
332
      if( isSame(vs[0]-xs,vs[1]-ys) ) break;
333
      }
334

    
335
    if( vCurr==len ) android.util.Log.e("D", "ERROR in produceNormalVector!!");
336

    
337
    int vPrev = vCurr==0 ? len-1 : vCurr-1;
338
    int vNext = vCurr>=len-1 ? 0 : vCurr+1;
339
    float[] vp = verts[vPrev];
340
    float[] vn = verts[vNext];
341

    
342
    return new float[] { vp[1]-vn[1], vn[0]-vp[0] };
343
    }
344

    
345
///////////////////////////////////////////////////////////////////////////////////////////////////
346

    
347
  private float[] produceNormalVector(float[][] verts, float xs, float ys, float xe, float ye)
348
    {
349
    int vCurr,len = verts.length;
350

    
351
    for(vCurr=0; vCurr<len; vCurr++)
352
      {
353
      float[] vs = verts[vCurr];
354

    
355
      if( isSame(vs[0]-xs,vs[1]-ys) )
356
        {
357
        int vNext = vCurr==len-1 ? 0 : vCurr+1;
358
        float[] ve = verts[vNext];
359
        if( isSame(ve[0]-xe,ve[1]-ye) ) break;
360
        }
361
      }
362

    
363
    int vPrev = vCurr==0 ? len-1 : vCurr-1;
364
    int vNext = vCurr>=len-1 ? 0 : vCurr+1;
365
    float[] vp = verts[vPrev];
366
    float[] vn = verts[vNext];
367

    
368
    return new float[] { vp[1]-vn[1], vn[0]-vp[0] };
369
    }
370

    
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

    
373
  private void computeEdgeVectors(float[][] vertices, int[][] edgesUp)
374
    {
375
    int numComponents = vertices.length;
376
    mEdgeVectors = new float[numComponents][][];
377

    
378
    for(int c=0; c<numComponents; c++)
379
      {
380
      float[] polygon = vertices[c];
381
      int numV = polygon.length/2;
382
      mEdgeVectors[c] = new float[numV][];
383

    
384
      for(int v=0; v<numV; v++)
385
        {
386
        int edgeUp = edgesUp[c][v];
387
        float xs = polygon[2*v];
388
        float ys = polygon[2*v+1];
389
        int n = v==numV-1 ? 0 : v+1;
390
        float xe = polygon[2*n];
391
        float ye = polygon[2*n+1];
392

    
393
        if( edgeUp<0 ) // external edge, normal vector
394
          {
395
          float[][] verts = mOuterAndHoleVertices[-edgeUp-1];
396
          mEdgeVectors[c][v] = produceNormalVector(verts,xs,ys,xe,ye);
397
          }
398
        else // internal edge - but the vertex that begins it might still be outer!
399
          {
400
          int numComp = retIndexBelongs(xs,ys);
401

    
402
          if( numComp<0 ) mEdgeVectors[c][v] = null;
403
          else
404
            {
405
            float[][] verts = mOuterAndHoleVertices[numComp];
406
            mEdgeVectors[c][v] = produceNormalVector(verts,xs,ys);
407
            }
408
          }
409
        //android.util.Log.e("D", "edgeVectors "+c+" "+v+" null: "+(mEdgeVectors[c][v]==null) );
410
        }
411
      }
412
    }
413

    
414
///////////////////////////////////////////////////////////////////////////////////////////////////
415

    
416
  private void printEdgeEnds(String str, float[][] vertices, int p, int e)
417
    {
418
    float[] polygon = vertices[p];
419
    int len = polygon.length/2;
420
    int n = e<len-1 ? e+1 : 0;
421

    
422
    android.util.Log.e("D", str+" edge "+p+" "+e+" : ("+polygon[2*e]+" "+polygon[2*e+1]+") - ("+polygon[2*n]+" "+polygon[2*n+1]+")");
423
    }
424

    
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426
// ret:
427
// -1  : vertex (x,y) is 'inner' (does not belong to outer vertices or any hole)
428
// N>=0: vertex (x,y) is outer [ N==0 --> outer, 1--> 1sr hole, 2 --> 2nd hole, etc ]
429

    
430
  private int retIndexBelongs(float x, float y)
431
    {
432
    int numOuterComponents = mOuterAndHoleVertices.length;
433

    
434
    for(int c=0; c<numOuterComponents; c++)
435
      {
436
      float[][] comp = mOuterAndHoleVertices[c];
437

    
438
      for(float[] v : comp)
439
        if( isSame(x-v[0],y-v[1]) ) return c;
440
      }
441

    
442
    return -1;
443
    }
444

    
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446

    
447
  private float[] retOuterVector(int component, int vert)
448
    {
449
    return mEdgeVectors[component][vert];
450
    }
451

    
452
///////////////////////////////////////////////////////////////////////////////////////////////////
453

    
454
  private boolean[][] computeVertsUp(float[][] vertices)
455
    {
456
    int num = vertices.length;
457
    boolean[][] up = new boolean[num][];
458

    
459
    for(int i=0; i<num; i++)
460
      {
461
      float[] v = vertices[i];
462
      int len = v.length/2;
463
      up[i] = new boolean[len];
464

    
465
      for(int j=0; j<len; j++)
466
        {
467
        float[] vect = retOuterVector(i,j);
468
        up[i][j] = (vect==null);
469
        }
470
      }
471

    
472
    return up;
473
    }
474

    
475
///////////////////////////////////////////////////////////////////////////////////////////////////
476

    
477
  private float[] computeCenter(float[] vertices)
478
    {
479
    int num = vertices.length/2;
480
    float[] ret = new float[2];
481

    
482
    for(int i=0; i<num; i++)
483
      {
484
      ret[0] += vertices[2*i];
485
      ret[1] += vertices[2*i+1];
486
      }
487

    
488
    ret[0] /= num;
489
    ret[1] /= num;
490

    
491
    return ret;
492
    }
493

    
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495

    
496
  private float[][] computeCenters(float[][] vertices)
497
    {
498
    int num = vertices.length;
499
    float[][] ret = new float[num][];
500
    for(int i=0; i<num; i++) ret[i] = computeCenter(vertices[i]);
501
    return ret;
502
    }
503

    
504
///////////////////////////////////////////////////////////////////////////////////////////////////
505

    
506
  private int computeMode(float[] vL, float[] vR, float[] vT, float[] normL, float[] normR,
507
                          int[][] edgesUp, boolean[][] vertsUp, float[][] vertices, float[][] centers, int component, int curr)
508
    {
509
    float[] v = vertices[component];
510
    int[] edges = edgesUp[component];
511
    int len = v.length /2;
512
    int next= curr==len-1 ? 0 : curr+1;
513
    int prev= curr==0 ? len-1 : curr-1;
514
    int eupc = edges[curr];
515

    
516
    if( eupc<0 )
517
      {
518
      vL[0] = v[2*curr];
519
      vL[1] = v[2*curr+1];
520
      vR[0] = v[2*next];
521
      vR[1] = v[2*next+1];
522
      vT[0] = centers[component][0];
523
      vT[1] = centers[component][1];
524

    
525
      float[] outerL = retOuterVector(component,curr);
526
      float[] outerR = retOuterVector(component,next);
527

    
528
      if( outerL!=null && outerR!=null )
529
        {
530
        normL[0] = -outerL[0];
531
        normL[1] = -outerL[1];
532
        normR[0] = -outerR[0];
533
        normR[1] = -outerR[1];
534
        }
535
      else
536
        {
537
        int eupp = edges[prev];
538
        int eupn = edges[next];
539

    
540
        if( eupp<0 )
541
          {
542
          normL[0]=vL[0]-vT[0];
543
          normL[1]=vL[1]-vT[1];
544
          }
545
        else
546
          {
547
          normL[0]= v[2*curr  ] - v[2*prev  ];
548
          normL[1]= v[2*curr+1] - v[2*prev+1];
549
          }
550

    
551
        if( eupn<0 )
552
          {
553
          normR[0]=vR[0]-vT[0];
554
          normR[1]=vR[1]-vT[1];
555
          }
556
        else
557
          {
558
          int nnxt= next==len-1 ? 0 : next+1;
559
          normR[0]= v[2*next  ] - v[2*nnxt  ];
560
          normR[1]= v[2*next+1] - v[2*nnxt+1];
561
          }
562
        }
563

    
564
      return MeshBandedTriangle.MODE_NORMAL;
565
      }
566
    else
567
      {
568
      vL[0] = centers[eupc][0];
569
      vL[1] = centers[eupc][1];
570
      vR[0] = centers[component][0];
571
      vR[1] = centers[component][1];
572
      vT[0] = v[2*curr];
573
      vT[1] = v[2*curr+1];
574

    
575
      boolean vup = vertsUp[component][curr];
576

    
577
      if( vup )
578
        {
579
        normL[0]=0;
580
        normL[1]=1;
581
        normR[0]=0;
582
        normR[1]=1;
583

    
584
        return MeshBandedTriangle.MODE_FLAT;
585
        }
586
      else
587
        {
588
        float[] outerT = retOuterVector(component,curr);
589

    
590
        if( outerT!=null )
591
          {
592
          normL[0]= outerT[0];
593
          normL[1]= outerT[1];
594
          normR[0]= outerT[0];
595
          normR[1]= outerT[1];
596
          }
597
        else
598
          {
599
          float dx = v[2*next  ]-v[2*curr  ];
600
          float dy = v[2*next+1]-v[2*curr+1];
601
          normL[0]= dx;
602
          normL[1]= dy;
603
          normR[0]= dx;
604
          normR[1]= dy;
605
          }
606

    
607
        return MeshBandedTriangle.MODE_INVERTED;
608
        }
609
      }
610
    }
611

    
612
///////////////////////////////////////////////////////////////////////////////////////////////////
613
// PUBLIC API
614
///////////////////////////////////////////////////////////////////////////////////////////////////
615

    
616
  public static int[][] computeEdgesUp(float[][] vertices)
617
    {
618
    int numPoly = vertices.length;
619
    int[][] up = new int[numPoly][];
620

    
621
    for(int p=0; p<numPoly; p++)
622
      {
623
      int numEdges = vertices[p].length/2;
624
      up[p] = new int[numEdges];
625

    
626
      for(int e=0; e<numEdges; e++)
627
        up[p][e] = isUp(vertices,p,e);
628
      }
629

    
630
    return up;
631
    }
632

    
633
///////////////////////////////////////////////////////////////////////////////////////////////////
634

    
635
  public static float[][][] computeOuterVertices(float[][] vertices, int[][] edgesUp)
636
    {
637
    ArrayList<float[]> tmp = new ArrayList<>();
638

    
639
    float[] vect = new float[] {1,0};
640
    float[] first= detectFirstOuterVertex(vertices);
641
    float[] next = first;
642

    
643
    do
644
      {
645
      float[] prev = next;
646
      next = detectNextOuterVertex(vertices,next,vect,edgesUp);
647
      vect[0] = prev[0]-next[0];
648
      vect[1] = prev[1]-next[1];
649
      tmp.add(next);
650
      }
651
    while( !isSame(next[0]-first[0],next[1]-first[1]) );
652

    
653
    int numOuterVerts= tmp.size();
654
    float[][] outerVertices = new float[numOuterVerts][];
655
    for(int i=0; i<numOuterVerts; i++)
656
      {
657
      outerVertices[i] = tmp.remove(0);
658

    
659
      //if( mNumOuterVerts>14 )
660
      //  android.util.Log.e("D","outer: "+mOuterVertices[i][0]+" "+mOuterVertices[i][1]);
661
      }
662

    
663
    int numEdgesDown = countEdgesDown(edgesUp);
664
    int numHoleVerts= numEdgesDown-numOuterVerts;
665
    float[][][] holeVertices=null;
666

    
667
    if( numHoleVerts>0 )
668
      {
669
      holeVertices = computeHoles(vertices,edgesUp,outerVertices,numHoleVerts);
670
      }
671

    
672
    int numHoles = holeVertices==null ? 0 : holeVertices.length;
673
    float[][][] ret = new float[1+numHoles][][];
674
    ret[0] = outerVertices;
675
    for(int i=0; i<numHoles; i++) ret[i+1] = holeVertices[i];
676

    
677
    return ret;
678
    }
679

    
680
///////////////////////////////////////////////////////////////////////////////////////////////////
681
/**
682
 * Specify several lists of vertices. Each list defines one polygon. (@see MeshPolygon).
683
 * If two such polygons share an edge (or several edges) then the edge in both of them is
684
 * marked 'up'.
685
 *
686
 * @param vertices   an array of arrays, each specifying vertices of a single polygon.
687
 * @param band       see MeshPolygon. Shared among all polygons.
688
 * @param exBands    see MeshPolygon. Shared among all polygons.
689
 * @param exVertices see MeshPolygon. Shared among all polygons.
690
 */
691
  public MeshMultigon(float[][] vertices, float[] band, int exBands, int exVertices)
692
    {
693
    super();
694

    
695
    int numTriangles=0;
696
    for(float[] vertex : vertices) numTriangles+=vertex.length/2;
697
    MeshBandedTriangle[] triangles = new MeshBandedTriangle[numTriangles];
698

    
699
    int[][] edgesUp = computeEdgesUp(vertices);
700
    mOuterAndHoleVertices = computeOuterVertices(vertices,edgesUp);
701

    
702
    computeEdgeVectors(vertices,edgesUp);
703

    
704
    boolean[][] vertsUp = computeVertsUp(vertices);
705
    float[][] centers = computeCenters(vertices);
706

    
707
    float[] vL = new float[2];
708
    float[] vR = new float[2];
709
    float[] vT = new float[2];
710
    float[] normL = new float[2];
711
    float[] normR = new float[2];
712

    
713
    int index=0,len = vertices.length;
714

    
715
    for(int i=0; i<len; i++)
716
      {
717
      int num=vertices[i].length/2;
718

    
719
      for(int j=0; j<num; j++)
720
        {
721
        int mode=computeMode(vL, vR, vT, normL, normR, edgesUp, vertsUp,vertices,centers, i,j);
722
        triangles[index++] = new MeshBandedTriangle(vL, vR, vT, band, normL, normR, mode, exBands, exVertices);
723
        }
724
      }
725

    
726
    join(triangles);
727
    mergeEffComponents();
728
    mergeTexComponents();
729
    }
730

    
731
///////////////////////////////////////////////////////////////////////////////////////////////////
732
/**
733
 * Copy constructor.
734
 */
735
  public MeshMultigon(MeshMultigon mesh, boolean deep)
736
    {
737
    super(mesh,deep);
738
    }
739

    
740
///////////////////////////////////////////////////////////////////////////////////////////////////
741
/**
742
 * Copy the Mesh.
743
 *
744
 * @param deep If to be a deep or shallow copy of mVertAttribs1, i.e. the array holding vertices,
745
 *             normals and inflates (the rest, in particular the mVertAttribs2 containing texture
746
 *             coordinates and effect associations, is always deep copied)
747
 */
748
  public MeshMultigon copy(boolean deep)
749
    {
750
    return new MeshMultigon(this,deep);
751
    }
752
 }
(7-7/12)