Project

General

Profile

« Previous | Next » 

Revision c18507d9

Added by Leszek Koltunski about 1 year ago

Introduce BandagedObjectPyraminx.

View differences:

src/main/java/org/distorted/objectlib/helpers/FactoryBandagedCubit.java
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 int[][] mBandIndices;
52
  private float[][] mMove;
53

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

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

  
62
  private FactoryBandagedCubit()
63
    {
64

  
65
    }
66

  
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

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

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

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

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

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

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

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

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

  
113
    return verts;
114
    }
115

  
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117

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

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

  
133
    return indices;
134
    }
135

  
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

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

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

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

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

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

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

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

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

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

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

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

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

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

  
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215

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

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

  
223
    return false;
224
    }
225

  
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227

  
228
  private void createRight(int x, ArrayList<float[]> list)
229
    {
230
    for(int y=0; y<mMax; y++)
231
      for(int z=0; z<mMax; z++)
232
        {
233
        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]) );
234
        mWall[z][y] = b ? WALL_MARKED : WALL_EMPTY;
235
        }
236

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

  
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241

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

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

  
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255

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

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

  
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269

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

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

  
282
///////////////////////////////////////////////////////////////////////////////////////////////////
283

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

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

  
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297

  
298
  private void createBack(int z, ArrayList<float[]> list)
299
    {
300
    for(int y=0; y<mMax; y++)
301
      for(int x=0; x<mMax; x++)
302
        {
303
        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]) );
304
        mWall[x][y] = b ? WALL_MARKED : WALL_EMPTY;
305
        }
306

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

  
310
///////////////////////////////////////////////////////////////////////////////////////////////////
311

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

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

  
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323

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

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

  
336
    return sections;
337
    }
338

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

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

  
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

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

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

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

  
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361

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

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

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

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

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

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

  
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384

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

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

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

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

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

  
405
///////////////////////////////////////////////////////////////////////////////////////////////////
406

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

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

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

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

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

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

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

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

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

  
448
      pointer++;
449
      }
450

  
451
    return vertices;
452
    }
453

  
454
///////////////////////////////////////////////////////////////////////////////////////////////////
455

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

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

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

  
500
    return numPoints;
501
    }
502

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

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

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

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

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

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

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

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

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

  
583
///////////////////////////////////////////////////////////////////////////////////////////////////
584

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

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

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

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

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

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

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

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

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

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

  
630
    return (int)max;
631
    }
632

  
633
///////////////////////////////////////////////////////////////////////////////////////////////////
634
// return array of:
635
// 0 if this is an inner face, 1 if its diameter is 1, 2 if diameter is 2, 3 if 3, etc
636
// but only up to 5 (because the number of bands is 6 - see createIrregularFaceShape() )
637

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

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

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

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

  
660
        bandIndices[cubitFace] &= vertBelongsBitmap;
661
        }
662

  
663
      if( bandIndices[cubitFace]!=0 ) // outer face
664
        {
665
        int diameter = faceDiameter(vertices, indices[cubitFace]);
666
        bandIndices[cubitFace] = (diameter>=6 ? 5:diameter);
667
        }
668

  
669
      //android.util.Log.e("D", "cubit face "+cubitFace+" : "+bandIndices[cubitFace]);
670
      }
671

  
672
    return bandIndices;
673
    }
674

  
675
///////////////////////////////////////////////////////////////////////////////////////////////////
676

  
677
  private int computeVectorFace(float[] prev, float[] curr, float[] next)
678
    {
679
    float ax = prev[0]-curr[0];
680
    float ay = prev[1]-curr[1];
681
    float az = prev[2]-curr[2];
682

  
683
    float bx = next[0]-curr[0];
684
    float by = next[1]-curr[1];
685
    float bz = next[2]-curr[2];
686

  
687
    float lena = (float)Math.sqrt(ax*ax + ay*ay + az*az);
688
    float lenb = (float)Math.sqrt(bx*bx + by*by + bz*bz);
689

  
690
    ax /= lena;
691
    ay /= lena;
692
    az /= lena;
693

  
694
    bx /= lenb;
695
    by /= lenb;
696
    bz /= lenb;
697

  
698
    float cx = ax + bx + ay*bz-az*by;
699
    float cy = ay + by + az*bx-ax*bz;
700
    float cz = az + bz + ax*by-ay*bx;
701

  
702
    return (cx<0 ? 0:4) + (cy<0 ? 0:2) + (cz<0 ? 0:1);
703
    }
704

  
705
///////////////////////////////////////////////////////////////////////////////////////////////////
706

  
707
  private float[] computeVector(int index, float[][] vertices, int[][] indices, int[] bandIndices)
708
    {
709
    int band=0;
710
    int len = indices.length;
711
    int vector=-1;
712

  
713
    for(int i=0; i<len; i++)
714
      {
715
      int len2 = indices[i].length;
716

  
717
      for(int j=0; j<len2; j++)
718
        {
719
        if( indices[i][j]==index )
720
          {
721
          int prev = j>0 ? j-1 : len2-1;
722
          int next = j<len2-1 ? j+1 : 0;
723

  
724
          int prevIndex = indices[i][prev];
725
          int currIndex = indices[i][j];
726
          int nextIndex = indices[i][next];
727

  
728
          int newVector = computeVectorFace(vertices[prevIndex],vertices[currIndex],vertices[nextIndex]);
729
          if( vector!=-1 && vector!=newVector ) return null;
730

  
731
          vector = newVector;
732
          band |= bandIndices[i];
733
          }
734
        }
735
      }
736

  
737
    return band==0 ? null : VECTOR[vector];
738
    }
739

  
740
///////////////////////////////////////////////////////////////////////////////////////////////////
741

  
742
  private float[][] generateVectors(float[][] vertices, int[][] indices, int[] bandIndices)
743
    {
744
    int len = vertices.length;
745
    float[][] vectors = new float[len][];
746

  
747
    for(int i=0; i<len; i++)
748
      {
749
      vectors[i] = computeVector(i,vertices,indices,bandIndices);
750
      }
751

  
752
    return vectors;
753
    }
754

  
755
///////////////////////////////////////////////////////////////////////////////////////////////////
756

  
757
  private void debug(float[][] vert, int[][] ind)
758
    {
759
    String vv="VERTICES: ";
760
    for (float[] floats : vert)
761
      {
762
      vv += "\n";
763
      int lenV2 = floats.length / 3;
764

  
765
      for (int v2 = 0; v2 < lenV2; v2++)
766
        {
767
        vv += " {";
768
        vv += (floats[3 * v2] + " ");
769
        vv += (floats[3 * v2 + 1] + " ");
770
        vv += (floats[3 * v2 + 2] + " ");
771
        vv += "}";
772
        }
773
      }
774
    android.util.Log.e("D", vv);
775

  
776
    String ii="INDICES: ";
777
    for (int[] ints : ind)
778
      {
779
      ii += "\n";
780
      int lenI2 = ints.length;
781

  
782
      for (int i2 = 0; i2 < lenI2; i2++)
783
        {
784
        ii += (ints[i2] + " ");
785
        }
786
      }
787
    android.util.Log.e("D", ii);
788
    }
789

  
790
///////////////////////////////////////////////////////////////////////////////////////////////////
791
// PUBLIC API
792

  
793
  public static FactoryBandagedCubit getInstance()
794
    {
795
    if( mThis==null ) mThis = new FactoryBandagedCubit();
796
    return mThis;
797
    }
798

  
799
///////////////////////////////////////////////////////////////////////////////////////////////////
800

  
801
  public void prepare(int numVariants, int x, int y, int z)
802
    {
803
    if( mVertexArray==null ) mVertexArray = new ArrayList<>();
804
    mVertices= new float[numVariants][][];
805
    mIndices = new int[numVariants][][];
806
    mMove = new float[numVariants][3];
807
    mBandIndices = new int[numVariants][];
808

  
809
    mX = x;
810
    mY = y;
811
    mZ = z;
812

  
813
    dX = mX/2.0f;
814
    dY = mY/2.0f;
815
    dZ = mZ/2.0f;
816

  
817
    mMax = mX>mY ? Math.max(mX,mZ) : Math.max(mY,mZ);
818

  
819
    mWall   = new int[mMax][mMax];
820
    mPoints = new int[mMax+1][mMax+1];
821
    mTmp    = new boolean[mX][mY][mZ];
822
    }
823

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

  
826
  public ObjectShape createIrregularShape(int variant, float[] pos)
827
    {
828
    mVertexArray.clear();
829

  
830
    float begX = 0.5f*(1-mX);
831
    float begY = 0.5f*(1-mY);
832
    float begZ = 0.5f*(1-mZ);
833

  
834
    for(int x=0; x<mX; x++)
835
      for(int y=0; y<mY; y++)
836
        for(int z=0; z<mZ; z++) mTmp[x][y][z] = cubitExists(pos,begX+x,begY+y,begZ+z);
837

  
838
    for(int x=0; x<mX; x++) createRight (x,mVertexArray);
839
    for(int x=0; x<mX; x++) createLeft  (x,mVertexArray);
840
    for(int y=0; y<mY; y++) createTop   (y,mVertexArray);
841
    for(int y=0; y<mY; y++) createBottom(y,mVertexArray);
842
    for(int z=0; z<mZ; z++) createFront (z,mVertexArray);
843
    for(int z=0; z<mZ; z++) createBack  (z,mVertexArray);
844

  
845
    float[][] verts = getVertices(mVertexArray,pos,variant);
846
    int[][] inds    = getIndices(mVertexArray);
847

  
848
    compressVerticesAndIndices(variant,verts,inds);
849
    mBandIndices[variant] = generateBandIndices(mVertices[variant], mIndices[variant], mMove[variant]);
850

  
851
    return new ObjectShape(mVertices[variant], mIndices[variant]);
852
    }
853

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

  
856
  public ObjectVertexEffects createVertexEffects(int variant, boolean roundCorners)
857
    {
858
    float[][] vertVec= generateVectors(mVertices[variant], mIndices[variant], mBandIndices[variant]);
859
    int numEffects   = mVertices[variant].length;
860
    float S          = 0.04f;
861
    float[] region   = {0,0,0,0.15f};
862
    String[] names   = new String[numEffects];
863
    float[][] regions= new float[numEffects][];
864
    boolean[] uses   = new boolean[numEffects];
865
    float[][] vars   = new float[numEffects][];
866

  
867
    for(int i=0; i<numEffects; i++)
868
      {
869
      float[] v = vertVec[i];
870

  
871
      if( v!=null )
872
        {
873
        names[i]  = FactoryCubit.NAME;
874
        regions[i]= region;
875
        uses[i]   = roundCorners;
876
        vars[i]   = new float[] { 0, S*v[0], S*v[1], S*v[2], 1 };
877
        }
878
      }
879

  
880
    return new ObjectVertexEffects(names,vars,mVertices[variant],regions,uses);
881
    }
882

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

  
885
  public ObjectFaceShape createIrregularFaceShape(int variant, boolean iconMode)
886
    {
887
    float height= iconMode ? 0.001f : 0.048f;
888
    int angle   = 60;
889
    float R     = 0.2f;
890
    float S     = 0.5f;
891
    int numVerts= 5;
892
    int extraI  = 0;
893
    int extraV  = 0;
894

  
895
    float[][] bands  = { {  0.001f,angle,R,S,numVerts,extraV,extraI},
896
                         {height/1,angle,R,S,numVerts,extraV,extraI},
897
                         {height/2,angle,R,S,numVerts,extraV,extraI},
898
                         {height/3,angle,R,S,numVerts,extraV,extraI},
899
                         {height/4,angle,R,S,numVerts,extraV,extraI},
900
                         {height/5,angle,R,S,numVerts,extraV,extraI} };
901

  
902
    return new ObjectFaceShape(bands,mBandIndices[variant],null);
903
    }
904

  
905
///////////////////////////////////////////////////////////////////////////////////////////////////
906

  
907
  public MeshBase createMesh(float[] pos, int x, int y, int z, boolean iconMode, boolean roundCorners)
908
    {
909
    prepare(1,x,y,z);
910
    ObjectShape shape           = createIrregularShape(0,pos);
911
    ObjectFaceShape face        = createIrregularFaceShape(0,iconMode);
912
    ObjectVertexEffects effects = createVertexEffects(0,roundCorners);
913
    int[][] indices             = shape.getVertIndices();
914
    int numComponents           = indices.length;
915

  
916
    FactoryCubit factory = FactoryCubit.getInstance();
917
    factory.clear();
918
    factory.createNewFaceTransform(shape,null);
919
    return factory.createRoundedSolid(shape,face,effects,MESH_NICE,numComponents);
920
    }
921
  }
src/main/java/org/distorted/objectlib/helpers/FactoryBandagedCuboid.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

  
10
package org.distorted.objectlib.helpers;
11

  
12
import java.util.ArrayList;
13

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

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

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

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

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

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

  
46
  private static FactoryBandagedCuboid mThis;
47
  private ArrayList<float[]> mVertexArray;
48
  private ArrayList<float[]> mTmpArray;
49
  private float[][][] mVertices;
50
  private int[][][] mIndices;
51
  private int[][] mBandIndices;
52
  private float[][] mMove;
53

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

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

  
62
  private FactoryBandagedCuboid()
63
    {
64

  
65
    }
66

  
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

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

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

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

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

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

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

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

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

  
113
    return verts;
114
    }
115

  
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117

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

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

  
133
    return indices;
134
    }
135

  
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

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

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

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

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

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

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

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

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

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

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

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

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

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

  
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215

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

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

  
223
    return false;
224
    }
225

  
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227

  
228
  private void createRight(int x, ArrayList<float[]> list)
229
    {
230
    for(int y=0; y<mMax; y++)
231
      for(int z=0; z<mMax; z++)
232
        {
233
        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]) );
234
        mWall[z][y] = b ? WALL_MARKED : WALL_EMPTY;
235
        }
236

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

  
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241

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

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

  
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255

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

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

  
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269

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

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

  
282
///////////////////////////////////////////////////////////////////////////////////////////////////
283

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

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

  
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297

  
298
  private void createBack(int z, ArrayList<float[]> list)
299
    {
300
    for(int y=0; y<mMax; y++)
301
      for(int x=0; x<mMax; x++)
302
        {
303
        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]) );
304
        mWall[x][y] = b ? WALL_MARKED : WALL_EMPTY;
305
        }
306

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

  
310
///////////////////////////////////////////////////////////////////////////////////////////////////
311

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

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

  
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323

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

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

  
336
    return sections;
337
    }
338

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

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

  
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

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

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

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

  
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361

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

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

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

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

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

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

  
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384

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

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

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

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

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

  
405
///////////////////////////////////////////////////////////////////////////////////////////////////
406

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

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

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

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

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

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

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

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

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

  
448
      pointer++;
449
      }
450

  
451
    return vertices;
452
    }
453

  
454
///////////////////////////////////////////////////////////////////////////////////////////////////
455

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

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

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

  
500
    return numPoints;
501
    }
502

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

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

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

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

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

  
561
    float dx = (axis==AXIS_XP || axis==AXIS_XM) ? dZ : dX;
562
    float dy = (axis==AXIS_YP || axis==AXIS_YM) ? dZ : dY;
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff