Project

General

Profile

« Previous | Next » 

Revision 9ee850c5

Added by Leszek Koltunski 10 months ago

Major progress with supporting cubit faces with holes.

View differences:

src/main/java/org/distorted/library/mesh/MeshMultigon.java
35 35
public class MeshMultigon extends MeshBase
36 36
  {
37 37
  private static final float MAX_ERROR = 0.000001f;
38
  private float[][] mOuterVertices;
39
  private float[][] mOuterVectors;
40
  private int mNumOuter;
38
  private float[][][] mOuterAndHoleVertices;
39
  private float[][][] mEdgeVectors;
41 40

  
42 41
///////////////////////////////////////////////////////////////////////////////////////////////////
43 42

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

  
49 48
///////////////////////////////////////////////////////////////////////////////////////////////////
50 49

  
51
  private int isUp(float[][] vertices, int polygon, int edge)
50
  private static int isUp(float[][] vertices, int polygon, int edge)
52 51
    {
53 52
    float[] p= vertices[polygon];
54 53
    int lenP = p.length/2;
......
83 82

  
84 83
///////////////////////////////////////////////////////////////////////////////////////////////////
85 84

  
86
  private int[][] computeEdgesUp(float[][] vertices)
87
    {
88
    int num = vertices.length;
89
    int[][] up = new int[num][];
90

  
91
    for(int i=0; i<num; i++)
92
      {
93
      int len = vertices[i].length/2;
94
      up[i] = new int[len];
95
      for(int j=0; j<len; j++) up[i][j] = isUp(vertices,i,j);
96
      }
97

  
98
    return up;
99
    }
100

  
101
///////////////////////////////////////////////////////////////////////////////////////////////////
102

  
103
  private float[] detectFirstOuterVertex(float[][] vertices)
85
  private static float[] detectFirstOuterVertex(float[][] vertices)
104 86
    {
105 87
    float X = -Float.MAX_VALUE;
106 88
    int I=0,J=0, len = vertices.length;
......
125 107

  
126 108
///////////////////////////////////////////////////////////////////////////////////////////////////
127 109

  
128
  private double computeAngle(float x1,float y1, float x2, float y2)
110
  private static double computeAngle(float x1,float y1, float x2, float y2)
129 111
    {
130 112
    double diff = Math.atan2(y2,x2)-Math.atan2(y1,x1);
131 113
    return diff<0 ? diff+(2*Math.PI) : diff;
......
133 115

  
134 116
///////////////////////////////////////////////////////////////////////////////////////////////////
135 117

  
136
  private float[] detectNextOuterVertex(float[][] vertices, float[] curr, float[] vect)
118
  private static float[] detectNextOuterVertex(float[][] vertices, float[] curr, float[] vect, int[][] edgesUp)
137 119
    {
138
    double minAngle = 2*Math.PI;
120
    double maxAngle = 0;
139 121
    float x=0, y=0;
122
    int numC = vertices.length;
140 123

  
141
    for( float[] v : vertices )
124
    for( int c=0; c<numC; c++ )
142 125
      {
143
      int num = v.length/2;
126
      float[] vert = vertices[c];
127
      int numV = vert.length/2;
144 128

  
145
      for( int j=0; j<num; j++)
129
      for( int v=0; v<numV; v++)
146 130
        {
147
        float xc = v[2*j];
148
        float yc = v[2*j+1];
131
        float xc = vert[2*v];
132
        float yc = vert[2*v+1];
149 133

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

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

  
158
          if (angle < minAngle)
142
          if (angle > maxAngle)
159 143
            {
160
            minAngle = angle;
144
            maxAngle = angle;
161 145
            x = xn;
162 146
            y = yn;
163 147
            }
......
167 151
        }
168 152
      }
169 153

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

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

  
173 159
///////////////////////////////////////////////////////////////////////////////////////////////////
174 160

  
175
  private void computeOuterVectors()
161
  private static int getNextIndex(float[][] vertices, int[][] unclaimedEdges, int currIndex, int numHoleVerts)
176 162
    {
177
    mOuterVectors = new float[mNumOuter][];
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;
178 169

  
179
    for(int curr=0; curr<mNumOuter; curr++)
170
    float x = polygon[2*nextE];
171
    float y = polygon[2*nextE+1];
172

  
173
    for(int e=0; e<numHoleVerts; e++)
180 174
      {
181
      int prev = curr==0 ? mNumOuter-1 : curr-1;
182
      int next = curr==mNumOuter-1 ? 0 : curr+1;
175
      int[] edge = unclaimedEdges[e];
183 176

  
184
      float[] vP = mOuterVertices[prev];
185
      float[] vN = mOuterVertices[next];
177
      if( edge[2]==1 )
178
        {
179
        int po = edge[0];
180
        int ed = edge[1];
186 181

  
187
      float dx = vP[0]-vN[0];
188
      float dy = vP[1]-vN[1];
182
        float cx = vertices[po][2*ed];
183
        float cy = vertices[po][2*ed+1];
189 184

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

  
193
    return -1;
192 194
    }
193 195

  
194 196
///////////////////////////////////////////////////////////////////////////////////////////////////
195 197

  
196
  private void computeOuterVertices(float[][] vertices)
198
  private static int generateHole(float[][] vertices, int[][] unclaimedEdges, float[][] output, int[][] edgesUp, int holeNumber, int numHoleVerts)
197 199
    {
198
    ArrayList<float[]> tmp = new ArrayList<>();
200
    int firstIndex=-1;
199 201

  
200
    float[] vect = new float[] {1,0};
201
    float[] first= detectFirstOuterVertex(vertices);
202
    float[] next = first;
202
    for(int e=0; e<numHoleVerts; e++)
203
      if( unclaimedEdges[e][2]==1 )
204
        {
205
        firstIndex = e;
206
        break;
207
        }
203 208

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

  
213
    while( nextIndex!=firstIndex )
205 214
      {
206
      float[] prev = next;
207
      next = detectNextOuterVertex(vertices,next,vect);
208
      vect[0] = prev[0]-next[0];
209
      vect[1] = prev[1]-next[1];
210
      tmp.add(next);
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++;
211 229
      }
212
    while( !isSame(next[0]-first[0],next[1]-first[1]) );
213 230

  
214
    mNumOuter = tmp.size();
215
    mOuterVertices = new float[mNumOuter][];
216
    for(int i=0; i<mNumOuter; i++) mOuterVertices[i] = tmp.remove(0);
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] };
217 343
    }
218 344

  
219 345
///////////////////////////////////////////////////////////////////////////////////////////////////
220 346

  
221
  private int belongsToOuter(float x, float y)
347
  private float[] produceNormalVector(float[][] verts, float xs, float ys, float xe, float ye)
222 348
    {
223
    for( int i=0; i<mNumOuter; i++ )
349
    int vCurr,len = verts.length;
350

  
351
    for(vCurr=0; vCurr<len; vCurr++)
224 352
      {
225
      float[] v = mOuterVertices[i];
226
      if( isSame(x-v[0],y-v[1]) ) return i;
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;
227 440
      }
228 441

  
229 442
    return -1;
230 443
    }
231 444

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

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

  
232 452
///////////////////////////////////////////////////////////////////////////////////////////////////
233 453

  
234 454
  private boolean[][] computeVertsUp(float[][] vertices)
......
244 464

  
245 465
      for(int j=0; j<len; j++)
246 466
        {
247
        int vert = belongsToOuter(v[2*j],v[2*j+1]);
248
        up[i][j] = (vert==-1);
467
        float[] vect = retOuterVector(i,j);
468
        up[i][j] = (vect==null);
249 469
        }
250 470
      }
251 471

  
......
302 522
      vT[0] = centers[component][0];
303 523
      vT[1] = centers[component][1];
304 524

  
305
      int outerL = belongsToOuter(vL[0],vL[1]);
306
      int outerR = belongsToOuter(vR[0],vR[1]);
525
      float[] outerL = retOuterVector(component,curr);
526
      float[] outerR = retOuterVector(component,next);
307 527

  
308
      if( outerL>=0 && outerR>=0 )
528
      if( outerL!=null && outerR!=null )
309 529
        {
310
        float[] vl =mOuterVectors[outerL];
311
        normL[0] = -vl[0];
312
        normL[1] = -vl[1];
313
        float[] vr =mOuterVectors[outerR];
314
        normR[0] = -vr[0];
315
        normR[1] = -vr[1];
530
        normL[0] = -outerL[0];
531
        normL[1] = -outerL[1];
532
        normR[0] = -outerR[0];
533
        normR[1] = -outerR[1];
316 534
        }
317 535
      else
318 536
        {
......
367 585
        }
368 586
      else
369 587
        {
370
        int outerT = belongsToOuter(vT[0],vT[1]);
588
        float[] outerT = retOuterVector(component,curr);
371 589

  
372
        if( outerT>=0 )
590
        if( outerT!=null )
373 591
          {
374
          float[] vt =mOuterVectors[outerT];
375
          normL[0]= vt[0];
376
          normL[1]= vt[1];
377
          normR[0]= vt[0];
378
          normR[1]= vt[1];
592
          normL[0]= outerT[0];
593
          normL[1]= outerT[1];
594
          normR[0]= outerT[0];
595
          normR[1]= outerT[1];
379 596
          }
380 597
        else
381 598
          {
......
394 611

  
395 612
///////////////////////////////////////////////////////////////////////////////////////////////////
396 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

  
397 680
///////////////////////////////////////////////////////////////////////////////////////////////////
398 681
/**
399 682
 * Specify several lists of vertices. Each list defines one polygon. (@see MeshPolygon).
......
413 696
    for(float[] vertex : vertices) numTriangles+=vertex.length/2;
414 697
    MeshBandedTriangle[] triangles = new MeshBandedTriangle[numTriangles];
415 698

  
416
    computeOuterVertices(vertices);
417
    computeOuterVectors();
418

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

  
702
    computeEdgeVectors(vertices,edgesUp);
703

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

  

Also available in: Unified diff