Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / helpers / FactoryBandagedCuboid.java @ 3821ebef

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.helpers;
11

    
12
import java.util.ArrayList;
13

    
14
import org.distorted.library.mesh.MeshBase;
15
import org.distorted.library.type.Static3D;
16
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
17

    
18
import static org.distorted.objectlib.main.TwistyObject.MESH_NICE;
19

    
20
///////////////////////////////////////////////////////////////////////////////////////////////////
21

    
22
public class FactoryBandagedCuboid
23
  {
24
  private static final int WALL_MARKED=0;
25
  private static final int WALL_EMPTY =-1;
26

    
27
  private static final int AXIS_XP = 0;
28
  private static final int AXIS_XM = 1;
29
  private static final int AXIS_YP = 2;
30
  private static final int AXIS_YM = 3;
31
  private static final int AXIS_ZP = 4;
32
  private static final int AXIS_ZM = 5;
33

    
34
  private static final float[][] VECTOR =
35
      {
36
          {-1.0f,-1.0f,-1.0f},
37
          {-1.0f,-1.0f,+1.0f},
38
          {-1.0f,+1.0f,-1.0f},
39
          {-1.0f,+1.0f,+1.0f},
40
          {+1.0f,-1.0f,-1.0f},
41
          {+1.0f,-1.0f,+1.0f},
42
          {+1.0f,+1.0f,-1.0f},
43
          {+1.0f,+1.0f,+1.0f}
44
      };
45

    
46
  private static FactoryBandagedCuboid mThis;
47
  private BandagedElementCuboid[] mElements;
48
  private ArrayList<float[][]> mVertexArray;
49
  private ArrayList<float[]> mTmpArray;
50

    
51
  private float[][][] mVertices;
52
  private int[][][][] mIndices;
53
  private int[][] mBandIndices;
54
  private float[][] mMove;
55
  private int mX, mY, mZ, mMax;
56
  private float dX, dY, dZ;
57
  private int[][] mWall;
58
  private float[][] mCuts;
59
  private float[][] mNormal;
60
  private int mNumElements;
61
  private int[][] mFaceBelongsBitmap;
62

    
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64

    
65
  private FactoryBandagedCuboid()
66
    {
67

    
68
    }
69

    
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71

    
72
  public float[][] getCuts(int[] numLayers)
73
    {
74
    int numFaces = 6;
75
    float[][] cuts = new float[numFaces][];
76

    
77
    for(int axis=0; axis<numFaces; axis++)
78
      {
79
      int len = numLayers[axis/2];
80
      float start = 1-len*0.5f;
81

    
82
      if( len>=2 )
83
        {
84
        cuts[axis] = new float[len-1];
85
        for(int i=0; i<len-1; i++) cuts[axis][i] = start+i;
86
        }
87
      }
88

    
89
    return cuts;
90
    }
91

    
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93

    
94
  private void createNormal()
95
    {
96
    if( mNormal==null )
97
      {
98
      mNormal = new float[][]
99
        {
100
          { 1, 0, 0 },
101
          {-1, 0, 0 },
102
          { 0, 1, 0 },
103
          { 0,-1, 0 },
104
          { 0, 0, 1 },
105
          { 0, 0,-1 }
106
        };
107
      }
108
    }
109

    
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111

    
112
  private void computeMove(float[] pos, int variant)
113
    {
114
    int numMoves = pos.length/3;
115
    float[] m = mMove[variant];
116
    m[0]=0.0f;
117
    m[1]=0.0f;
118
    m[2]=0.0f;
119

    
120
    for(int i=0; i<numMoves; i++)
121
      {
122
      m[0] += pos[3*i  ];
123
      m[1] += pos[3*i+1];
124
      m[2] += pos[3*i+2];
125
      }
126

    
127
    m[0]/=numMoves;
128
    m[1]/=numMoves;
129
    m[2]/=numMoves;
130
    }
131

    
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133

    
134
  private float[][] getVertices(ArrayList<float[][]> list, int variant)
135
    {
136
    int total  = 0;
137
    int length = list.size();
138
    float[][][] vertices = new float[length][][];
139

    
140
    for( int i=0; i<length; i++ )
141
      {
142
      vertices[i] = list.get(i);
143
      int len = vertices[i].length;
144
      for(int j=0; j<len; j++) total += vertices[i][j].length/3;
145
      }
146

    
147
    float[][] verts = new float[total][3];
148
    int pointer = 0;
149

    
150
    for(int i=0; i<length; i++)
151
      {
152
      int len = vertices[i].length;
153

    
154
      for(int j=0; j<len; j++)
155
        {
156
        float[] v = vertices[i][j];
157
        int l = v.length/3;
158

    
159
        for(int k=0; k<l; k++)
160
          {
161
          verts[pointer][0] = v[3*k  ] - mMove[variant][0];
162
          verts[pointer][1] = v[3*k+1] - mMove[variant][1];
163
          verts[pointer][2] = v[3*k+2] - mMove[variant][2];
164
          pointer++;
165
          }
166
        }
167
      }
168

    
169
    return verts;
170
    }
171

    
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173

    
174
  private int[][][] getIndices(ArrayList<float[][]> list)
175
    {
176
    int indicesSoFar=0;
177
    int length = list.size();
178
    int[][][] indices = new int[length][][];
179

    
180
    for( int i=0; i<length; i++ )
181
      {
182
      float[][] face = list.get(i);
183
      int len = face.length;
184
      int[][] ind = new int[len][];
185

    
186
      for(int j=0; j<len; j++)
187
        {
188
        int l = face[j].length/3;
189
        ind[j] = new int[l];
190
        for(int k=0; k<l; k++) ind[j][k] = (indicesSoFar++);
191
        }
192

    
193
      indices[i] = ind;
194
      }
195

    
196
    return indices;
197
    }
198

    
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

    
201
  private void markAllVertices(float[] vertex, float[][] vertices, int[][][] indices, int pointer, int variant)
202
    {
203
    int numFaces = indices.length;
204

    
205
    for(int face=0; face<numFaces; face++)
206
      {
207
      int len = indices[face].length;
208

    
209
      for(int comp=0; comp<len; comp++)
210
        {
211
        int l = indices[face][comp].length;
212

    
213
        for(int v=0; v<l; v++)
214
          {
215
          if( mIndices[variant][face][comp][v]==-1 )
216
            {
217
            int ind=indices[face][comp][v];
218
            float[] ver=vertices[ind];
219

    
220
            if(vertex[0]==ver[0] && vertex[1]==ver[1] && vertex[2]==ver[2])
221
              {
222
              mIndices[variant][face][comp][v]=pointer;
223
              }
224
            }
225
          }
226
        }
227
      }
228
    }
229

    
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231
// So far the 'vertices/indices' are stored inefficiently, with each vertex stored three times
232
// (each one normally is a corner of three faces) or even six times. Compress!
233
// Example of six times: the central vertex here:
234
//
235
// { 1.0f,  0.0f, -1.0f,
236
//   1.0f, -1.0f, -1.0f,
237
//   1.0f, -1.0f, +0.0f,
238
//   0.0f, -1.0f, -1.0f },
239

    
240
  private void compressVerticesAndIndices(int variant, float[][] vertices, int[][][] indices)
241
    {
242
    if( mTmpArray==null ) mTmpArray = new ArrayList<>();
243

    
244
    int numFaces = indices.length;
245
    int pointer=0;
246

    
247
    mIndices[variant] = new int[numFaces][][];
248

    
249
    for(int face=0; face<numFaces;face++)
250
      {
251
      int len = indices[face].length;
252
      mIndices[variant][face] = new int[len][];
253

    
254
      for(int comp=0; comp<len; comp++)
255
        {
256
        int l = indices[face][comp].length;
257
        mIndices[variant][face][comp] = new int[l];
258
        for(int v=0; v<l; v++) mIndices[variant][face][comp][v] = -1;
259
        }
260
      }
261

    
262
    for(int face=0; face<numFaces; face++)
263
      {
264
      int len = indices[face].length;
265

    
266
      for(int comp=0; comp<len; comp++)
267
        {
268
        int l = indices[face][comp].length;
269

    
270
        for(int v=0; v<l; v++)
271
          {
272
          if( mIndices[variant][face][comp][v]==-1 )
273
            {
274
            int ind=indices[face][comp][v];
275
            float[] ver=vertices[ind];
276
            mTmpArray.add(ver);
277
            markAllVertices(ver, vertices, indices, pointer, variant);
278
            pointer++;
279
            }
280
          }
281
        }
282
      }
283

    
284
    int len = mTmpArray.size();
285
    mVertices[variant] = new float[len][];
286

    
287
    for(int i=0; i<len; i++)
288
      {
289
      mVertices[variant][i] = mTmpArray.remove(0);
290
      }
291
    }
292

    
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294

    
295
  private boolean elementExists(int x, int y, int z)
296
    {
297
    for(int i=0; i<mNumElements; i++)
298
      {
299
      int[] row = mElements[i].getRotRow();
300
      if( row[0]==x && row[2]==y && row[4]==z ) return true;
301
      }
302

    
303
    return false;
304
    }
305

    
306
///////////////////////////////////////////////////////////////////////////////////////////////////
307

    
308
  private void createRight(int x, ArrayList<float[][]> list)
309
    {
310
    for(int i=0; i<mMax; i++)
311
      for(int j=0; j<mMax; j++) mWall[i][j] = WALL_EMPTY;
312

    
313
    for(int i=0; i<mNumElements; i++)
314
      {
315
      int[] row = mElements[i].getRotRow();
316

    
317
      if( row[0]==x )
318
        {
319
        int y = mY-1-row[2];
320
        int z = mZ-1-row[4];
321
        mWall[z][y] = elementExists(x+1,row[2],row[4]) ? WALL_EMPTY : WALL_MARKED;
322
        }
323
      }
324

    
325
    createVertices(list,mWall,AXIS_XP,x);
326
    }
327

    
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329

    
330
  private void createLeft(int x, ArrayList<float[][]> list)
331
    {
332
    for(int i=0; i<mMax; i++)
333
      for(int j=0; j<mMax; j++) mWall[i][j] = WALL_EMPTY;
334

    
335
    for(int i=0; i<mNumElements; i++)
336
      {
337
      int[] row = mElements[i].getRotRow();
338

    
339
      if( row[0]==x )
340
        {
341
        int y = mY-1-row[2];
342
        int z = row[4];
343
        mWall[z][y] = elementExists(x-1,row[2],row[4]) ? WALL_EMPTY : WALL_MARKED;
344
        }
345
      }
346

    
347
    createVertices(list,mWall,AXIS_XM,x);
348
    }
349

    
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351

    
352
  private void createTop(int y, ArrayList<float[][]> list)
353
    {
354
    for(int i=0; i<mMax; i++)
355
      for(int j=0; j<mMax; j++) mWall[i][j] = WALL_EMPTY;
356

    
357
    for(int i=0; i< mNumElements; i++)
358
      {
359
      int[] row = mElements[i].getRotRow();
360

    
361
      if( row[2]==y )
362
        {
363
        int x = row[0];
364
        int z = row[4];
365
        mWall[x][z] = elementExists(row[0],y+1,row[4]) ? WALL_EMPTY : WALL_MARKED;
366
        }
367
      }
368

    
369
    createVertices(list,mWall,AXIS_YP,y);
370
    }
371

    
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373

    
374
  private void createBottom(int y, ArrayList<float[][]> list)
375
    {
376
    for(int i=0; i<mMax; i++)
377
      for(int j=0; j<mMax; j++) mWall[i][j] = WALL_EMPTY;
378

    
379
    for(int i=0; i<mNumElements; i++)
380
      {
381
      int[] row = mElements[i].getRotRow();
382

    
383
      if( row[2]==y )
384
        {
385
        int x = row[0];
386
        int z = mZ-1-row[4];
387
        mWall[x][z] = elementExists(row[0],y-1,row[4]) ? WALL_EMPTY : WALL_MARKED;
388
        }
389
      }
390

    
391
    createVertices(list,mWall,AXIS_YM,y);
392
    }
393

    
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395

    
396
  private void createFront(int z, ArrayList<float[][]> list)
397
    {
398
    for(int i=0; i<mMax; i++)
399
      for(int j=0; j<mMax; j++) mWall[i][j] = WALL_EMPTY;
400

    
401
    for(int i=0; i<mNumElements; i++)
402
      {
403
      int[] row = mElements[i].getRotRow();
404

    
405
      if( row[4]==z )
406
        {
407
        int x = row[0];
408
        int y = mY-1-row[2];
409
        mWall[x][y] = elementExists(row[0],row[2],z+1) ? WALL_EMPTY : WALL_MARKED;
410
        }
411
      }
412

    
413
    createVertices(list,mWall,AXIS_ZP,z);
414
    }
415

    
416
///////////////////////////////////////////////////////////////////////////////////////////////////
417

    
418
  private void createBack(int z, ArrayList<float[][]> list)
419
    {
420
    for(int i=0; i<mMax; i++)
421
      for(int j=0; j<mMax; j++) mWall[i][j] = WALL_EMPTY;
422

    
423
    for(int i=0; i<mNumElements; i++)
424
      {
425
      int[] row = mElements[i].getRotRow();
426

    
427
      if( row[4]==z )
428
        {
429
        int x = mX-1-row[0];
430
        int y = mY-1-row[2];
431
        mWall[x][y] = elementExists(row[0],row[2],z-1) ? WALL_EMPTY : WALL_MARKED;
432
        }
433
      }
434

    
435
    createVertices(list,mWall,AXIS_ZM,z);
436
    }
437

    
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439

    
440
  private void markNeighbours(int[][] wall, int x, int y, int section)
441
    {
442
    wall[x][y] = section;
443

    
444
    if( x  >   0 && wall[x-1][y]==WALL_MARKED ) markNeighbours(wall,x-1,y,section);
445
    if( x+1<mMax && wall[x+1][y]==WALL_MARKED ) markNeighbours(wall,x+1,y,section);
446
    if( y  >   0 && wall[x][y-1]==WALL_MARKED ) markNeighbours(wall,x,y-1,section);
447
    if( y+1<mMax && wall[x][y+1]==WALL_MARKED ) markNeighbours(wall,x,y+1,section);
448
    }
449

    
450
///////////////////////////////////////////////////////////////////////////////////////////////////
451

    
452
  private int markSections(int[][] wall)
453
    {
454
    int sections = 0;
455

    
456
    for(int x=0; x<mMax; x++)
457
      for(int y=0; y<mMax; y++)
458
        if( wall[x][y]==WALL_MARKED )
459
          {
460
          sections++;
461
          markNeighbours(wall,x,y,sections);
462
          }
463

    
464
    return sections;
465
    }
466

    
467
///////////////////////////////////////////////////////////////////////////////////////////////////
468

    
469
  private float[][] buildVertices(int[][] wall, int section, float dx, float dy)
470
    {
471
    int numMarked = howManyMarked(wall,section);
472
    float[][] vertices = new float[numMarked][];
473
    int curr=0;
474

    
475
    for(int x=0; x<mMax; x++)
476
      for(int y=0; y<mMax; y++)
477
        if( wall[x][y]==section )
478
          {
479
          vertices[curr] = new float[12];
480

    
481
          vertices[curr][ 0] = x-dx;
482
          vertices[curr][ 1] = dy-y;
483
          vertices[curr][ 2] = 0.0f;
484

    
485
          vertices[curr][ 3] = x-dx;
486
          vertices[curr][ 4] = dy-y-1;
487
          vertices[curr][ 5] = 0.0f;
488

    
489
          vertices[curr][ 6] = x-dx+1;
490
          vertices[curr][ 7] = dy-y-1;
491
          vertices[curr][ 8] = 0.0f;
492

    
493
          vertices[curr][ 9] = x-dx+1;
494
          vertices[curr][10] = dy-y;
495
          vertices[curr][11] = 0.0f;
496

    
497
          curr++;
498
          }
499

    
500
    return vertices;
501
    }
502

    
503
///////////////////////////////////////////////////////////////////////////////////////////////////
504

    
505
  private int howManyMarked(int[][] wall, int section)
506
    {
507
    int numMarked=0;
508

    
509
    for(int x=0; x<mMax; x++)
510
      for(int y=0; y<mMax; y++)
511
        if( wall[x][y]==section ) numMarked++;
512

    
513
    return numMarked;
514
    }
515

    
516
///////////////////////////////////////////////////////////////////////////////////////////////////
517

    
518
  private void rotateAndMoveVertices(float[][] vertices, int axis, int layer)
519
    {
520
    int i,len = vertices.length;
521

    
522
    switch(axis)
523
      {
524
      case AXIS_XP: for(i=0; i<len; i++)
525
                      {
526
                      int l = vertices[i].length/3;
527

    
528
                      for(int j=0; j<l; j++)
529
                        {
530
                        vertices[i][3*j+2] = -vertices[i][3*j];
531
                        vertices[i][3*j]   = layer-(dX-1.0f);
532
                        }
533
                      }
534
                    break;
535
      case AXIS_XM: for(i=0; i<len; i++)
536
                      {
537
                      int l = vertices[i].length/3;
538

    
539
                      for(int j=0; j<l; j++)
540
                        {
541
                        vertices[i][3*j+2] = vertices[i][3*j];
542
                        vertices[i][3*j]   = layer-dX;
543
                        }
544
                      }
545
                    break;
546
      case AXIS_YP: for(i=0; i<len; i++)
547
                      {
548
                      int l = vertices[i].length/3;
549

    
550
                      for(int j=0; j<l; j++)
551
                        {
552
                        vertices[i][3*j+2] = -vertices[i][3*j+1];
553
                        vertices[i][3*j+1] = layer-(dY-1.0f);
554
                        }
555
                      }
556
                    break;
557
      case AXIS_YM: for(i=0; i<len; i++)
558
                      {
559
                      int l = vertices[i].length/3;
560

    
561
                      for(int j=0; j<l; j++)
562
                        {
563
                        vertices[i][3*j+2] = vertices[i][3*j+1];
564
                        vertices[i][3*j+1] = layer-dY;
565
                        }
566
                      }
567
                    break;
568
      case AXIS_ZP: for(i=0; i<len; i++)
569
                      {
570
                      int l = vertices[i].length/3;
571

    
572
                      for(int j=0; j<l; j++)
573
                        {
574
                        vertices[i][3*j+2] = layer-(dZ-1.0f);
575
                        }
576
                      }
577
                    break;
578
      case AXIS_ZM: for(i=0; i<len; i++)
579
                      {
580
                      int l = vertices[i].length/3;
581

    
582
                      for(int j=0; j<l; j++)
583
                        {
584
                        vertices[i][3*j+2] = layer-dZ;
585
                        vertices[i][3*j]   = -vertices[i][3*j];
586
                        }
587
                      }
588
                    break;
589
      }
590
    }
591

    
592
///////////////////////////////////////////////////////////////////////////////////////////////////
593
// 1. assume the 'wall' is in the XY plane
594
// 2. split the wall into individual connected regions and for each such region:
595
//   a. build the list of vertices (Z=0)
596
//   b. take the axis into consideration and rotate the vertices.
597
//   c. take layer into consideration and move the vertices.
598
//   d. add the resulting vertices to the list.
599

    
600
  private void createVertices(ArrayList<float[][]> list, int[][] wall, int axis, int layer)
601
    {
602
    int sections = markSections(wall);
603

    
604
    float dx = (axis==AXIS_XP || axis==AXIS_XM) ? dZ : dX;
605
    float dy = (axis==AXIS_YP || axis==AXIS_YM) ? dZ : dY;
606

    
607
    for(int i=0; i<sections; i++)
608
      {
609
      float[][] vertices = buildVertices(wall,i+1,dx,dy);
610
      rotateAndMoveVertices(vertices,axis,layer);
611
      list.add(vertices);
612
      }
613
    }
614

    
615
///////////////////////////////////////////////////////////////////////////////////////////////////
616

    
617
  private static boolean vertInFace(float[] vertex, float[] move, Static3D faceAxis, float dist)
618
    {
619
    final float MAX_ERROR = 0.01f;
620

    
621
    float x= faceAxis.get0();
622
    float y= faceAxis.get1();
623
    float z= faceAxis.get2();
624

    
625
    float a = (vertex[0]+move[0])*x + (vertex[1]+move[1])*y + (vertex[2]+move[2])*z;
626
    float diff = a - dist;
627

    
628
    return diff>-MAX_ERROR && diff<MAX_ERROR;
629
    }
630

    
631
///////////////////////////////////////////////////////////////////////////////////////////////////
632
// (vertices,indices) define a cubit face, i.e. a connected subset of the NxN grid.
633
// Return its 'diameter', i.e. max(width,height)
634

    
635
  private int faceDiameter(float[][] vertices, int[][] indices)
636
    {
637
    float maxX = -dX;
638
    float minX =  dX;
639
    float maxY = -dY;
640
    float minY =  dY;
641
    float maxZ = -dZ;
642
    float minZ =  dZ;
643

    
644
    for (int[] ind : indices)
645
      for(int index : ind)
646
        {
647
        float[] v = vertices[index];
648

    
649
        if (v[0] > maxX) maxX = v[0];
650
        if (v[0] < minX) minX = v[0];
651
        if (v[1] > maxY) maxY = v[1];
652
        if (v[1] < minY) minY = v[1];
653
        if (v[2] > maxZ) maxZ = v[2];
654
        if (v[2] < minZ) minZ = v[2];
655
        }
656

    
657
    float diffX = maxX-minX;
658
    float diffY = maxY-minY;
659
    float diffZ = maxZ-minZ;
660

    
661
    float max = diffX>diffY ? Math.max(diffX,diffZ) : Math.max(diffY,diffZ);
662

    
663
    return (int)max;
664
    }
665

    
666
///////////////////////////////////////////////////////////////////////////////////////////////////
667

    
668
  private int[] computeFaceBelongsBitmap(float[][] vertices, int[][][] indices, float[] move)
669
    {
670
    int numVerts = vertices.length;
671
    int[] ret = new int[numVerts];
672

    
673
    for(int[][] ints : indices)
674
      for(int[] ind : ints)
675
        for(int index : ind)
676
          {
677
          int vertBelongsBitmap=0x00000000;
678
          float[] vert=vertices[index];
679

    
680
          if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[0], dX) ) vertBelongsBitmap |= (1   );
681
          if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[1], dX) ) vertBelongsBitmap |= (1<<1);
682
          if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[2], dY) ) vertBelongsBitmap |= (1<<2);
683
          if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[3], dY) ) vertBelongsBitmap |= (1<<3);
684
          if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[4], dZ) ) vertBelongsBitmap |= (1<<4);
685
          if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[5], dZ) ) vertBelongsBitmap |= (1<<5);
686

    
687
          ret[index]=vertBelongsBitmap;
688
          }
689

    
690
    return ret;
691
    }
692

    
693
///////////////////////////////////////////////////////////////////////////////////////////////////
694
// return array of:
695
// 0 if this is an inner face, 1 if its diameter is 1, 2 if diameter is 2, 3 if 3, etc
696
// but only up to 5 (because the number of bands is 6 - see createIrregularFaceShape() )
697

    
698
  private int[] generateBandIndices(float[][] vertices, int[][][] indices, int[] belongs)
699
    {
700
    int numCubitFaces = indices.length;
701
    int[] bandIndices = new int[numCubitFaces];
702

    
703
    for(int f=0; f<numCubitFaces; f++)
704
      {
705
      bandIndices[f] = 0xffffffff;
706
      for( int index : indices[f][0] ) bandIndices[f] &= belongs[index];
707

    
708
      if( bandIndices[f]!=0 ) // outer face
709
        {
710
        int diameter = faceDiameter(vertices, indices[f]);
711
        bandIndices[f] = (diameter>=6 ? 5:diameter);
712
        }
713
      }
714

    
715
    return bandIndices;
716
    }
717

    
718
///////////////////////////////////////////////////////////////////////////////////////////////////
719

    
720
  private int computeVectorFace(float[] prev, float[] curr, float[] next)
721
    {
722
    float ax = prev[0]-curr[0];
723
    float ay = prev[1]-curr[1];
724
    float az = prev[2]-curr[2];
725

    
726
    float bx = next[0]-curr[0];
727
    float by = next[1]-curr[1];
728
    float bz = next[2]-curr[2];
729

    
730
    float lena = (float)Math.sqrt(ax*ax + ay*ay + az*az);
731
    float lenb = (float)Math.sqrt(bx*bx + by*by + bz*bz);
732

    
733
    ax /= lena;
734
    ay /= lena;
735
    az /= lena;
736

    
737
    bx /= lenb;
738
    by /= lenb;
739
    bz /= lenb;
740

    
741
    float cx = ax + bx + ay*bz-az*by;
742
    float cy = ay + by + az*bx-ax*bz;
743
    float cz = az + bz + ax*by-ay*bx;
744

    
745
    return (cx<0 ? 0:4) + (cy<0 ? 0:2) + (cz<0 ? 0:1);
746
    }
747

    
748
///////////////////////////////////////////////////////////////////////////////////////////////////
749

    
750
  private float[] computeVector(int index, float[][] vertices, int[][][] indices, int[] bandIndices)
751
    {
752
    int band=0;
753
    int numFaces = indices.length;
754
    int vector=-1;
755

    
756
    for(int f=0; f<numFaces; f++)
757
      {
758
      int numComponentsInFace = indices[f].length;
759

    
760
      for(int c=0; c<numComponentsInFace; c++)
761
        {
762
        int[] ind = indices[f][c];
763
        int numVertsInComponent = ind.length;
764

    
765
        for(int v=0; v<numVertsInComponent; v++)
766
          {
767
          if(ind[v]==index)
768
            {
769
            int prev=v>0 ? v-1 : numVertsInComponent-1;
770
            int next=v<numVertsInComponent-1 ? v+1 : 0;
771

    
772
            int prevIndex=ind[prev];
773
            int currIndex=ind[v];
774
            int nextIndex=ind[next];
775

    
776
            int newVector=computeVectorFace(vertices[prevIndex], vertices[currIndex], vertices[nextIndex]);
777
            if(vector!=-1 && vector!=newVector) return null;
778

    
779
            vector=newVector;
780
            band|=bandIndices[f];
781
            v = numVertsInComponent;
782
            }
783
          }
784
        }
785
      }
786

    
787
    return band==0 ? null : VECTOR[vector];
788
    }
789

    
790
///////////////////////////////////////////////////////////////////////////////////////////////////
791

    
792
  private float[][] generateVectors(float[][] vertices, int[][][] indices, int[] bandIndices)
793
    {
794
    int len = vertices.length;
795
    float[][] vectors = new float[len][];
796

    
797
    for(int i=0; i<len; i++)
798
      {
799
      vectors[i] = computeVector(i,vertices,indices,bandIndices);
800
      }
801

    
802
    return vectors;
803
    }
804

    
805
///////////////////////////////////////////////////////////////////////////////////////////////////
806

    
807
  private void displayWall(String tmp)
808
    {
809
    StringBuilder sb = new StringBuilder();
810

    
811
    for(int i=0; i<mMax; i++)
812
      {
813
      for(int j=0; j<mMax; j++)
814
        {
815
        sb.append(mWall[i][j]);
816
        sb.append(' ');
817
        }
818
      sb.append("  -  ");
819
      }
820

    
821
    android.util.Log.e("D", tmp+" : "+sb);
822
    }
823

    
824
///////////////////////////////////////////////////////////////////////////////////////////////////
825

    
826
  private void debug(float[][] vert, int[][] ind)
827
    {
828
    String vv="VERTICES: ";
829
    for (float[] floats : vert)
830
      {
831
      vv += "\n";
832
      int lenV2 = floats.length / 3;
833

    
834
      for (int v2 = 0; v2 < lenV2; v2++)
835
        {
836
        vv += " {";
837
        vv += (floats[3 * v2] + " ");
838
        vv += (floats[3 * v2 + 1] + " ");
839
        vv += (floats[3 * v2 + 2] + " ");
840
        vv += "}";
841
        }
842
      }
843
    android.util.Log.e("D", vv);
844

    
845
    String ii="INDICES: ";
846
    for (int[] ints : ind)
847
      {
848
      ii += "\n";
849
      for(int anInt : ints) ii+=(anInt+" ");
850
      }
851
    android.util.Log.e("D", ii);
852
    }
853

    
854
///////////////////////////////////////////////////////////////////////////////////////////////////
855

    
856
  private int debugArray(int start, String str)
857
    {
858
    StringBuilder s = new StringBuilder();
859
    int n = mVertexArray.size();
860
    for(int i=start; i<n; i++)
861
      {
862
      float[][] v = mVertexArray.get(i);
863
      int numC = v.length;
864
      s.append("numComp: ");
865
      s.append(numC);
866

    
867
      for(float[] floats : v)
868
        {
869
        int l=floats.length/3;
870

    
871
        for(int k=0; k<l; k++)
872
          {
873
          s.append(" (");
874
          s.append(floats[3*k  ]);
875
          s.append(" ");
876
          s.append(floats[3*k+1]);
877
          s.append(" ");
878
          s.append(floats[3*k+2]);
879
          s.append(") ");
880
          }
881
        }
882
      }
883

    
884
    android.util.Log.e("D", str+" : "+s);
885

    
886
    return n;
887
    }
888

    
889
///////////////////////////////////////////////////////////////////////////////////////////////////
890
// PUBLIC API
891

    
892
  public static FactoryBandagedCuboid getInstance()
893
    {
894
    if( mThis==null ) mThis = new FactoryBandagedCuboid();
895
    return mThis;
896
    }
897

    
898
///////////////////////////////////////////////////////////////////////////////////////////////////
899

    
900
  public void prepare(int numVariants, int[] numLayers)
901
    {
902
    if( mVertexArray==null ) mVertexArray = new ArrayList<>();
903
    mVertices= new float[numVariants][][];
904
    mIndices = new int[numVariants][][][];
905
    mMove = new float[numVariants][3];
906
    mBandIndices = new int[numVariants][];
907
    mFaceBelongsBitmap= new int[numVariants][];
908

    
909
    mX = numLayers[0];
910
    mY = numLayers[1];
911
    mZ = numLayers[2];
912

    
913
    dX = mX/2.0f;
914
    dY = mY/2.0f;
915
    dZ = mZ/2.0f;
916

    
917
    mMax = mX>mY ? Math.max(mX,mZ) : Math.max(mY,mZ);
918

    
919
    mWall = new int[mMax][mMax];
920
    mCuts = getCuts(numLayers);
921

    
922
    createNormal();
923
    }
924

    
925
///////////////////////////////////////////////////////////////////////////////////////////////////
926

    
927
  public ObjectShape createIrregularShape(int variant, float[] pos)
928
    {
929
    mVertexArray.clear();
930

    
931
    mNumElements = pos.length/3;
932
    mElements = new BandagedElementCuboid[mNumElements];
933
    for(int i=0; i<mNumElements; i++) mElements[i] = new BandagedElementCuboid(pos, 3*i, mNormal, mCuts);
934

    
935
    for(int x=0; x<mX; x++) createRight (x,mVertexArray);
936
    for(int x=0; x<mX; x++) createLeft  (x,mVertexArray);
937
    for(int y=0; y<mY; y++) createTop   (y,mVertexArray);
938
    for(int y=0; y<mY; y++) createBottom(y,mVertexArray);
939
    for(int z=0; z<mZ; z++) createFront (z,mVertexArray);
940
    for(int z=0; z<mZ; z++) createBack  (z,mVertexArray);
941

    
942
    computeMove(pos,variant);
943
    float[][] verts = getVertices(mVertexArray,variant);
944
    int[][][] inds  = getIndices(mVertexArray);
945

    
946
    compressVerticesAndIndices(variant,verts,inds);
947

    
948
    mFaceBelongsBitmap[variant] = computeFaceBelongsBitmap(mVertices[variant], mIndices[variant], mMove[variant]);
949
    mBandIndices[variant] = generateBandIndices(mVertices[variant], mIndices[variant], mFaceBelongsBitmap[variant]);
950

    
951
    return new ObjectShape(mVertices[variant], mIndices[variant]);
952
    }
953

    
954
///////////////////////////////////////////////////////////////////////////////////////////////////
955

    
956
  public ObjectVertexEffects createVertexEffects(int variant, boolean roundCorners)
957
    {
958
    float[][] vertVec= generateVectors(mVertices[variant], mIndices[variant], mBandIndices[variant]);
959
    int numEffects   = mVertices[variant].length;
960
    float S          = 0.04f;
961
    float[] region   = {0,0,0,0.15f};
962
    String[] names   = new String[numEffects];
963
    float[][] regions= new float[numEffects][];
964
    boolean[] uses   = new boolean[numEffects];
965
    float[][] vars   = new float[numEffects][];
966

    
967
    for(int i=0; i<numEffects; i++)
968
      {
969
      float[] v = vertVec[i];
970

    
971
      if( v!=null )
972
        {
973
        names[i]  = FactoryCubit.NAME;
974
        regions[i]= region;
975
        uses[i]   = roundCorners;
976
        vars[i]   = new float[] { 0, S*v[0], S*v[1], S*v[2], 1 };
977
        }
978
      }
979

    
980
    return new ObjectVertexEffects(names,vars,mVertices[variant],regions,uses);
981
    }
982

    
983
///////////////////////////////////////////////////////////////////////////////////////////////////
984

    
985
  public ObjectFaceShape createIrregularFaceShape(int variant, boolean iconMode)
986
    {
987
    float height= iconMode ? 0.001f : 0.048f;
988
    int[] angle = {60,50,40,32,28,23};
989
    float R     = 0.2f;
990
    float S     = 0.5f;
991
    int extraI  = 0;
992
    int extraV  = 0;
993

    
994
    int sum = mX+mY+mZ;
995
    int numVertA= sum>=19 ? 3 : (sum>=16 ? 4:5);
996
    int numVertI= 3;
997

    
998
    float[][] bands  = { {  0.001f,angle[0],R,S,numVertI,extraV,extraI},
999
                         {height  ,angle[1],R,S,numVertA,extraV,extraI},
1000
                         {height/2,angle[2],R,S,numVertA,extraV,extraI},
1001
                         {height/3,angle[3],R,S,numVertA,extraV,extraI},
1002
                         {height/4,angle[4],R,S,numVertA,extraV,extraI},
1003
                         {height/5,angle[5],R,S,numVertA,extraV,extraI} };
1004

    
1005
    return new ObjectFaceShape(bands,mBandIndices[variant],null);
1006
    }
1007

    
1008
///////////////////////////////////////////////////////////////////////////////////////////////////
1009

    
1010
  public MeshBase createMesh(float[] pos, int[] numLayers, boolean iconMode, boolean roundCorners)
1011
    {
1012
    prepare(1,numLayers);
1013
    ObjectShape shape           = createIrregularShape(0,pos);
1014
    ObjectFaceShape face        = createIrregularFaceShape(0,iconMode);
1015
    ObjectVertexEffects effects = createVertexEffects(0,roundCorners);
1016
    int numFaces                = shape.getNumFaces();
1017

    
1018
    FactoryCubit factory = FactoryCubit.getInstance();
1019
    factory.clear();
1020
    factory.createNewFaceTransform(shape,null);
1021
    return factory.createRoundedSolid(shape,face,effects,MESH_NICE,numFaces);
1022
    }
1023
  }
(3-3/16)