Project

General

Profile

« Previous | Next » 

Revision fe3dec09

Added by Leszek Koltunski about 2 years ago

use MeshMultigon in puzzle cubits (FactoryCubit)

View differences:

src/main/java/org/distorted/objectlib/helpers/FactoryCubit.java
17 17
import org.distorted.library.helpers.QuatHelper;
18 18
import org.distorted.library.mesh.MeshBase;
19 19
import org.distorted.library.mesh.MeshJoined;
20
import org.distorted.library.mesh.MeshMultigon;
20 21
import org.distorted.library.mesh.MeshPolygon;
21 22
import org.distorted.library.type.Static3D;
22 23
import org.distorted.library.type.Static4D;
......
41 42

  
42 43
  public static final String NAME = EffectName.DEFORM.name();
43 44

  
44
  public static class StickerCoords
45
  private static class StickerCoords
45 46
    {
46 47
    float[] vertices;
48
    float[][] fullVertices;
47 49
    float scale;
48 50
    boolean outer;
49 51
    }
......
187 189

  
188 190
///////////////////////////////////////////////////////////////////////////////////////////////////
189 191

  
192
  private float[] detectFirstOuterVertex(float[][] vertices)
193
    {
194
    float X = -Float.MAX_VALUE;
195
    int I=0,J=0, len = vertices.length;
196

  
197
    for(int i=0; i<len; i++ )
198
      {
199
      float[] v = vertices[i];
200
      int num = v.length/2;
201

  
202
      for(int j=0; j<num; j++)
203
        if(v[2*j]>X)
204
          {
205
          X = v[2*j];
206
          I = i;
207
          J = j;
208
          }
209
      }
210

  
211
    float[] v = vertices[I];
212
    return new float[] {v[2*J],v[2*J+1]};
213
    }
214

  
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216

  
217
  private double computeAngle(float x1,float y1, float x2, float y2)
218
    {
219
    double diff = Math.atan2(y2,x2)-Math.atan2(y1,x1);
220
    return diff<0 ? diff+(2*Math.PI) : diff;
221
    }
222

  
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224

  
225
  private float[] detectNextOuterVertex(float[][] vertices, float[] curr, float[] vect)
226
    {
227
    double minAngle = 2*Math.PI;
228
    float x=0, y=0;
229

  
230
    for( float[] v : vertices )
231
      {
232
      int num = v.length/2;
233

  
234
      for( int j=0; j<num; j++)
235
        {
236
        float xc = v[2*j];
237
        float yc = v[2*j+1];
238

  
239
        if( xc==curr[0] && yc==curr[1])
240
          {
241
          int n = (j==num-1 ? 0 : j+1);
242
          float xn = v[2*n];
243
          float yn = v[2*n+1];
244

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

  
247
          if (angle < minAngle)
248
            {
249
            minAngle = angle;
250
            x = xn;
251
            y = yn;
252
            }
253

  
254
          break;
255
          }
256
        }
257
      }
258

  
259
    return new float[] {x,y};
260
    }
261

  
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263
// same as in MeshMultigon
264

  
265
  private float[] computeOuterEdge(float[][] vertices)
266
    {
267
    ArrayList<float[]> tmp = new ArrayList<>();
268

  
269
    float[] vect = new float[] {1,0};
270
    float[] first= detectFirstOuterVertex(vertices);
271
    float[] next = first;
272

  
273
    do
274
      {
275
      float[] prev = next;
276
      next = detectNextOuterVertex(vertices,next,vect);
277
      vect[0] = prev[0]-next[0];
278
      vect[1] = prev[1]-next[1];
279
      tmp.add(next);
280
      }
281
    while( next[0]!=first[0] || next[1]!=first[1] );
282

  
283
    int num = tmp.size();
284
    float[] ret = new float[2*num];
285

  
286
    for(int i=0; i<num; i++)
287
      {
288
      float[] t = tmp.remove(0);
289
      ret[2*i  ] = t[0];
290
      ret[2*i+1] = t[1];
291
      }
292

  
293
    return ret;
294
    }
295

  
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297
// polygon
298

  
190 299
  private void fitInSquare(FaceTransform info, float[][] vert3D, boolean isOuter)
191 300
    {
192 301
    float minX = Float.MAX_VALUE;
......
221 330
    sInfo.outer = isOuter;
222 331
    sInfo.scale = info.scale;
223 332
    sInfo.vertices = new float[2*len];
333
    sInfo.fullVertices = null;
224 334

  
225 335
    for( int vertex=0; vertex<len; vertex++ )
226 336
      {
......
233 343
    info.sticker = mStickerCoords.size() -1;
234 344
    }
235 345

  
346

  
236 347
///////////////////////////////////////////////////////////////////////////////////////////////////
348
// multigon
349

  
350
  private void fitInSquare(FaceTransform info, float[][][] vert3D, boolean isOuter)
351
    {
352
    float minX = Float.MAX_VALUE;
353
    float maxX =-Float.MAX_VALUE;
354
    float minY = Float.MAX_VALUE;
355
    float maxY =-Float.MAX_VALUE;
356

  
357
    for( float[][] vert : vert3D)
358
      for( float[] v : vert)
359
        {
360
        float x = v[0];
361
        float y = v[1];
362

  
363
        if (x > maxX) maxX = x;
364
        if (x < minX) minX = x;
365
        if (y > maxY) maxY = y;
366
        if (y < minY) minY = y;
367
        }
368

  
369
    minX = minX<0 ? -minX:minX;
370
    maxX = maxX<0 ? -maxX:maxX;
371
    minY = minY<0 ? -minY:minY;
372
    maxY = maxY<0 ? -maxY:maxY;
373

  
374
    float max1 = Math.max(minX,minY);
375
    float max2 = Math.max(maxX,maxY);
376
    float max3 = Math.max(max1,max2);
377

  
378
    info.scale = max3/0.5f;
379

  
380
    int len = vert3D.length;
381
    StickerCoords sInfo = new StickerCoords();
382
    sInfo.outer = isOuter;
383
    sInfo.scale = info.scale;
384
    sInfo.fullVertices = new float[len][];
385

  
386
    for( int comp=0; comp<len; comp++ )
387
      {
388
      float[][] vert = vert3D[comp];
389
      int num = vert.length;
390
      sInfo.fullVertices[comp] = new float[2*num];
391
      float[] t = sInfo.fullVertices[comp];
392

  
393
      for( int vertex=0; vertex<num; vertex++)
394
        {
395
        t[2*vertex  ] = vert[vertex][0] / info.scale;
396
        t[2*vertex+1] = vert[vertex][1] / info.scale;
397
        }
398
      }
399

  
400
    sInfo.vertices = computeOuterEdge(sInfo.fullVertices);
401

  
402
    mStickerCoords.add(sInfo);
403

  
404
    info.sticker = mStickerCoords.size() -1;
405
    }
406

  
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408
// polygon
237 409

  
238 410
  private FaceTransform constructNewTransform(final float[][] vert3D, boolean isOuter, int face, int numFaces)
239 411
    {
......
355 527
    return ft;
356 528
    }
357 529

  
530
///////////////////////////////////////////////////////////////////////////////////////////////////
531
// multigon
532

  
533
  private FaceTransform constructNewTransform(final float[][][] vert3D, boolean isOuter, int face, int numFaces)
534
    {
535
    FaceTransform ft = new FaceTransform();
536
    ft.face = face;
537
    ft.numFaces = numFaces;
538

  
539
    // compute center of gravity
540
    ft.vx = 0.0f;
541
    ft.vy = 0.0f;
542
    ft.vz = 0.0f;
543
    int len = 0;
544

  
545
    for( float[][] vert : vert3D )
546
      for( float[] v : vert )
547
        {
548
        ft.vx += v[0];
549
        ft.vy += v[1];
550
        ft.vz += v[2];
551
        len++;
552
        }
553

  
554
    ft.vx /= len;
555
    ft.vy /= len;
556
    ft.vz /= len;
557

  
558
    // move all vertices so that their center of gravity is at (0,0,0)
559
    for( float[][] vert : vert3D )
560
      for( float[] v : vert )
561
        {
562
        v[0] -= ft.vx;
563
        v[1] -= ft.vy;
564
        v[2] -= ft.vz;
565
        }
566

  
567
    // find 3 non-colinear vertices
568
    int foundIndex = -1;
569
    len = vert3D[0].length;
570

  
571
    for(int vertex=2; vertex<len; vertex++)
572
      {
573
      if( !areColinear(vert3D[0],0,1,vertex) )
574
        {
575
        foundIndex = vertex;
576
        break;
577
        }
578
      }
579

  
580
    // compute the normal vector
581
    if( foundIndex==-1 )
582
      {
583
      StringBuilder sb = new StringBuilder();
584

  
585
      for (float[] v : vert3D[0])
586
        {
587
        sb.append(' ');
588
        sb.append("(");
589
        sb.append(v[0]);
590
        sb.append(" ");
591
        sb.append(v[1]);
592
        sb.append(" ");
593
        sb.append(v[2]);
594
        sb.append(")");
595
        }
596
      android.util.Log.e("D", "verts: "+sb);
597

  
598
      throw new RuntimeException("all vertices colinear");
599
      }
600

  
601
    computeNormalVector(vert3D[0],0,1,foundIndex);
602

  
603
    // rotate so that the normal vector becomes (0,0,1)
604
    float axisX, axisY, axisZ;
605

  
606
    if( mBuffer[0]!=0.0f || mBuffer[1]!=0.0f )
607
      {
608
      axisX = -mBuffer[1];
609
      axisY =  mBuffer[0];
610
      axisZ = 0.0f;
611

  
612
      float axiLen = axisX*axisX + axisY*axisY;
613
      axiLen = (float)Math.sqrt(axiLen);
614
      axisX /= axiLen;
615
      axisY /= axiLen;
616
      axisZ /= axiLen;
617
      }
618
    else
619
      {
620
      axisX = 0.0f;
621
      axisY = 1.0f;
622
      axisZ = 0.0f;
623
      }
624

  
625
    float cosTheta = mBuffer[2];
626
    float sinTheta = (float)Math.sqrt(1-cosTheta*cosTheta);
627
    float sinHalfTheta = computeSinHalf(cosTheta);
628
    float cosHalfTheta = computeCosHalf(sinTheta,cosTheta);
629

  
630
    mQuat1[0] = axisX*sinHalfTheta;
631
    mQuat1[1] = axisY*sinHalfTheta;
632
    mQuat1[2] = axisZ*sinHalfTheta;
633
    mQuat1[3] = cosHalfTheta;
634
    mQuat2[0] =-axisX*sinHalfTheta;
635
    mQuat2[1] =-axisY*sinHalfTheta;
636
    mQuat2[2] =-axisZ*sinHalfTheta;
637
    mQuat2[3] = cosHalfTheta;
638

  
639
    for( float[][] vert : vert3D)
640
      for( float[] v : vert)
641
        {
642
        QuatHelper.quatMultiply(mQuat3, mQuat1, v  );
643
        QuatHelper.quatMultiply(  v, mQuat3, mQuat2);
644
        }
645

  
646
    // fit the whole thing in a square and remember the scale & 2D vertices
647
    fitInSquare(ft, vert3D, isOuter);
648

  
649
    // remember the rotation
650
    ft.qx =-mQuat1[0];
651
    ft.qy =-mQuat1[1];
652
    ft.qz =-mQuat1[2];
653
    ft.qw = mQuat1[3];
654

  
655
    return ft;
656
    }
657

  
358 658
///////////////////////////////////////////////////////////////////////////////////////////////////
359 659

  
360 660
  private void rotateAllVertices(float[] result, int len, float[] vertices, float sin, float cos)
361 661
    {
362 662
    for(int i=0; i<len; i++)
363 663
      {
364
      result[2*i  ] = vertices[2*i  ]*cos - vertices[2*i+1]*sin;
365
      result[2*i+1] = vertices[2*i  ]*sin + vertices[2*i+1]*cos;
664
      float x = vertices[2*i];
665
      float y = vertices[2*i+1];
666
      result[2*i  ] = x*cos - y*sin;
667
      result[2*i+1] = x*sin + y*cos;
366 668
      }
367 669
    }
368 670

  
......
577 879
    }
578 880

  
579 881
///////////////////////////////////////////////////////////////////////////////////////////////////
882
// polygon
580 883

  
581 884
  private float[][] constructVert(float[][] vertices, int[] index)
582 885
    {
......
595 898
    return ret;
596 899
    }
597 900

  
901
///////////////////////////////////////////////////////////////////////////////////////////////////
902
// multigon
903

  
904
  private float[][][] constructVert(float[][] vertices, int[][] index)
905
    {
906
    int len = index.length;
907
    float[][][] ret = new float[len][][];
908

  
909
    for(int i=0; i<len; i++)
910
      {
911
      int[] ind = index[i];
912
      int num = ind.length;
913
      ret[i] = new float[num][4];
914

  
915
      for(int j=0; j<num; j++)
916
        {
917
        float[] r = ret[i][j];
918
        float[] v = vertices[ind[j]];
919
        r[0] = v[0];
920
        r[1] = v[1];
921
        r[2] = v[2];
922
        r[3] = 1.0f;
923
        }
924
      }
925

  
926
    return ret;
927
    }
928

  
598 929
///////////////////////////////////////////////////////////////////////////////////////////////////
599 930

  
600 931
  private void applyVertexEffects(MeshBase mesh, ObjectVertexEffects effects, int meshState)
......
796 1127
  public static FactoryCubit getInstance()
797 1128
    {
798 1129
    if( mThis==null ) mThis = new FactoryCubit();
799

  
800 1130
    return mThis;
801 1131
    }
802 1132

  
......
982 1312
    {
983 1313
    float[][] vertices = shape.getVertices();
984 1314
    int[][] indices = shape.getVertIndices();
1315
    int[][][] fullIndices = shape.getMultigonIndices();
1316
    boolean isMultigon = shape.isMultigon();
985 1317
    FaceTransform ft;
986 1318
    int numNew = mNewFaceTransf.size();
987 1319

  
......
991 1323
      mOldFaceTransf.add(ft);
992 1324
      }
993 1325

  
994
    int numFaces = indices.length;
1326
    int numFaces = shape.getNumFaces();
995 1327
    int numOld = mOldFaceTransf.size();
996 1328

  
997 1329
    for (int face=0; face<numFaces; face++)
998 1330
      {
999 1331
      boolean collapsed = false;
1000 1332
      boolean isOuter = (outer!=null && outer[face]>0);
1001
      float[][] vert = constructVert(vertices, indices[face]);
1002
      FaceTransform newT = constructNewTransform(vert,isOuter,face,numFaces);
1333
      FaceTransform newT;
1334

  
1335
      if( !isMultigon )
1336
        {
1337
        float[][] vert = constructVert(vertices, indices[face]);
1338
        newT = constructNewTransform(vert,isOuter,face,numFaces);
1339
        }
1340
      else
1341
        {
1342
        float[][][] vert = constructVert(vertices, fullIndices[face]);
1343
        newT = constructNewTransform(vert,isOuter,face,numFaces);
1344
        }
1003 1345

  
1004 1346
      for (int old=0; !collapsed && old<numOld; old++)
1005 1347
        {
......
1022 1364
  public MeshBase createRoundedSolid(final ObjectShape shape, final ObjectFaceShape faceShape,
1023 1365
                                     final ObjectVertexEffects effects, int meshState, int numComponents)
1024 1366
    {
1025
    int[][] vertIndexes     = shape.getVertIndices();
1026 1367
    float[][] bands         = faceShape.getBands();
1027 1368
    int[]   bandIndexes     = faceShape.getBandIndices();
1028 1369
    float[] convexityCenter = faceShape.getConvexityCenter();
1029 1370

  
1030
    int numFaces = vertIndexes.length;
1371
    int numFaces = shape.getNumFaces();
1372
    boolean multigonMode = shape.isMultigon();
1031 1373
    float[] band, bandsComputed;
1032 1374
    MeshBase[] meshes = new MeshBase[numFaces];
1033 1375
    FaceTransform fInfo;
......
1039 1381
    for(int face=0; face<numFaces; face++)
1040 1382
      {
1041 1383
      fInfo = mNewFaceTransf.get(face);
1042
      sInfo = mStickerCoords.get(fInfo.sticker);
1043

  
1044
      float[] verts = sInfo.vertices;
1045
      int lenVerts = verts.length;
1046
      float[] copiedVerts = new float[lenVerts];
1047
      System.arraycopy(verts, 0, copiedVerts, 0, lenVerts);
1048

  
1049 1384
      computeConvexityCenter(convexXY,convexityCenter,fInfo);
1050 1385

  
1051 1386
      int index = bandIndexes[face];
......
1073 1408
        }
1074 1409

  
1075 1410
      bandsComputed = computeBands(height,alpha,dist,K,N);
1076
      meshes[face] = new MeshPolygon(copiedVerts,bandsComputed,null,null,exIndex,exVertices, convexXY[0], convexXY[1]);
1411

  
1412
      if( !multigonMode )
1413
        {
1414
        sInfo = mStickerCoords.get(fInfo.sticker);
1415
        float[] verts = sInfo.vertices;
1416
        int lenVerts = verts.length;
1417
        float[] copiedVerts = new float[lenVerts];
1418
        System.arraycopy(verts, 0, copiedVerts, 0, lenVerts);
1419
        meshes[face] = new MeshPolygon(copiedVerts,bandsComputed,null,null,exIndex,exVertices, convexXY[0], convexXY[1]);
1420
        }
1421
      else
1422
        {
1423
        sInfo = mStickerCoords.get(fInfo.sticker);
1424
        float[][] verts = sInfo.fullVertices;
1425
        int lenVerts = verts.length;
1426
        float[][] copiedVerts = new float[lenVerts][];
1427

  
1428
        for(int i=0; i<lenVerts; i++)
1429
          {
1430
          float[] v = verts[i];
1431
          int len = v.length;
1432
          copiedVerts[i] = new float[len];
1433
          System.arraycopy(v, 0, copiedVerts[i], 0, len);
1434
          }
1435

  
1436
        meshes[face] = new MeshMultigon(copiedVerts,bandsComputed,exIndex,exVertices);
1437
        }
1438

  
1077 1439
      meshes[face].setEffectAssociation(0,0,face);
1078 1440
      }
1079 1441

  
src/main/java/org/distorted/objectlib/helpers/ObjectShape.java
24 24
  private final float[][] mVertices;
25 25
  private final int[][] mVertIndices;
26 26

  
27
  private final boolean mFacesMultigon;
28
  private final int mNumFaces;
29
  private final int[][][] mMultigonIndices;
30

  
27 31
///////////////////////////////////////////////////////////////////////////////////////////////////
28 32

  
29 33
  public ObjectShape(float[][] vertices, int[][] vertIndices)
30 34
    {
31
    mVertices   = vertices;
32
    mVertIndices= vertIndices;
35
    mVertices        = vertices;
36
    mVertIndices     = vertIndices;
37
    mMultigonIndices = null;
38
    mFacesMultigon   = false;
39
    mNumFaces        = vertIndices.length;
40
    }
41

  
42
///////////////////////////////////////////////////////////////////////////////////////////////////
43

  
44
  public ObjectShape(float[][] vertices, int[][][] vertIndices)
45
    {
46
    mVertices       = vertices;
47
    mVertIndices    = null;
48
    mMultigonIndices= vertIndices;
49
    mFacesMultigon  = true;
50
    mNumFaces       = vertIndices.length;
51
    }
52

  
53
///////////////////////////////////////////////////////////////////////////////////////////////////
54

  
55
  public int getNumFaces()
56
    {
57
    return mNumFaces;
58
    }
59

  
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61

  
62
  public boolean isMultigon()
63
    {
64
    return mFacesMultigon;
33 65
    }
34 66

  
35 67
///////////////////////////////////////////////////////////////////////////////////////////////////
......
46 78
    return mVertIndices;
47 79
    }
48 80

  
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82

  
83
  public int[][][] getMultigonIndices()
84
    {
85
    return mMultigonIndices;
86
    }
87

  
49 88
///////////////////////////////////////////////////////////////////////////////////////////////////
50 89

  
51 90
  public static int computeNumComponents(ObjectShape[] shapes)

Also available in: Unified diff