Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / helpers / FactoryBandagedCubit.java @ df3dcf97

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 FactoryBandagedCubit
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 FactoryBandagedCubit mThis;
47
  private ArrayList<float[]> mVertexArray;
48
  private ArrayList<float[]> mTmpArray;
49
  private float[][][] mVertices;
50
  private int[][][] mIndices;
51
  private float[][] mMove;
52

    
53
  private int mX, mY, mZ, mMax;
54
  private float dX, dY, dZ;
55
  private int[][] mWall;
56
  private int[][] mPoints;
57
  private boolean[][][] mTmp;
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

    
61
  private FactoryBandagedCubit()
62
    {
63

    
64
    }
65

    
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67

    
68
  private float[][] getVertices(ArrayList<float[]> list, float[] move, int variant)
69
    {
70
    int numMoves = move.length/3;
71
    mMove[variant][0]=0.0f;
72
    mMove[variant][1]=0.0f;
73
    mMove[variant][2]=0.0f;
74

    
75
    for(int m=0; m<numMoves; m++)
76
      {
77
      mMove[variant][0] += move[3*m  ];
78
      mMove[variant][1] += move[3*m+1];
79
      mMove[variant][2] += move[3*m+2];
80
      }
81

    
82
    mMove[variant][0]/=numMoves;
83
    mMove[variant][1]/=numMoves;
84
    mMove[variant][2]/=numMoves;
85

    
86
    int total  = 0;
87
    int length = list.size();
88
    float[][] vertices = new float[length][];
89

    
90
    for( int i=0; i<length; i++ )
91
      {
92
      vertices[i] = list.get(i);
93
      total += vertices[i].length/3;
94
      }
95

    
96
    float[][] verts = new float[total][3];
97
    int pointer = 0;
98

    
99
    for(int i=0; i<length; i++)
100
      {
101
      int len = vertices[i].length/3;
102

    
103
      for(int j=0; j<len; j++)
104
        {
105
        verts[pointer][0] = vertices[i][3*j  ] - mMove[variant][0];
106
        verts[pointer][1] = vertices[i][3*j+1] - mMove[variant][1];
107
        verts[pointer][2] = vertices[i][3*j+2] - mMove[variant][2];
108
        pointer++;
109
        }
110
      }
111

    
112
    return verts;
113
    }
114

    
115
///////////////////////////////////////////////////////////////////////////////////////////////////
116

    
117
  private int[][] getIndices(ArrayList<float[]> list)
118
    {
119
    int indicesSoFar=0;
120
    int length = list.size();
121
    int[][] indices = new int[length][];
122

    
123
    for( int i=0; i<length; i++ )
124
      {
125
      float[] f = list.get(i);
126
      int len = f.length/3;
127
      int[] ind = new int[len];
128
      for(int j=0; j<len; j++) ind[j] = (indicesSoFar++);
129
      indices[i] = ind;
130
      }
131

    
132
    return indices;
133
    }
134

    
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

    
137
  private void markAllVertices(float[] vertex, float[][] vertices, int[][] indices, int pointer, int variant)
138
    {
139
    int lenI = indices.length;
140

    
141
    for(int index=0; index<lenI; index++)
142
      {
143
      int len = indices[index].length;
144

    
145
      for(int i=0; i<len; i++)
146
        {
147
        if( mIndices[variant][index][i] == -1 )
148
          {
149
          int ind = indices[index][i];
150
          float[] ver = vertices[ind];
151

    
152
          if( vertex[0]==ver[0] && vertex[1]==ver[1] && vertex[2]==ver[2] )
153
            {
154
            mIndices[variant][index][i] = pointer;
155
            }
156
          }
157
        }
158
      }
159
    }
160

    
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162
// So far the 'vertices/indices' are stored inefficiently, with each vertex stored three times
163
// (each one normally is a corner of three faces) or even six times. Compress!
164
// Example of six times: the central vertex here:
165
//
166
// { 1.0f,  0.0f, -1.0f,
167
//   1.0f, -1.0f, -1.0f,
168
//   1.0f, -1.0f, +0.0f,
169
//   0.0f, -1.0f, -1.0f },
170

    
171
  private void compressVerticesAndIndices(int variant, float[][] vertices, int[][] indices)
172
    {
173
    if( mTmpArray==null ) mTmpArray = new ArrayList<>();
174

    
175
    int lenI = indices.length;
176
    int pointer=0;
177

    
178
    mIndices[variant] = new int[lenI][];
179

    
180
    for(int index=0; index<lenI; index++)
181
      {
182
      int len = indices[index].length;
183
      mIndices[variant][index] = new int[len];
184
      for(int i=0; i<len; i++) mIndices[variant][index][i] = -1;
185
      }
186

    
187
    for(int index=0; index<lenI; index++)
188
      {
189
      int len = indices[index].length;
190

    
191
      for(int i=0; i<len; i++)
192
        {
193
        if( mIndices[variant][index][i] == -1 )
194
          {
195
          int ind = indices[index][i];
196
          float[] ver = vertices[ind];
197
          mTmpArray.add(ver);
198
          markAllVertices(ver,vertices,indices,pointer,variant);
199
          pointer++;
200
          }
201
        }
202
      }
203

    
204
    int len = mTmpArray.size();
205
    mVertices[variant] = new float[len][];
206

    
207
    for(int i=0; i<len; i++)
208
      {
209
      mVertices[variant][i] = mTmpArray.remove(0);
210
      }
211
    }
212

    
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214

    
215
  private boolean cubitExists(float[] pos, float x, float y, float z)
216
    {
217
    int len = pos.length/3;
218

    
219
    for(int i=0; i<len; i++)
220
      if( pos[3*i]==x && pos[3*i+1]==y && pos[3*i+2]==z ) return true;
221

    
222
    return false;
223
    }
224

    
225
///////////////////////////////////////////////////////////////////////////////////////////////////
226

    
227
  private void createRight(int x, ArrayList<float[]> list)
228
    {
229
    for(int y=0; y<mMax; y++)
230
      for(int z=0; z<mMax; z++)
231
        {
232
        boolean b = (y<mY && z<mZ) && ( mTmp[x][mY-1-y][mZ-1-z] && (x+1>=mX || !mTmp[x+1][mY-1-y][mZ-1-z]) );
233
        mWall[z][y] = b ? WALL_MARKED : WALL_EMPTY;
234
        }
235

    
236
    createVertices(list,mWall,AXIS_XP,x);
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

    
241
  private void createLeft(int x, ArrayList<float[]> list)
242
    {
243
    for(int y=0; y<mMax; y++)
244
      for(int z=0; z<mMax; z++)
245
        {
246
        boolean b = (y<mY && z<mZ) && ( mTmp[x][mY-1-y][z] && (x<1 || !mTmp[x-1][mY-1-y][z]) );
247
        mWall[z][y] = b ? WALL_MARKED : WALL_EMPTY;
248
        }
249

    
250
    createVertices(list,mWall,AXIS_XM,x);
251
    }
252

    
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

    
255
  private void createTop(int y, ArrayList<float[]> list)
256
    {
257
    for(int z=0; z<mMax; z++)
258
      for(int x=0; x<mMax; x++)
259
        {
260
        boolean b = (x<mX && z<mZ) && ( mTmp[x][y][z] && (y+1>=mY || !mTmp[x][y+1][z]) );
261
        mWall[x][z] = b ? WALL_MARKED : WALL_EMPTY;
262
        }
263

    
264
    createVertices(list,mWall,AXIS_YP,y);
265
    }
266

    
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268

    
269
  private void createBottom(int y, ArrayList<float[]> list)
270
    {
271
    for(int z=0; z<mMax; z++)
272
      for(int x=0; x<mMax; x++)
273
        {
274
        boolean b = (x<mX && z<mZ) && ( mTmp[x][y][mZ-1-z] && (y<1 || !mTmp[x][y-1][mZ-1-z]) );
275
        mWall[x][z] = b ? WALL_MARKED : WALL_EMPTY;
276
        }
277

    
278
    createVertices(list,mWall,AXIS_YM,y);
279
    }
280

    
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

    
283
  private void createFront(int z, ArrayList<float[]> list)
284
    {
285
    for(int y=0; y<mMax; y++)
286
      for(int x=0; x<mMax; x++)
287
        {
288
        boolean b = (x<mX && y<mY) && ( mTmp[x][mY-1-y][z] && (z+1>=mZ || !mTmp[x][mY-1-y][z+1]) );
289
        mWall[x][y] = b ? WALL_MARKED : WALL_EMPTY;
290
        }
291

    
292
    createVertices(list,mWall,AXIS_ZP,z);
293
    }
294

    
295
///////////////////////////////////////////////////////////////////////////////////////////////////
296

    
297
  private void createBack(int z, ArrayList<float[]> list)
298
    {
299
    for(int y=0; y<mMax; y++)
300
      for(int x=0; x<mMax; x++)
301
        {
302
        boolean b = (x<mX && y<mY) && ( mTmp[mX-1-x][mY-1-y][z] && (z<1 || !mTmp[mX-1-x][mY-1-y][z-1]) );
303
        mWall[x][y] = b ? WALL_MARKED : WALL_EMPTY;
304
        }
305

    
306
    createVertices(list,mWall,AXIS_ZM,z);
307
    }
308

    
309
///////////////////////////////////////////////////////////////////////////////////////////////////
310

    
311
  private void markNeighbours(int[][] wall, int x, int y, int section)
312
    {
313
    wall[x][y] = section;
314

    
315
    if( x  >   0 && wall[x-1][y]==WALL_MARKED ) markNeighbours(wall,x-1,y,section);
316
    if( x+1<mMax && wall[x+1][y]==WALL_MARKED ) markNeighbours(wall,x+1,y,section);
317
    if( y  >   0 && wall[x][y-1]==WALL_MARKED ) markNeighbours(wall,x,y-1,section);
318
    if( y+1<mMax && wall[x][y+1]==WALL_MARKED ) markNeighbours(wall,x,y+1,section);
319
    }
320

    
321
///////////////////////////////////////////////////////////////////////////////////////////////////
322

    
323
  private int markSections(int[][] wall)
324
    {
325
    int sections = 0;
326

    
327
    for(int x=0; x<mMax; x++)
328
      for(int y=0; y<mMax; y++)
329
        if( wall[x][y]==WALL_MARKED )
330
          {
331
          sections++;
332
          markNeighbours(wall,x,y,sections);
333
          }
334

    
335
    return sections;
336
    }
337

    
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339
// return true iff exactly three or exactly one of the four values (x1,x2,x3,x4) are equal to 'value'.
340

    
341
  private boolean threeOrOne(int x1, int x2, int x3, int x4, int value)
342
    {
343
    if( x1==value ) return x2==value ? (x3==value)^(x4==value) : (x3==value)^(x4!=value);
344
    else            return x2==value ? (x3==value)^(x4!=value) : (x3==value)^(x4==value);
345
    }
346

    
347
///////////////////////////////////////////////////////////////////////////////////////////////////
348

    
349
  private boolean isOddVertical(int x, int y)
350
    {
351
    int number = 0;
352

    
353
    for(int i=0; i<y; i++)
354
      if( mPoints[x][i]==0 ) number++;
355

    
356
    return (number%2)==0;
357
    }
358

    
359
///////////////////////////////////////////////////////////////////////////////////////////////////
360

    
361
  private boolean isOddHorizontal(int x, int y)
362
    {
363
    int number = 0;
364

    
365
    for(int i=0; i<x; i++)
366
      if( mPoints[i][y]==0 ) number++;
367

    
368
    return (number%2)==0;
369
    }
370

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

    
373
  private int moveUp(int x, int y)
374
    {
375
    for(int i=y-1; i>=0; i--)
376
      if( mPoints[x][i]==0 ) return i;
377

    
378
    android.util.Log.e("D", "moveUp error!");
379
    return 0;
380
    }
381

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383

    
384
  private int moveDown(int x, int y)
385
    {
386
    for(int i=y+1; i<=mMax; i++)
387
      if( mPoints[x][i]==0 ) return i;
388

    
389
    android.util.Log.e("D", "moveDown error!");
390
    return 0;
391
    }
392

    
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394

    
395
  private int moveLeft(int x, int y)
396
    {
397
    for(int i=x-1; i>=0; i--)
398
      if( mPoints[i][y]==0 ) return i;
399

    
400
    android.util.Log.e("D", "moveLeft error!");
401
    return 0;
402
    }
403

    
404
///////////////////////////////////////////////////////////////////////////////////////////////////
405

    
406
  private int moveRight(int x, int y)
407
    {
408
    for(int i=x+1; i<=mMax; i++)
409
      if( mPoints[i][y]==0 ) return i;
410

    
411
    android.util.Log.e("D", "moveRight error!");
412
    return 0;
413
    }
414

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416

    
417
  private float[] buildVertices(int[][] wall, int section, float dx, float dy)
418
    {
419
    int numPoints = buildPoints(wall,section);
420
    int numSections = numPoints/2;
421
    float[] vertices = new float[3*numPoints];
422
    int x=0,y=0,pointer=0;
423

    
424
    for(int i=0; i<=mMax; i++)
425
      for(int j=0; j<=mMax; j++)
426
        if( mPoints[i][j]==0 )
427
          {
428
          x = i;
429
          y = j;
430
          i = j = mMax+1;
431
          }
432

    
433
    for(int s=0; s<numSections; s++)
434
      {
435
      vertices[6*pointer  ] = x-dx;
436
      vertices[6*pointer+1] = dy-y;
437
      vertices[6*pointer+2] = 0.0f;
438

    
439
      y = isOddVertical(x,y) ? moveDown(x,y) : moveUp(x,y);
440

    
441
      vertices[6*pointer+3] = x-dx;
442
      vertices[6*pointer+4] = dy-y;
443
      vertices[6*pointer+5] = 0.0f;
444

    
445
      x = isOddHorizontal(x,y) ? moveRight(x,y) : moveLeft(x,y);
446

    
447
      pointer++;
448
      }
449

    
450
    return vertices;
451
    }
452

    
453
///////////////////////////////////////////////////////////////////////////////////////////////////
454

    
455
  private int buildPoints(int[][] wall, int section)
456
    {
457
    int numPoints=0;
458
    boolean thereIsCorner;
459

    
460
    for(int x=0; x<=mMax; x++)
461
      for(int y=0; y<=mMax; y++)
462
        {
463
        if( y==0 )
464
          {
465
               if( x==   0 ) thereIsCorner = (wall[     0][0]==section);
466
          else if( x==mMax ) thereIsCorner = (wall[mMax-1][0]==section);
467
          else               thereIsCorner = (wall[x-1][0]==section)^(wall[x][0]==section);
468
          }
469
        else if( y==mMax )
470
          {
471
               if( x==   0 ) thereIsCorner = (wall[     0][mMax-1]==section);
472
          else if( x==mMax ) thereIsCorner = (wall[mMax-1][mMax-1]==section);
473
          else               thereIsCorner = (wall[x-1][mMax-1]==section)^(wall[x][mMax-1]==section);
474
          }
475
        else if( x==0 )
476
          {
477
          thereIsCorner = (wall[0][y-1]==section)^(wall[0][y]==section);
478
          }
479
        else if( x==mMax )
480
          {
481
          thereIsCorner = (wall[mMax-1][y-1]==section)^(wall[mMax-1][y]==section);
482
          }
483
        else
484
          {
485
          thereIsCorner = threeOrOne(wall[x-1][y-1],wall[x-1][y],wall[x][y-1],wall[x][y],section);
486
          }
487

    
488
        if( thereIsCorner )
489
          {
490
          mPoints[x][y] = 0;
491
          numPoints++;
492
          }
493
        else
494
          {
495
          mPoints[x][y] =-1;
496
          }
497
        }
498

    
499
    return numPoints;
500
    }
501

    
502
///////////////////////////////////////////////////////////////////////////////////////////////////
503

    
504
  private void rotateAndMoveVertices(float[] vertices, int axis, int layer)
505
    {
506
    int i,len = vertices.length/3;
507

    
508
    switch(axis)
509
      {
510
      case AXIS_XP: for(i=0; i<len; i++)
511
                      {
512
                      vertices[3*i+2] =-vertices[3*i  ];
513
                      vertices[3*i  ] = layer-(dX-1.0f);
514
                      }
515
                    break;
516
      case AXIS_XM: for(i=0; i<len; i++)
517
                      {
518
                      vertices[3*i+2] = vertices[3*i  ];
519
                      vertices[3*i  ] = layer-dX;
520
                      }
521
                    break;
522
      case AXIS_YP: for(i=0; i<len; i++)
523
                      {
524
                      vertices[3*i+2] =-vertices[3*i+1];
525
                      vertices[3*i+1] = layer-(dY-1.0f);
526
                      }
527
                    break;
528
      case AXIS_YM: for(i=0; i<len; i++)
529
                      {
530
                      vertices[3*i+2] = vertices[3*i+1];
531
                      vertices[3*i+1] = layer-dY;
532
                      }
533
                    break;
534
      case AXIS_ZP: for(i=0; i<len; i++)
535
                      {
536
                      vertices[3*i+2] = layer-(dZ-1.0f);
537
                      }
538
                    break;
539
      case AXIS_ZM: for(i=0; i<len; i++)
540
                      {
541
                      vertices[3*i+2] = layer-dZ;
542
                      vertices[3*i  ] =-vertices[3*i  ];
543
                      }
544
                    break;
545
      }
546
    }
547

    
548
///////////////////////////////////////////////////////////////////////////////////////////////////
549
// 1. assume the 'wall' is in the XY plane
550
// 2. split the wall into individual connected regions and for each such region:
551
//   a. build the list of vertices (Z=0)
552
//   b. take the axis into consideration and rotate the vertices.
553
//   c. take layer into consideration and move the vertices.
554
//   d. add the resulting vertices to the list.
555

    
556
  private void createVertices(ArrayList<float[]> list, int[][] wall, int axis, int layer)
557
    {
558
    int sections = markSections(wall);
559

    
560
    float dx = (axis==AXIS_XP || axis==AXIS_XM) ? dZ : dX;
561
    float dy = (axis==AXIS_YP || axis==AXIS_YM) ? dZ : dY;
562

    
563
    for(int i=0; i<sections; i++)
564
      {
565
      float[] vertices = buildVertices(wall,i+1,dx,dy);
566

    
567
      rotateAndMoveVertices(vertices,axis,layer);
568
      list.add(vertices);
569
/*
570
      int len = vertices.length/3;
571
      String w="";
572

    
573
      for(int j=0; j<len; j++)
574
        {
575
        w += ( "["+vertices[3*j]+" "+vertices[3*j+1]+" "+vertices[3*j+2]+"] ");
576
        }
577
      android.util.Log.e("D", "1 section: "+i+" axis: "+axis+" layer: "+layer+" vertices after: "+w);
578
*/
579
      }
580
    }
581

    
582
///////////////////////////////////////////////////////////////////////////////////////////////////
583

    
584
  private static boolean vertInFace(float[] vertex, float[] move, Static3D faceAxis, float dist)
585
    {
586
    final float MAX_ERROR = 0.01f;
587

    
588
    float x= faceAxis.get0();
589
    float y= faceAxis.get1();
590
    float z= faceAxis.get2();
591

    
592
    float a = (vertex[0]+move[0])*x + (vertex[1]+move[1])*y + (vertex[2]+move[2])*z;
593
    float diff = a - dist;
594

    
595
    return diff>-MAX_ERROR && diff<MAX_ERROR;
596
    }
597

    
598
///////////////////////////////////////////////////////////////////////////////////////////////////
599
// (vertices,indices) define a cubit face, i.e. a connected subset of the NxN grid.
600
// Return its 'diameter', i.e. max(width,height)
601

    
602
  private int faceDiameter(float[][] vertices, int[] indices)
603
    {
604
    float maxX = -dX;
605
    float minX = +dX;
606
    float maxY = -dY;
607
    float minY = +dY;
608
    float maxZ = -dZ;
609
    float minZ = +dZ;
610

    
611
    for (int index : indices)
612
      {
613
      float[] v = vertices[index];
614

    
615
      if (v[0] > maxX) maxX = v[0];
616
      if (v[0] < minX) minX = v[0];
617
      if (v[1] > maxY) maxY = v[1];
618
      if (v[1] < minY) minY = v[1];
619
      if (v[2] > maxZ) maxZ = v[2];
620
      if (v[2] < minZ) minZ = v[2];
621
      }
622

    
623
    float diffX = maxX-minX;
624
    float diffY = maxY-minY;
625
    float diffZ = maxZ-minZ;
626

    
627
    float max = diffX>diffY ? Math.max(diffX,diffZ) : Math.max(diffY,diffZ);
628

    
629
    return (int)max;
630
    }
631

    
632
///////////////////////////////////////////////////////////////////////////////////////////////////
633
// return array of:
634
// 0 if this is an inner face, 1 if its diameter is 1, 2 if diameter is 2, 3 if 3, etc
635

    
636
  private int[] generateBandIndices(float[][] vertices, int[][] indices, float[] move)
637
    {
638
    int numCubitFaces = indices.length;
639
    int[] bandIndices = new int[numCubitFaces];
640

    
641
    for(int cubitFace=0; cubitFace<numCubitFaces; cubitFace++)
642
      {
643
      bandIndices[cubitFace] = 0xffffffff;
644
      int numVertices = indices[cubitFace].length;
645

    
646
      for(int vertex=0; vertex<numVertices; vertex++)
647
        {
648
        int vertBelongsBitmap = 0x00000000;
649
        float[] vert = vertices[ indices[cubitFace][vertex] ];
650

    
651
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[0], dX) ) vertBelongsBitmap |= (1<<0);
652
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[1], dX) ) vertBelongsBitmap |= (1<<1);
653
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[2], dY) ) vertBelongsBitmap |= (1<<2);
654
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[3], dY) ) vertBelongsBitmap |= (1<<3);
655
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[4], dZ) ) vertBelongsBitmap |= (1<<4);
656
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[5], dZ) ) vertBelongsBitmap |= (1<<5);
657

    
658
        bandIndices[cubitFace] &= vertBelongsBitmap;
659
        }
660

    
661
      if( bandIndices[cubitFace]!=0 ) // outer face
662
        {
663
        bandIndices[cubitFace] = faceDiameter(vertices, indices[cubitFace]);
664
        }
665

    
666
      //android.util.Log.e("D", "cubit face "+cubitFace+" : "+bandIndices[cubitFace]);
667
      }
668

    
669
    return bandIndices;
670
    }
671

    
672
///////////////////////////////////////////////////////////////////////////////////////////////////
673

    
674
  private int[] generateCornerIndices(float[][] vertices, boolean roundCorners)
675
    {
676
    int len = vertices.length;
677
    int val = roundCorners ? 0 : -1;
678
    int[] cornerIndices = new int[len];
679
    for(int i=0; i<len; i++) cornerIndices[i] = val;
680
    return cornerIndices;
681
    }
682

    
683
///////////////////////////////////////////////////////////////////////////////////////////////////
684

    
685
  private int computeVectorFace(float[] prev, float[] curr, float[] next)
686
    {
687
    float ax = prev[0]-curr[0];
688
    float ay = prev[1]-curr[1];
689
    float az = prev[2]-curr[2];
690

    
691
    float bx = next[0]-curr[0];
692
    float by = next[1]-curr[1];
693
    float bz = next[2]-curr[2];
694

    
695
    float lena = (float)Math.sqrt(ax*ax + ay*ay + az*az);
696
    float lenb = (float)Math.sqrt(bx*bx + by*by + bz*bz);
697

    
698
    ax /= lena;
699
    ay /= lena;
700
    az /= lena;
701

    
702
    bx /= lenb;
703
    by /= lenb;
704
    bz /= lenb;
705

    
706
    float cx = ax + bx + ay*bz-az*by;
707
    float cy = ay + by + az*bx-ax*bz;
708
    float cz = az + bz + ax*by-ay*bx;
709

    
710
    return (cx<0 ? 0:4) + (cy<0 ? 0:2) + (cz<0 ? 0:1);
711
    }
712

    
713
///////////////////////////////////////////////////////////////////////////////////////////////////
714

    
715
  private float[] computeVector(int index, float[][] vertices, int[][] indices, int[] bandIndices)
716
    {
717
    int band=0;
718
    int len = indices.length;
719
    int vector=-1;
720

    
721
    for(int i=0; i<len; i++)
722
      {
723
      int len2 = indices[i].length;
724

    
725
      for(int j=0; j<len2; j++)
726
        {
727
        if( indices[i][j]==index )
728
          {
729
          int prev = j>0 ? j-1 : len2-1;
730
          int next = j<len2-1 ? j+1 : 0;
731

    
732
          int prevIndex = indices[i][prev];
733
          int currIndex = indices[i][j];
734
          int nextIndex = indices[i][next];
735

    
736
          int newVector = computeVectorFace(vertices[prevIndex],vertices[currIndex],vertices[nextIndex]);
737
          if( vector!=-1 && vector!=newVector ) return null;
738

    
739
          vector = newVector;
740
          band |= bandIndices[i];
741
          }
742
        }
743
      }
744

    
745
    return band==0 ? null : VECTOR[vector];
746
    }
747

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

    
750
  private float[][] generateVectors(float[][] vertices, int[][] indices, int[] bandIndices)
751
    {
752
    int len = vertices.length;
753
    float[][] vectors = new float[len][];
754

    
755
    for(int i=0; i<len; i++)
756
      {
757
      vectors[i] = computeVector(i,vertices,indices,bandIndices);
758
      }
759

    
760
    return vectors;
761
    }
762

    
763
///////////////////////////////////////////////////////////////////////////////////////////////////
764

    
765
  private float[][] generateCenters(float[][] vertices, float[][] vectors)
766
    {
767
    int pointer=0,total=0;
768
    int len = vertices.length;
769

    
770
    for( float[] vector : vectors )
771
      {
772
      if( vector!=null ) total++;
773
      }
774

    
775
    float[][] centers = new float[total][3];
776

    
777
    for( int i=0; i<len; i++ )
778
      {
779
      if( vectors[i]!=null )
780
        {
781
        centers[pointer][0] = vertices[i][0]+vectors[i][0];
782
        centers[pointer][1] = vertices[i][1]+vectors[i][1];
783
        centers[pointer][2] = vertices[i][2]+vectors[i][2];
784
        pointer++;
785
        }
786
      }
787

    
788
    return centers;
789
    }
790

    
791
///////////////////////////////////////////////////////////////////////////////////////////////////
792

    
793
  private int[] generateCenterIndices(float[][] vectors)
794
    {
795
    int pointer=0;
796
    int len = vectors.length;
797
    int[] centerIndices = new int[len];
798

    
799
    for(int i=0; i<len; i++)
800
      {
801
      if( vectors[i]==null )
802
        {
803
        centerIndices[i] = -1;
804
        }
805
      else
806
        {
807
        centerIndices[i] = pointer;
808
        pointer++;
809
        }
810
      }
811

    
812
    return centerIndices;
813
    }
814

    
815
///////////////////////////////////////////////////////////////////////////////////////////////////
816
// PUBLIC API
817

    
818
  public static FactoryBandagedCubit getInstance()
819
    {
820
    if( mThis==null ) mThis = new FactoryBandagedCubit();
821
    return mThis;
822
    }
823

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

    
826
  public void prepare(int numVariants, int x, int y, int z)
827
    {
828
    if( mVertexArray==null ) mVertexArray = new ArrayList<>();
829
    mVertices= new float[numVariants][][];
830
    mIndices = new int[numVariants][][];
831
    mMove = new float[numVariants][3];
832

    
833
    mX = x;
834
    mY = y;
835
    mZ = z;
836

    
837
    dX = mX/2.0f;
838
    dY = mY/2.0f;
839
    dZ = mZ/2.0f;
840

    
841
    mMax = mX>mY ? Math.max(mX,mZ) : Math.max(mY,mZ);
842

    
843
    mWall   = new int[mMax][mMax];
844
    mPoints = new int[mMax+1][mMax+1];
845
    mTmp    = new boolean[mX][mY][mZ];
846
    }
847

    
848
///////////////////////////////////////////////////////////////////////////////////////////////////
849

    
850
  public ObjectShape createIrregularShape(int variant, float[] pos)
851
    {
852
    mVertexArray.clear();
853

    
854
    float begX = 0.5f*(1-mX);
855
    float begY = 0.5f*(1-mY);
856
    float begZ = 0.5f*(1-mZ);
857

    
858
    for(int x=0; x<mX; x++)
859
      for(int y=0; y<mY; y++)
860
        for(int z=0; z<mZ; z++) mTmp[x][y][z] = cubitExists(pos,begX+x,begY+y,begZ+z);
861

    
862
    for(int x=0; x<mX; x++) createRight (x,mVertexArray);
863
    for(int x=0; x<mX; x++) createLeft  (x,mVertexArray);
864
    for(int y=0; y<mY; y++) createTop   (y,mVertexArray);
865
    for(int y=0; y<mY; y++) createBottom(y,mVertexArray);
866
    for(int z=0; z<mZ; z++) createFront (z,mVertexArray);
867
    for(int z=0; z<mZ; z++) createBack  (z,mVertexArray);
868

    
869
    float[][] verts = getVertices(mVertexArray,pos,variant);
870
    int[][] inds    = getIndices(mVertexArray);
871

    
872
    compressVerticesAndIndices(variant,verts,inds);
873

    
874
    return new ObjectShape(mVertices[variant], mIndices[variant]);
875
    }
876

    
877
///////////////////////////////////////////////////////////////////////////////////////////////////
878

    
879
  private void debug(float[][] vert, int[][] ind)
880
    {
881
    String vv="VERTICES: ";
882
    for (float[] floats : vert)
883
      {
884
      vv += "\n";
885
      int lenV2 = floats.length / 3;
886

    
887
      for (int v2 = 0; v2 < lenV2; v2++)
888
        {
889
        vv += " {";
890
        vv += (floats[3 * v2] + " ");
891
        vv += (floats[3 * v2 + 1] + " ");
892
        vv += (floats[3 * v2 + 2] + " ");
893
        vv += "}";
894
        }
895
      }
896
    android.util.Log.e("D", vv);
897

    
898
    String ii="INDICES: ";
899
    for (int[] ints : ind)
900
      {
901
      ii += "\n";
902
      int lenI2 = ints.length;
903

    
904
      for (int i2 = 0; i2 < lenI2; i2++)
905
        {
906
        ii += (ints[i2] + " ");
907
        }
908
      }
909
    android.util.Log.e("D", ii);
910
    }
911

    
912
///////////////////////////////////////////////////////////////////////////////////////////////////
913

    
914
  public ObjectFaceShape createIrregularFaceShape(int variant, boolean iconMode, boolean roundCorners)
915
    {
916
    float height   = iconMode ? 0.001f : 0.048f;
917
    int angle      = 60;
918
    float R        = 0.2f;
919
    float S        = 0.5f;
920
    int numVertices= 5;
921
    int extraI     = 0;
922
    int extraV     = 0;
923

    
924
    float[][] corners   = { {0.02f,0.12f} };
925
    float[][] bands     = { {  0.001f,angle,R,S,numVertices,extraV,extraI},
926
                            {height/1,angle,R,S,numVertices,extraV,extraI},
927
                            {height/2,angle,R,S,numVertices,extraV,extraI},
928
                            {height/3,angle,R,S,numVertices,extraV,extraI},
929
                            {height/4,angle,R,S,numVertices,extraV,extraI},
930
                            {height/5,angle,R,S,numVertices,extraV,extraI} };
931

    
932
    int[] bandIndices   = generateBandIndices(mVertices[variant], mIndices[variant], mMove[variant]);
933
    int[] cornerIndices = generateCornerIndices(mVertices[variant], roundCorners);
934
    float[][] vertexVec = generateVectors(mVertices[variant], mIndices[variant], bandIndices);
935
    float[][] centers   = generateCenters(mVertices[variant], vertexVec);
936
    int[] centerIndices = generateCenterIndices(vertexVec);
937

    
938
    return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
939
    }
940

    
941
///////////////////////////////////////////////////////////////////////////////////////////////////
942

    
943
  public MeshBase createMesh(float[] pos, int x, int y, int z, boolean iconMode, boolean roundCorners)
944
    {
945
    prepare(1,x,y,z);
946
    ObjectShape shape    = createIrregularShape(0,pos);
947
    ObjectFaceShape face = createIrregularFaceShape(0,iconMode,roundCorners);
948
    int[][] indices      = shape.getVertIndices();
949
    int numComponents    = indices.length;
950

    
951
    FactoryCubit factory = FactoryCubit.getInstance();
952
    factory.clear();
953
    factory.createNewFaceTransform(shape,null);
954
    return factory.createRoundedSolid(shape,face,MESH_NICE,numComponents);
955
    }
956
  }
(2-2/12)