Project

General

Profile

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

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

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, float dx, float dy)
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+2] = layer-dZ;
552
                      vertices[3*i  ] =-vertices[3*i  ];
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
    float dx = (axis==AXIS_XP || axis==AXIS_XM) ? dZ : dX;
571
    float dy = (axis==AXIS_YP || axis==AXIS_YM) ? dZ : dY;
572

    
573
    for(int i=0; i<sections; i++)
574
      {
575
      float[] vertices = buildVertices(wall,i+1,dx,dy);
576

    
577
      rotateAndMoveVertices(vertices,axis,layer);
578
      list.add(vertices);
579
/*
580
      int len = vertices.length/3;
581
      String w="";
582

    
583
      for(int j=0; j<len; j++)
584
        {
585
        w += ( "["+vertices[3*j]+" "+vertices[3*j+1]+" "+vertices[3*j+2]+"] ");
586
        }
587
      android.util.Log.e("D", "1 section: "+i+" axis: "+axis+" layer: "+layer+" vertices after: "+w);
588
*/
589
      }
590
    }
591

    
592
///////////////////////////////////////////////////////////////////////////////////////////////////
593

    
594
  private static boolean vertInFace(float[] vertex, float[] move, Static3D faceAxis, float dist)
595
    {
596
    final float MAX_ERROR = 0.01f;
597

    
598
    float x= faceAxis.get0();
599
    float y= faceAxis.get1();
600
    float z= faceAxis.get2();
601

    
602
    float a = (vertex[0]+move[0])*x + (vertex[1]+move[1])*y + (vertex[2]+move[2])*z;
603
    float diff = a - dist;
604

    
605
    return diff>-MAX_ERROR && diff<MAX_ERROR;
606
    }
607

    
608
///////////////////////////////////////////////////////////////////////////////////////////////////
609
// (vertices,indices) define a cubit face, i.e. a connected subset of the NxN grid.
610
// Return its 'diameter', i.e. max(width,height)
611

    
612
  private int faceDiameter(float[][] vertices, int[] indices)
613
    {
614
    float maxX = -dX;
615
    float minX = +dX;
616
    float maxY = -dY;
617
    float minY = +dY;
618
    float maxZ = -dZ;
619
    float minZ = +dZ;
620

    
621
    for (int index : indices)
622
      {
623
      float[] v = vertices[index];
624

    
625
      if (v[0] > maxX) maxX = v[0];
626
      if (v[0] < minX) minX = v[0];
627
      if (v[1] > maxY) maxY = v[1];
628
      if (v[1] < minY) minY = v[1];
629
      if (v[2] > maxZ) maxZ = v[2];
630
      if (v[2] < minZ) minZ = v[2];
631
      }
632

    
633
    float diffX = maxX-minX;
634
    float diffY = maxY-minY;
635
    float diffZ = maxZ-minZ;
636

    
637
    float max = diffX>diffY ? Math.max(diffX,diffZ) : Math.max(diffY,diffZ);
638

    
639
    return (int)max;
640
    }
641

    
642
///////////////////////////////////////////////////////////////////////////////////////////////////
643
// return array of:
644
// 0 if this is an inner face, 1 if its diameter is 1, 2 if diameter is 2, 3 if 3, etc
645

    
646
  private int[] generateBandIndices(float[][] vertices, int[][] indices, float[] move)
647
    {
648
    int numCubitFaces = indices.length;
649
    int[] bandIndices = new int[numCubitFaces];
650

    
651
    for(int cubitFace=0; cubitFace<numCubitFaces; cubitFace++)
652
      {
653
      bandIndices[cubitFace] = 0xffffffff;
654
      int numVertices = indices[cubitFace].length;
655

    
656
      for(int vertex=0; vertex<numVertices; vertex++)
657
        {
658
        int vertBelongsBitmap = 0x00000000;
659
        float[] vert = vertices[ indices[cubitFace][vertex] ];
660

    
661
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[0], dX) ) vertBelongsBitmap |= (1<<0);
662
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[1], dX) ) vertBelongsBitmap |= (1<<1);
663
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[2], dY) ) vertBelongsBitmap |= (1<<2);
664
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[3], dY) ) vertBelongsBitmap |= (1<<3);
665
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[4], dZ) ) vertBelongsBitmap |= (1<<4);
666
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[5], dZ) ) vertBelongsBitmap |= (1<<5);
667

    
668
        bandIndices[cubitFace] &= vertBelongsBitmap;
669
        }
670

    
671
      if( bandIndices[cubitFace]!=0 ) // outer face
672
        {
673
        bandIndices[cubitFace] = faceDiameter(vertices, indices[cubitFace]);
674
        }
675

    
676
      //android.util.Log.e("D", "cubit face "+cubitFace+" : "+bandIndices[cubitFace]);
677
      }
678

    
679
    return bandIndices;
680
    }
681

    
682
///////////////////////////////////////////////////////////////////////////////////////////////////
683

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

    
693
///////////////////////////////////////////////////////////////////////////////////////////////////
694

    
695
  private int computeVectorFace(float[] prev, float[] curr, float[] next)
696
    {
697
    float ax = prev[0]-curr[0];
698
    float ay = prev[1]-curr[1];
699
    float az = prev[2]-curr[2];
700

    
701
    float bx = next[0]-curr[0];
702
    float by = next[1]-curr[1];
703
    float bz = next[2]-curr[2];
704

    
705
    float lena = (float)Math.sqrt(ax*ax + ay*ay + az*az);
706
    float lenb = (float)Math.sqrt(bx*bx + by*by + bz*bz);
707

    
708
    ax /= lena;
709
    ay /= lena;
710
    az /= lena;
711

    
712
    bx /= lenb;
713
    by /= lenb;
714
    bz /= lenb;
715

    
716
    float cx = ax + bx + ay*bz-az*by;
717
    float cy = ay + by + az*bx-ax*bz;
718
    float cz = az + bz + ax*by-ay*bx;
719

    
720
    return (cx<0 ? 0:4) + (cy<0 ? 0:2) + (cz<0 ? 0:1);
721
    }
722

    
723
///////////////////////////////////////////////////////////////////////////////////////////////////
724

    
725
  private float[] computeVector(int index, float[][] vertices, int[][] indices, int[] bandIndices)
726
    {
727
    int band=0;
728
    int len = indices.length;
729
    int vector=-1;
730

    
731
    for(int i=0; i<len; i++)
732
      {
733
      int len2 = indices[i].length;
734

    
735
      for(int j=0; j<len2; j++)
736
        {
737
        if( indices[i][j]==index )
738
          {
739
          int prev = j>0 ? j-1 : len2-1;
740
          int next = j<len2-1 ? j+1 : 0;
741

    
742
          int prevIndex = indices[i][prev];
743
          int currIndex = indices[i][j];
744
          int nextIndex = indices[i][next];
745

    
746
          int newVector = computeVectorFace(vertices[prevIndex],vertices[currIndex],vertices[nextIndex]);
747
          if( vector!=-1 && vector!=newVector ) return null;
748

    
749
          vector = newVector;
750
          band |= bandIndices[i];
751
          }
752
        }
753
      }
754

    
755
    return band==0 ? null : VECTOR[vector];
756
    }
757

    
758
///////////////////////////////////////////////////////////////////////////////////////////////////
759

    
760
  private float[][] generateVectors(float[][] vertices, int[][] indices, int[] bandIndices)
761
    {
762
    int len = vertices.length;
763
    float[][] vectors = new float[len][];
764

    
765
    for(int i=0; i<len; i++)
766
      {
767
      vectors[i] = computeVector(i,vertices,indices,bandIndices);
768
      }
769

    
770
    return vectors;
771
    }
772

    
773
///////////////////////////////////////////////////////////////////////////////////////////////////
774

    
775
  private float[][] generateCenters(float[][] vertices, float[][] vectors)
776
    {
777
    int pointer=0,total=0;
778
    int len = vertices.length;
779

    
780
    for( float[] vector : vectors )
781
      {
782
      if( vector!=null ) total++;
783
      }
784

    
785
    float[][] centers = new float[total][3];
786

    
787
    for( int i=0; i<len; i++ )
788
      {
789
      if( vectors[i]!=null )
790
        {
791
        centers[pointer][0] = vertices[i][0]+vectors[i][0];
792
        centers[pointer][1] = vertices[i][1]+vectors[i][1];
793
        centers[pointer][2] = vertices[i][2]+vectors[i][2];
794
        pointer++;
795
        }
796
      }
797

    
798
    return centers;
799
    }
800

    
801
///////////////////////////////////////////////////////////////////////////////////////////////////
802

    
803
  private int[] generateCenterIndices(float[][] vectors)
804
    {
805
    int pointer=0;
806
    int len = vectors.length;
807
    int[] centerIndices = new int[len];
808

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

    
822
    return centerIndices;
823
    }
824

    
825
///////////////////////////////////////////////////////////////////////////////////////////////////
826
// PUBLIC API
827

    
828
  public static FactoryBandagedCubit getInstance()
829
    {
830
    if( mThis==null ) mThis = new FactoryBandagedCubit();
831
    return mThis;
832
    }
833

    
834
///////////////////////////////////////////////////////////////////////////////////////////////////
835

    
836
  public void prepare(int numVariants, int x, int y, int z)
837
    {
838
    if( mVertexArray==null ) mVertexArray = new ArrayList<>();
839
    mVertices= new float[numVariants][][];
840
    mIndices = new int[numVariants][][];
841
    mMove = new float[numVariants][3];
842

    
843
    mX = x;
844
    mY = y;
845
    mZ = z;
846

    
847
    dX = mX/2.0f;
848
    dY = mY/2.0f;
849
    dZ = mZ/2.0f;
850

    
851
    mMax = mX>mY ? Math.max(mX,mZ) : Math.max(mY,mZ);
852

    
853
    mWall   = new int[mMax][mMax];
854
    mPoints = new int[mMax+1][mMax+1];
855
    mTmp    = new boolean[mX][mY][mZ];
856
    }
857

    
858
///////////////////////////////////////////////////////////////////////////////////////////////////
859

    
860
  public ObjectShape createIrregularShape(int variant, float[] pos)
861
    {
862
    mVertexArray.clear();
863

    
864
    float begX = 0.5f*(1-mX);
865
    float begY = 0.5f*(1-mY);
866
    float begZ = 0.5f*(1-mZ);
867

    
868
    for(int x=0; x<mX; x++)
869
      for(int y=0; y<mY; y++)
870
        for(int z=0; z<mZ; z++) mTmp[x][y][z] = cubitExists(pos,begX+x,begY+y,begZ+z);
871

    
872
    for(int x=0; x<mX; x++) createRight (x,mVertexArray);
873
    for(int x=0; x<mX; x++) createLeft  (x,mVertexArray);
874
    for(int y=0; y<mY; y++) createTop   (y,mVertexArray);
875
    for(int y=0; y<mY; y++) createBottom(y,mVertexArray);
876
    for(int z=0; z<mZ; z++) createFront (z,mVertexArray);
877
    for(int z=0; z<mZ; z++) createBack  (z,mVertexArray);
878

    
879
    float[][] verts = getVertices(mVertexArray,pos,variant);
880
    int[][] inds    = getIndices(mVertexArray);
881

    
882
    compressVerticesAndIndices(variant,verts,inds);
883

    
884
    return new ObjectShape(mVertices[variant], mIndices[variant]);
885
    }
886

    
887
///////////////////////////////////////////////////////////////////////////////////////////////////
888

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

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

    
908
    String ii="INDICES: ";
909
    for (int[] ints : ind)
910
      {
911
      ii += "\n";
912
      int lenI2 = ints.length;
913

    
914
      for (int i2 = 0; i2 < lenI2; i2++)
915
        {
916
        ii += (ints[i2] + " ");
917
        }
918
      }
919
    android.util.Log.e("D", ii);
920
    }
921

    
922
///////////////////////////////////////////////////////////////////////////////////////////////////
923

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

    
934
    float[][] corners   = { {0.02f,0.12f} };
935
    float[][] bands     = { {  0.001f,angle,R,S,numVertices,extraV,extraI},
936
                            {height/1,angle,R,S,numVertices,extraV,extraI},
937
                            {height/2,angle,R,S,numVertices,extraV,extraI},
938
                            {height/3,angle,R,S,numVertices,extraV,extraI} };
939

    
940
    int[] bandIndices   = generateBandIndices(mVertices[variant], mIndices[variant], mMove[variant]);
941
    int[] cornerIndices = generateCornerIndices(mVertices[variant], roundCorners);
942
    float[][] vertexVec = generateVectors(mVertices[variant], mIndices[variant], bandIndices);
943
    float[][] centers   = generateCenters(mVertices[variant], vertexVec);
944
    int[] centerIndices = generateCenterIndices(vertexVec);
945

    
946
    return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
947
    }
948

    
949
///////////////////////////////////////////////////////////////////////////////////////////////////
950

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

    
959
    FactoryCubit factory = FactoryCubit.getInstance();
960
    factory.clear();
961
    factory.createNewFaceTransform(shape,null);
962
    return factory.createRoundedSolid(shape,face,MESH_NICE,numComponents);
963
    }
964
  }
(2-2/10)