Project

General

Profile

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

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

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objectlib.helpers;
21

    
22
import java.util.ArrayList;
23

    
24
import org.distorted.library.mesh.MeshBase;
25
import org.distorted.library.type.Static3D;
26
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
27

    
28
import static org.distorted.objectlib.main.TwistyObject.MESH_NICE;
29

    
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31

    
32
public class FactoryBandagedCubit
33
  {
34
  private static final int WALL_MARKED=0;
35
  private static final int WALL_EMPTY =-1;
36

    
37
  private static final int AXIS_XP = 0;
38
  private static final int AXIS_XM = 1;
39
  private static final int AXIS_YP = 2;
40
  private static final int AXIS_YM = 3;
41
  private static final int AXIS_ZP = 4;
42
  private static final int AXIS_ZM = 5;
43

    
44
  private static final float[][] VECTOR =
45
      {
46
          {-1.0f,-1.0f,-1.0f},
47
          {-1.0f,-1.0f,+1.0f},
48
          {-1.0f,+1.0f,-1.0f},
49
          {-1.0f,+1.0f,+1.0f},
50
          {+1.0f,-1.0f,-1.0f},
51
          {+1.0f,-1.0f,+1.0f},
52
          {+1.0f,+1.0f,-1.0f},
53
          {+1.0f,+1.0f,+1.0f}
54
      };
55

    
56
  private static FactoryBandagedCubit mThis;
57
  private ArrayList<float[]> mVertexArray;
58
  private ArrayList<float[]> mTmpArray;
59
  private float[][][] mVertices;
60
  private int[][][] mIndices;
61
  private float[][] mMove;
62

    
63
  private int mX, mY, mZ, mMax;
64
  private float dX, dY, dZ;
65
  private int[][] mWall;
66
  private int[][] mPoints;
67
  private boolean[][][] mTmp;
68

    
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70

    
71
  private FactoryBandagedCubit()
72
    {
73

    
74
    }
75

    
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77

    
78
  private float[][] getVertices(ArrayList<float[]> list, float[] move, int variant)
79
    {
80
    int numMoves = move.length/3;
81
    mMove[variant][0]=0.0f;
82
    mMove[variant][1]=0.0f;
83
    mMove[variant][2]=0.0f;
84

    
85
    for(int m=0; m<numMoves; m++)
86
      {
87
      mMove[variant][0] += move[3*m  ];
88
      mMove[variant][1] += move[3*m+1];
89
      mMove[variant][2] += move[3*m+2];
90
      }
91

    
92
    mMove[variant][0]/=numMoves;
93
    mMove[variant][1]/=numMoves;
94
    mMove[variant][2]/=numMoves;
95

    
96
    int total  = 0;
97
    int length = list.size();
98
    float[][] vertices = new float[length][];
99

    
100
    for( int i=0; i<length; i++ )
101
      {
102
      vertices[i] = list.get(i);
103
      total += vertices[i].length/3;
104
      }
105

    
106
    float[][] verts = new float[total][3];
107
    int pointer = 0;
108

    
109
    for(int i=0; i<length; i++)
110
      {
111
      int len = vertices[i].length/3;
112

    
113
      for(int j=0; j<len; j++)
114
        {
115
        verts[pointer][0] = vertices[i][3*j  ] - mMove[variant][0];
116
        verts[pointer][1] = vertices[i][3*j+1] - mMove[variant][1];
117
        verts[pointer][2] = vertices[i][3*j+2] - mMove[variant][2];
118
        pointer++;
119
        }
120
      }
121

    
122
    return verts;
123
    }
124

    
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126

    
127
  private int[][] getIndices(ArrayList<float[]> list)
128
    {
129
    int indicesSoFar=0;
130
    int length = list.size();
131
    int[][] indices = new int[length][];
132

    
133
    for( int i=0; i<length; i++ )
134
      {
135
      float[] f = list.get(i);
136
      int len = f.length/3;
137
      int[] ind = new int[len];
138
      for(int j=0; j<len; j++) ind[j] = (indicesSoFar++);
139
      indices[i] = ind;
140
      }
141

    
142
    return indices;
143
    }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146

    
147
  private void markAllVertices(float[] vertex, float[][] vertices, int[][] indices, int pointer, int variant)
148
    {
149
    int lenI = indices.length;
150

    
151
    for(int index=0; index<lenI; index++)
152
      {
153
      int len = indices[index].length;
154

    
155
      for(int i=0; i<len; i++)
156
        {
157
        if( mIndices[variant][index][i] == -1 )
158
          {
159
          int ind = indices[index][i];
160
          float[] ver = vertices[ind];
161

    
162
          if( vertex[0]==ver[0] && vertex[1]==ver[1] && vertex[2]==ver[2] )
163
            {
164
            mIndices[variant][index][i] = pointer;
165
            }
166
          }
167
        }
168
      }
169
    }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172
// So far the 'vertices/indices' are stored inefficiently, with each vertex stored three times
173
// (each one normally is a corner of three faces) or even six times. Compress!
174
// Example of six times: the central vertex here:
175
//
176
// { 1.0f,  0.0f, -1.0f,
177
//   1.0f, -1.0f, -1.0f,
178
//   1.0f, -1.0f, +0.0f,
179
//   0.0f, -1.0f, -1.0f },
180

    
181
  private void compressVerticesAndIndices(int variant, float[][] vertices, int[][] indices)
182
    {
183
    if( mTmpArray==null ) mTmpArray = new ArrayList<>();
184

    
185
    int lenI = indices.length;
186
    int pointer=0;
187

    
188
    mIndices[variant] = new int[lenI][];
189

    
190
    for(int index=0; index<lenI; index++)
191
      {
192
      int len = indices[index].length;
193
      mIndices[variant][index] = new int[len];
194
      for(int i=0; i<len; i++) mIndices[variant][index][i] = -1;
195
      }
196

    
197
    for(int index=0; index<lenI; index++)
198
      {
199
      int len = indices[index].length;
200

    
201
      for(int i=0; i<len; i++)
202
        {
203
        if( mIndices[variant][index][i] == -1 )
204
          {
205
          int ind = indices[index][i];
206
          float[] ver = vertices[ind];
207
          mTmpArray.add(ver);
208
          markAllVertices(ver,vertices,indices,pointer,variant);
209
          pointer++;
210
          }
211
        }
212
      }
213

    
214
    int len = mTmpArray.size();
215
    mVertices[variant] = new float[len][];
216

    
217
    for(int i=0; i<len; i++)
218
      {
219
      mVertices[variant][i] = mTmpArray.remove(0);
220
      }
221
    }
222

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

    
225
  private boolean cubitExists(float[] pos, float x, float y, float z)
226
    {
227
    int len = pos.length/3;
228

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

    
232
    return false;
233
    }
234

    
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236

    
237
  private void createRight(int x, ArrayList<float[]> list)
238
    {
239
    for(int y=0; y<mMax; y++)
240
      for(int z=0; z<mMax; z++)
241
        {
242
        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]) );
243
        mWall[z][y] = b ? WALL_MARKED : WALL_EMPTY;
244
        }
245

    
246
    createVertices(list,mWall,AXIS_XP,x);
247
    }
248

    
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250

    
251
  private void createLeft(int x, ArrayList<float[]> list)
252
    {
253
    for(int y=0; y<mMax; y++)
254
      for(int z=0; z<mMax; z++)
255
        {
256
        boolean b = (y<mY && z<mZ) && ( mTmp[x][mY-1-y][z] && (x<1 || !mTmp[x-1][mY-1-y][z]) );
257
        mWall[z][y] = b ? WALL_MARKED : WALL_EMPTY;
258
        }
259

    
260
    createVertices(list,mWall,AXIS_XM,x);
261
    }
262

    
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264

    
265
  private void createTop(int y, ArrayList<float[]> list)
266
    {
267
    for(int z=0; z<mMax; z++)
268
      for(int x=0; x<mMax; x++)
269
        {
270
        boolean b = (x<mX && z<mZ) && ( mTmp[x][y][z] && (y+1>=mY || !mTmp[x][y+1][z]) );
271
        mWall[x][z] = b ? WALL_MARKED : WALL_EMPTY;
272
        }
273

    
274
    createVertices(list,mWall,AXIS_YP,y);
275
    }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

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

    
288
    createVertices(list,mWall,AXIS_YM,y);
289
    }
290

    
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292

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

    
302
    createVertices(list,mWall,AXIS_ZP,z);
303
    }
304

    
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306

    
307
  private void createBack(int z, ArrayList<float[]> list)
308
    {
309
    for(int y=0; y<mMax; y++)
310
      for(int x=0; x<mMax; x++)
311
        {
312
        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]) );
313
        mWall[x][y] = b ? WALL_MARKED : WALL_EMPTY;
314
        }
315

    
316
    createVertices(list,mWall,AXIS_ZM,z);
317
    }
318

    
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320

    
321
  private void markNeighbours(int[][] wall, int x, int y, int section)
322
    {
323
    wall[x][y] = section;
324

    
325
    if( x  >   0 && wall[x-1][y]==WALL_MARKED ) markNeighbours(wall,x-1,y,section);
326
    if( x+1<mMax && wall[x+1][y]==WALL_MARKED ) markNeighbours(wall,x+1,y,section);
327
    if( y  >   0 && wall[x][y-1]==WALL_MARKED ) markNeighbours(wall,x,y-1,section);
328
    if( y+1<mMax && wall[x][y+1]==WALL_MARKED ) markNeighbours(wall,x,y+1,section);
329
    }
330

    
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332

    
333
  private int markSections(int[][] wall)
334
    {
335
    int sections = 0;
336

    
337
    for(int x=0; x<mMax; x++)
338
      for(int y=0; y<mMax; y++)
339
        if( wall[x][y]==WALL_MARKED )
340
          {
341
          sections++;
342
          markNeighbours(wall,x,y,sections);
343
          }
344

    
345
    return sections;
346
    }
347

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

    
351
  private boolean threeOrOne(int x1, int x2, int x3, int x4, int value)
352
    {
353
    if( x1==value ) return x2==value ? (x3==value)^(x4==value) : (x3==value)^(x4!=value);
354
    else            return x2==value ? (x3==value)^(x4!=value) : (x3==value)^(x4==value);
355
    }
356

    
357
///////////////////////////////////////////////////////////////////////////////////////////////////
358

    
359
  private boolean isOddVertical(int x, int y)
360
    {
361
    int number = 0;
362

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

    
366
    return (number%2)==0;
367
    }
368

    
369
///////////////////////////////////////////////////////////////////////////////////////////////////
370

    
371
  private boolean isOddHorizontal(int x, int y)
372
    {
373
    int number = 0;
374

    
375
    for(int i=0; i<x; i++)
376
      if( mPoints[i][y]==0 ) number++;
377

    
378
    return (number%2)==0;
379
    }
380

    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

    
383
  private int moveUp(int x, int y)
384
    {
385
    for(int i=y-1; i>=0; i--)
386
      if( mPoints[x][i]==0 ) return i;
387

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

    
392
///////////////////////////////////////////////////////////////////////////////////////////////////
393

    
394
  private int moveDown(int x, int y)
395
    {
396
    for(int i=y+1; i<=mMax; i++)
397
      if( mPoints[x][i]==0 ) return i;
398

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

    
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404

    
405
  private int moveLeft(int x, int y)
406
    {
407
    for(int i=x-1; i>=0; i--)
408
      if( mPoints[i][y]==0 ) return i;
409

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

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

    
416
  private int moveRight(int x, int y)
417
    {
418
    for(int i=x+1; i<=mMax; i++)
419
      if( mPoints[i][y]==0 ) return i;
420

    
421
    android.util.Log.e("D", "moveRight error!");
422
    return 0;
423
    }
424

    
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426

    
427
  private float[] buildVertices(int[][] wall, int section)
428
    {
429
    int numPoints = buildPoints(wall,section);
430
    int numSections = numPoints/2;
431
    float[] vertices = new float[3*numPoints];
432
    int x=0,y=0,pointer=0;
433

    
434
    for(int i=0; i<=mMax; i++)
435
      for(int j=0; j<=mMax; j++)
436
        if( mPoints[i][j]==0 )
437
          {
438
          x = i;
439
          y = j;
440
          i = j = mMax+1;
441
          }
442

    
443
    for(int s=0; s<numSections; s++)
444
      {
445
      vertices[6*pointer  ] = x-dX;
446
      vertices[6*pointer+1] = dY-y;
447
      vertices[6*pointer+2] = 0.0f;
448

    
449
      y = isOddVertical(x,y) ? moveDown(x,y) : moveUp(x,y);
450

    
451
      vertices[6*pointer+3] = x-dX;
452
      vertices[6*pointer+4] = dY-y;
453
      vertices[6*pointer+5] = 0.0f;
454

    
455
      x = isOddHorizontal(x,y) ? moveRight(x,y) : moveLeft(x,y);
456

    
457
      pointer++;
458
      }
459

    
460
    return vertices;
461
    }
462

    
463
///////////////////////////////////////////////////////////////////////////////////////////////////
464

    
465
  private int buildPoints(int[][] wall, int section)
466
    {
467
    int numPoints=0;
468
    boolean thereIsCorner;
469

    
470
    for(int x=0; x<=mMax; x++)
471
      for(int y=0; y<=mMax; y++)
472
        {
473
        if( y==0 )
474
          {
475
               if( x==   0 ) thereIsCorner = (wall[     0][0]==section);
476
          else if( x==mMax ) thereIsCorner = (wall[mMax-1][0]==section);
477
          else               thereIsCorner = (wall[x-1][0]==section)^(wall[x][0]==section);
478
          }
479
        else if( y==mMax )
480
          {
481
               if( x==   0 ) thereIsCorner = (wall[     0][mMax-1]==section);
482
          else if( x==mMax ) thereIsCorner = (wall[mMax-1][mMax-1]==section);
483
          else               thereIsCorner = (wall[x-1][mMax-1]==section)^(wall[x][mMax-1]==section);
484
          }
485
        else if( x==0 )
486
          {
487
          thereIsCorner = (wall[0][y-1]==section)^(wall[0][y]==section);
488
          }
489
        else if( x==mMax )
490
          {
491
          thereIsCorner = (wall[mMax-1][y-1]==section)^(wall[mMax-1][y]==section);
492
          }
493
        else
494
          {
495
          thereIsCorner = threeOrOne(wall[x-1][y-1],wall[x-1][y],wall[x][y-1],wall[x][y],section);
496
          }
497

    
498
        if( thereIsCorner )
499
          {
500
          mPoints[x][y] = 0;
501
          numPoints++;
502
          }
503
        else
504
          {
505
          mPoints[x][y] =-1;
506
          }
507
        }
508

    
509
    return numPoints;
510
    }
511

    
512
///////////////////////////////////////////////////////////////////////////////////////////////////
513

    
514
  private void rotateAndMoveVertices(float[] vertices, int axis, int layer)
515
    {
516
    int i,len = vertices.length/3;
517

    
518
    switch(axis)
519
      {
520
      case AXIS_XP: for(i=0; i<len; i++)
521
                      {
522
                      vertices[3*i+2] = -vertices[3*i];
523
                      vertices[3*i  ] = layer-(dX-1.0f);
524
                      }
525
                    break;
526
      case AXIS_XM: for(i=0; i<len; i++)
527
                      {
528
                      vertices[3*i+2] = vertices[3*i];
529
                      vertices[3*i  ] = layer-dX;
530
                      }
531
                    break;
532
      case AXIS_YP: for(i=0; i<len; i++)
533
                      {
534
                      vertices[3*i+2] = -vertices[3*i+1];
535
                      vertices[3*i+1] = layer-(dY-1.0f);
536
                      }
537
                    break;
538
      case AXIS_YM: for(i=0; i<len; i++)
539
                      {
540
                      vertices[3*i+2] = vertices[3*i+1];
541
                      vertices[3*i+1] = layer-dY;
542
                      }
543
                    break;
544
      case AXIS_ZP: for(i=0; i<len; i++)
545
                      {
546
                      vertices[3*i+2] = layer-(dZ-1.0f);
547
                      }
548
                    break;
549
      case AXIS_ZM: for(i=0; i<len; i++)
550
                      {
551
                      vertices[3*i  ] = -vertices[3*i];
552
                      vertices[3*i+2] = layer-dZ;
553
                      }
554
                    break;
555
      }
556
    }
557

    
558
///////////////////////////////////////////////////////////////////////////////////////////////////
559
// 1. assume the 'wall' is in the XY plane
560
// 2. split the wall into individual connected regions and for each such region:
561
//   a. build the list of vertices (Z=0)
562
//   b. take the axis into consideration and rotate the vertices.
563
//   c. take layer into consideration and move the vertices.
564
//   d. add the resulting vertices to the list.
565

    
566
  private void createVertices(ArrayList<float[]> list, int[][] wall, int axis, int layer)
567
    {
568
    int sections = markSections(wall);
569

    
570
    for(int i=0; i<sections; i++)
571
      {
572
      float[] vertices = buildVertices(wall,i+1);
573
      rotateAndMoveVertices(vertices,axis,layer);
574
      list.add(vertices);
575
/*
576
      int len = vertices.length/3;
577
      String w="";
578

    
579
      for(int j=0; j<len; j++)
580
        {
581
        w += ( "["+vertices[3*j]+" "+vertices[3*j+1]+" "+vertices[3*j+2]+"] ");
582
        }
583
      android.util.Log.e("D", "axis: "+axis+" layer: "+layer+" vertices after: "+w);
584
 */
585
      }
586
    }
587

    
588
///////////////////////////////////////////////////////////////////////////////////////////////////
589

    
590
  private static boolean vertInFace(float[] vertex, float[] move, Static3D faceAxis, float dist)
591
    {
592
    final float MAX_ERROR = 0.01f;
593

    
594
    float x= faceAxis.get0();
595
    float y= faceAxis.get1();
596
    float z= faceAxis.get2();
597

    
598
    float a = (vertex[0]+move[0])*x + (vertex[1]+move[1])*y + (vertex[2]+move[2])*z;
599
    float diff = a - dist;
600

    
601
    return diff>-MAX_ERROR && diff<MAX_ERROR;
602
    }
603

    
604
///////////////////////////////////////////////////////////////////////////////////////////////////
605
// (vertices,indices) define a cubit face, i.e. a connected subset of the NxN grid.
606
// Return its 'diameter', i.e. max(width,height)
607

    
608
  private int faceDiameter(float[][] vertices, int[] indices)
609
    {
610
    float maxX = -dX;
611
    float minX = +dX;
612
    float maxY = -dY;
613
    float minY = +dY;
614
    float maxZ = -dZ;
615
    float minZ = +dZ;
616

    
617
    for (int index : indices)
618
      {
619
      float[] v = vertices[index];
620

    
621
      if (v[0] > maxX) maxX = v[0];
622
      if (v[0] < minX) minX = v[0];
623
      if (v[1] > maxY) maxY = v[1];
624
      if (v[1] < minY) minY = v[1];
625
      if (v[2] > maxZ) maxZ = v[2];
626
      if (v[2] < minZ) minZ = v[2];
627
      }
628

    
629
    float diffX = maxX-minX;
630
    float diffY = maxY-minY;
631
    float diffZ = maxZ-minZ;
632

    
633
    float max = diffX>diffY ? Math.max(diffX,diffZ) : Math.max(diffY,diffZ);
634

    
635
    return (int)max;
636
    }
637

    
638
///////////////////////////////////////////////////////////////////////////////////////////////////
639
// return array of:
640
// 0 if this is an inner face, 1 if its diameter is 1, 2 if diameter is 2, 3 if 3, etc
641

    
642
  private int[] generateBandIndices(float[][] vertices, int[][] indices, float[] move)
643
    {
644
    int numCubitFaces = indices.length;
645
    int[] bandIndices = new int[numCubitFaces];
646

    
647
    for(int cubitFace=0; cubitFace<numCubitFaces; cubitFace++)
648
      {
649
      bandIndices[cubitFace] = 0xffffffff;
650
      int numVertices = indices[cubitFace].length;
651

    
652
      for(int vertex=0; vertex<numVertices; vertex++)
653
        {
654
        int vertBelongsBitmap = 0x00000000;
655
        float[] vert = vertices[ indices[cubitFace][vertex] ];
656

    
657
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[0], dX) ) vertBelongsBitmap |= (1<<0);
658
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[1], dX) ) vertBelongsBitmap |= (1<<1);
659
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[2], dY) ) vertBelongsBitmap |= (1<<2);
660
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[3], dY) ) vertBelongsBitmap |= (1<<3);
661
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[4], dZ) ) vertBelongsBitmap |= (1<<4);
662
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[5], dZ) ) vertBelongsBitmap |= (1<<5);
663

    
664
        bandIndices[cubitFace] &= vertBelongsBitmap;
665
        }
666

    
667
      if( bandIndices[cubitFace]!=0 ) // outer face
668
        {
669
        bandIndices[cubitFace] = faceDiameter(vertices, indices[cubitFace]);
670
        }
671

    
672
      //android.util.Log.e("D", "cubit face "+cubitFace+" : "+bandIndices[cubitFace]);
673
      }
674

    
675
    return bandIndices;
676
    }
677

    
678
///////////////////////////////////////////////////////////////////////////////////////////////////
679

    
680
  private int[] generateCornerIndices(float[][] vertices, boolean roundCorners)
681
    {
682
    int len = vertices.length;
683
    int val = roundCorners ? 0 : -1;
684
    int[] cornerIndices = new int[len];
685
    for(int i=0; i<len; i++) cornerIndices[i] = val;
686
    return cornerIndices;
687
    }
688

    
689
///////////////////////////////////////////////////////////////////////////////////////////////////
690

    
691
  private int computeVectorFace(float[] prev, float[] curr, float[] next)
692
    {
693
    float ax = prev[0]-curr[0];
694
    float ay = prev[1]-curr[1];
695
    float az = prev[2]-curr[2];
696

    
697
    float bx = next[0]-curr[0];
698
    float by = next[1]-curr[1];
699
    float bz = next[2]-curr[2];
700

    
701
    float lena = (float)Math.sqrt(ax*ax + ay*ay + az*az);
702
    float lenb = (float)Math.sqrt(bx*bx + by*by + bz*bz);
703

    
704
    ax /= lena;
705
    ay /= lena;
706
    az /= lena;
707

    
708
    bx /= lenb;
709
    by /= lenb;
710
    bz /= lenb;
711

    
712
    float cx = ax + bx + ay*bz-az*by;
713
    float cy = ay + by + az*bx-ax*bz;
714
    float cz = az + bz + ax*by-ay*bx;
715

    
716
    return (cx<0 ? 0:4) + (cy<0 ? 0:2) + (cz<0 ? 0:1);
717
    }
718

    
719
///////////////////////////////////////////////////////////////////////////////////////////////////
720

    
721
  private float[] computeVector(int index, float[][] vertices, int[][] indices, int[] bandIndices)
722
    {
723
    int band=0;
724
    int len = indices.length;
725
    int vector=-1;
726

    
727
    for(int i=0; i<len; i++)
728
      {
729
      int len2 = indices[i].length;
730

    
731
      for(int j=0; j<len2; j++)
732
        {
733
        if( indices[i][j]==index )
734
          {
735
          int prev = j>0 ? j-1 : len2-1;
736
          int next = j<len2-1 ? j+1 : 0;
737

    
738
          int prevIndex = indices[i][prev];
739
          int currIndex = indices[i][j];
740
          int nextIndex = indices[i][next];
741

    
742
          int newVector = computeVectorFace(vertices[prevIndex],vertices[currIndex],vertices[nextIndex]);
743
          if( vector!=-1 && vector!=newVector ) return null;
744

    
745
          vector = newVector;
746
          band |= bandIndices[i];
747
          }
748
        }
749
      }
750

    
751
    return band==0 ? null : VECTOR[vector];
752
    }
753

    
754
///////////////////////////////////////////////////////////////////////////////////////////////////
755

    
756
  private float[][] generateVectors(float[][] vertices, int[][] indices, int[] bandIndices)
757
    {
758
    int len = vertices.length;
759
    float[][] vectors = new float[len][];
760

    
761
    for(int i=0; i<len; i++)
762
      {
763
      vectors[i] = computeVector(i,vertices,indices,bandIndices);
764
      }
765

    
766
    return vectors;
767
    }
768

    
769
///////////////////////////////////////////////////////////////////////////////////////////////////
770

    
771
  private float[][] generateCenters(float[][] vertices, float[][] vectors)
772
    {
773
    int pointer=0,total=0;
774
    int len = vertices.length;
775

    
776
    for( float[] vector : vectors )
777
      {
778
      if( vector!=null ) total++;
779
      }
780

    
781
    float[][] centers = new float[total][3];
782

    
783
    for( int i=0; i<len; i++ )
784
      {
785
      if( vectors[i]!=null )
786
        {
787
        centers[pointer][0] = vertices[i][0]+vectors[i][0];
788
        centers[pointer][1] = vertices[i][1]+vectors[i][1];
789
        centers[pointer][2] = vertices[i][2]+vectors[i][2];
790
        pointer++;
791
        }
792
      }
793

    
794
    return centers;
795
    }
796

    
797
///////////////////////////////////////////////////////////////////////////////////////////////////
798

    
799
  private int[] generateCenterIndices(float[][] vectors)
800
    {
801
    int pointer=0;
802
    int len = vectors.length;
803
    int[] centerIndices = new int[len];
804

    
805
    for(int i=0; i<len; i++)
806
      {
807
      if( vectors[i]==null )
808
        {
809
        centerIndices[i] = -1;
810
        }
811
      else
812
        {
813
        centerIndices[i] = pointer;
814
        pointer++;
815
        }
816
      }
817

    
818
    return centerIndices;
819
    }
820

    
821
///////////////////////////////////////////////////////////////////////////////////////////////////
822
// PUBLIC API
823

    
824
  public static FactoryBandagedCubit getInstance()
825
    {
826
    if( mThis==null ) mThis = new FactoryBandagedCubit();
827
    return mThis;
828
    }
829

    
830
///////////////////////////////////////////////////////////////////////////////////////////////////
831

    
832
  public void prepare(int numVariants, int x, int y, int z)
833
    {
834
    if( mVertexArray==null ) mVertexArray = new ArrayList<>();
835
    mVertices= new float[numVariants][][];
836
    mIndices = new int[numVariants][][];
837
    mMove = new float[numVariants][3];
838

    
839
    mX = x;
840
    mY = y;
841
    mZ = z;
842

    
843
    dX = mX/2.0f;
844
    dY = mY/2.0f;
845
    dZ = mZ/2.0f;
846

    
847
    mMax = mX>mY ? Math.max(mX,mZ) : Math.max(mY,mZ);
848

    
849
    mWall   = new int[mMax][mMax];
850
    mPoints = new int[mMax+1][mMax+1];
851
    mTmp    = new boolean[mX][mY][mZ];
852
    }
853

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

    
856
  public ObjectShape createIrregularShape(int variant, float[] pos)
857
    {
858
    mVertexArray.clear();
859

    
860
    float begX = 0.5f*(1-mX);
861
    float begY = 0.5f*(1-mY);
862
    float begZ = 0.5f*(1-mZ);
863

    
864
    for(int x=0; x<mX; x++)
865
      for(int y=0; y<mY; y++)
866
        for(int z=0; z<mZ; z++) mTmp[x][y][z] = cubitExists(pos,begX+x,begY+y,begZ+z);
867

    
868
    for(int x=0; x<mX; x++) createRight (x,mVertexArray);
869
    for(int x=0; x<mX; x++) createLeft  (x,mVertexArray);
870
    for(int y=0; y<mY; y++) createTop   (y,mVertexArray);
871
    for(int y=0; y<mY; y++) createBottom(y,mVertexArray);
872
    for(int z=0; z<mZ; z++) createFront (z,mVertexArray);
873
    for(int z=0; z<mZ; z++) createBack  (z,mVertexArray);
874

    
875
    float[][] verts = getVertices(mVertexArray,pos,variant);
876
    int[][] inds    = getIndices(mVertexArray);
877

    
878
    compressVerticesAndIndices(variant,verts,inds);
879

    
880
    return new ObjectShape(mVertices[variant], mIndices[variant]);
881
    }
882

    
883
///////////////////////////////////////////////////////////////////////////////////////////////////
884

    
885
  private void debug(float[][] vert, int[][] ind)
886
    {
887
    String vv="VERTICES: ";
888
    for (float[] floats : vert)
889
      {
890
      vv += "\n";
891
      int lenV2 = floats.length / 3;
892

    
893
      for (int v2 = 0; v2 < lenV2; v2++)
894
        {
895
        vv += " {";
896
        vv += (floats[3 * v2] + " ");
897
        vv += (floats[3 * v2 + 1] + " ");
898
        vv += (floats[3 * v2 + 2] + " ");
899
        vv += "}";
900
        }
901
      }
902
    android.util.Log.e("D", vv);
903

    
904
    String ii="INDICES: ";
905
    for (int[] ints : ind)
906
      {
907
      ii += "\n";
908
      int lenI2 = ints.length;
909

    
910
      for (int i2 = 0; i2 < lenI2; i2++)
911
        {
912
        ii += (ints[i2] + " ");
913
        }
914
      }
915
    android.util.Log.e("D", ii);
916
    }
917

    
918
///////////////////////////////////////////////////////////////////////////////////////////////////
919

    
920
  public ObjectFaceShape createIrregularFaceShape(int variant, boolean iconMode, boolean roundCorners)
921
    {
922
    float height   = iconMode ? 0.001f : 0.048f;
923
    int angle      = 60;
924
    float R        = 0.2f;
925
    float S        = 0.5f;
926
    int numVertices= 5;
927
    int extraI     = 0;
928
    int extraV     = 0;
929

    
930
    float[][] corners   = { {0.02f,0.12f} };
931
    float[][] bands     = { {  0.001f,angle,R,S,numVertices,extraV,extraI},
932
                            {height/1,angle,R,S,numVertices,extraV,extraI},
933
                            {height/2,angle,R,S,numVertices,extraV,extraI},
934
                            {height/3,angle,R,S,numVertices,extraV,extraI} };
935

    
936
    int[] bandIndices   = generateBandIndices(mVertices[variant], mIndices[variant], mMove[variant]);
937
    int[] cornerIndices = generateCornerIndices(mVertices[variant], roundCorners);
938
    float[][] vertexVec = generateVectors(mVertices[variant], mIndices[variant], bandIndices);
939
    float[][] centers   = generateCenters(mVertices[variant], vertexVec);
940
    int[] centerIndices = generateCenterIndices(vertexVec);
941

    
942
    return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
943
    }
944

    
945
///////////////////////////////////////////////////////////////////////////////////////////////////
946

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

    
955
    FactoryCubit factory = FactoryCubit.getInstance();
956
    factory.clear();
957
    factory.createNewFaceTransform(shape,null);
958
    return factory.createRoundedSolid(shape,face,MESH_NICE,numComponents);
959
    }
960
  }
(2-2/10)