Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / helpers / FactoryBandagedPyraminx.java @ c18507d9

1 a7c10d03 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6 a7a40b3c Leszek Koltunski
// 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 a7c10d03 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10
package org.distorted.objectlib.helpers;
11
12 c18507d9 Leszek Koltunski
import static org.distorted.objectlib.main.TwistyObject.MESH_NICE;
13 a7c10d03 Leszek Koltunski
14 12aa6192 Leszek Koltunski
import org.distorted.library.mesh.MeshBase;
15 786098dd Leszek Koltunski
import org.distorted.library.type.Static3D;
16
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
17
18 c18507d9 Leszek Koltunski
import java.util.ArrayList;
19 12aa6192 Leszek Koltunski
20 786098dd Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
21
22 c18507d9 Leszek Koltunski
public class FactoryBandagedPyraminx
23 a7c10d03 Leszek Koltunski
  {
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 5987822f Leszek Koltunski
  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 c18507d9 Leszek Koltunski
  private static FactoryBandagedPyraminx mThis;
47 a7c10d03 Leszek Koltunski
  private ArrayList<float[]> mVertexArray;
48 b442e28c Leszek Koltunski
  private ArrayList<float[]> mTmpArray;
49 a7c10d03 Leszek Koltunski
  private float[][][] mVertices;
50
  private int[][][] mIndices;
51 84a17011 Leszek Koltunski
  private int[][] mBandIndices;
52 29ad5fc9 Leszek Koltunski
  private float[][] mMove;
53 b1f0d55d Leszek Koltunski
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 a7c10d03 Leszek Koltunski
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61
62 c18507d9 Leszek Koltunski
  private FactoryBandagedPyraminx()
63 a7c10d03 Leszek Koltunski
    {
64 b1f0d55d Leszek Koltunski
65 a7c10d03 Leszek Koltunski
    }
66
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68
69 29ad5fc9 Leszek Koltunski
  private float[][] getVertices(ArrayList<float[]> list, float[] move, int variant)
70 a7c10d03 Leszek Koltunski
    {
71 b8b71f52 Leszek Koltunski
    int numMoves = move.length/3;
72 29ad5fc9 Leszek Koltunski
    mMove[variant][0]=0.0f;
73
    mMove[variant][1]=0.0f;
74
    mMove[variant][2]=0.0f;
75 b8b71f52 Leszek Koltunski
76
    for(int m=0; m<numMoves; m++)
77
      {
78 29ad5fc9 Leszek Koltunski
      mMove[variant][0] += move[3*m  ];
79
      mMove[variant][1] += move[3*m+1];
80
      mMove[variant][2] += move[3*m+2];
81 b8b71f52 Leszek Koltunski
      }
82
83 29ad5fc9 Leszek Koltunski
    mMove[variant][0]/=numMoves;
84
    mMove[variant][1]/=numMoves;
85
    mMove[variant][2]/=numMoves;
86 b8b71f52 Leszek Koltunski
87
    int total  = 0;
88 a7c10d03 Leszek Koltunski
    int length = list.size();
89
    float[][] vertices = new float[length][];
90 b8b71f52 Leszek Koltunski
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 29ad5fc9 Leszek Koltunski
        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 b8b71f52 Leszek Koltunski
        pointer++;
110
        }
111
      }
112
113
    return verts;
114 a7c10d03 Leszek Koltunski
    }
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 b8b71f52 Leszek Koltunski
      int len = f.length/3;
128 a7c10d03 Leszek Koltunski
      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 b442e28c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 5987822f Leszek Koltunski
// (each one normally is a corner of three faces) or even six times. Compress!
165 b442e28c Leszek Koltunski
// 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 a7c10d03 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 b1f0d55d Leszek Koltunski
  private void createRight(int x, ArrayList<float[]> list)
229 a7c10d03 Leszek Koltunski
    {
230 b1f0d55d Leszek Koltunski
    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 a7c10d03 Leszek Koltunski
237 b1f0d55d Leszek Koltunski
    createVertices(list,mWall,AXIS_XP,x);
238 a7c10d03 Leszek Koltunski
    }
239
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241
242 b1f0d55d Leszek Koltunski
  private void createLeft(int x, ArrayList<float[]> list)
243 a7c10d03 Leszek Koltunski
    {
244 b1f0d55d Leszek Koltunski
    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 a7c10d03 Leszek Koltunski
251 b1f0d55d Leszek Koltunski
    createVertices(list,mWall,AXIS_XM,x);
252 a7c10d03 Leszek Koltunski
    }
253
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255
256 b1f0d55d Leszek Koltunski
  private void createTop(int y, ArrayList<float[]> list)
257 a7c10d03 Leszek Koltunski
    {
258 b1f0d55d Leszek Koltunski
    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 a7c10d03 Leszek Koltunski
265 b1f0d55d Leszek Koltunski
    createVertices(list,mWall,AXIS_YP,y);
266 a7c10d03 Leszek Koltunski
    }
267
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269
270 b1f0d55d Leszek Koltunski
  private void createBottom(int y, ArrayList<float[]> list)
271 a7c10d03 Leszek Koltunski
    {
272 b1f0d55d Leszek Koltunski
    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 a7c10d03 Leszek Koltunski
279 b1f0d55d Leszek Koltunski
    createVertices(list,mWall,AXIS_YM,y);
280 a7c10d03 Leszek Koltunski
    }
281
282
///////////////////////////////////////////////////////////////////////////////////////////////////
283
284 b1f0d55d Leszek Koltunski
  private void createFront(int z, ArrayList<float[]> list)
285 a7c10d03 Leszek Koltunski
    {
286 b1f0d55d Leszek Koltunski
    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 a7c10d03 Leszek Koltunski
293 b1f0d55d Leszek Koltunski
    createVertices(list,mWall,AXIS_ZP,z);
294 a7c10d03 Leszek Koltunski
    }
295
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297
298 b1f0d55d Leszek Koltunski
  private void createBack(int z, ArrayList<float[]> list)
299 a7c10d03 Leszek Koltunski
    {
300 b1f0d55d Leszek Koltunski
    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 a7c10d03 Leszek Koltunski
307 b1f0d55d Leszek Koltunski
    createVertices(list,mWall,AXIS_ZM,z);
308 a7c10d03 Leszek Koltunski
    }
309
310
///////////////////////////////////////////////////////////////////////////////////////////////////
311
312 b1f0d55d Leszek Koltunski
  private void markNeighbours(int[][] wall, int x, int y, int section)
313 a7c10d03 Leszek Koltunski
    {
314 b1f0d55d Leszek Koltunski
    wall[x][y] = section;
315 a7c10d03 Leszek Koltunski
316 b1f0d55d Leszek Koltunski
    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 a7c10d03 Leszek Koltunski
    }
321
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323
324 b1f0d55d Leszek Koltunski
  private int markSections(int[][] wall)
325 a7c10d03 Leszek Koltunski
    {
326
    int sections = 0;
327
328 b1f0d55d Leszek Koltunski
    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 a7c10d03 Leszek Koltunski
336
    return sections;
337
    }
338
339
///////////////////////////////////////////////////////////////////////////////////////////////////
340 b8b71f52 Leszek Koltunski
// return true iff exactly three or exactly one of the four values (x1,x2,x3,x4) are equal to 'value'.
341 a7c10d03 Leszek Koltunski
342 b8b71f52 Leszek Koltunski
  private boolean threeOrOne(int x1, int x2, int x3, int x4, int value)
343 a7c10d03 Leszek Koltunski
    {
344 b8b71f52 Leszek Koltunski
    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 a7c10d03 Leszek Koltunski
    }
382
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384
385 b8b71f52 Leszek Koltunski
  private int moveDown(int x, int y)
386 a7c10d03 Leszek Koltunski
    {
387 b1f0d55d Leszek Koltunski
    for(int i=y+1; i<=mMax; i++)
388 b8b71f52 Leszek Koltunski
      if( mPoints[x][i]==0 ) return i;
389 a7c10d03 Leszek Koltunski
390 b8b71f52 Leszek Koltunski
    android.util.Log.e("D", "moveDown error!");
391
    return 0;
392 a7c10d03 Leszek Koltunski
    }
393
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395
396 b8b71f52 Leszek Koltunski
  private int moveLeft(int x, int y)
397 a7c10d03 Leszek Koltunski
    {
398 b8b71f52 Leszek Koltunski
    for(int i=x-1; i>=0; i--)
399
      if( mPoints[i][y]==0 ) return i;
400 a7c10d03 Leszek Koltunski
401 b8b71f52 Leszek Koltunski
    android.util.Log.e("D", "moveLeft error!");
402
    return 0;
403
    }
404
405
///////////////////////////////////////////////////////////////////////////////////////////////////
406
407
  private int moveRight(int x, int y)
408
    {
409 b1f0d55d Leszek Koltunski
    for(int i=x+1; i<=mMax; i++)
410 b8b71f52 Leszek Koltunski
      if( mPoints[i][y]==0 ) return i;
411
412
    android.util.Log.e("D", "moveRight error!");
413
    return 0;
414
    }
415
416
///////////////////////////////////////////////////////////////////////////////////////////////////
417
418 630cf5ce Leszek Koltunski
  private float[] buildVertices(int[][] wall, int section, float dx, float dy)
419 b8b71f52 Leszek Koltunski
    {
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 b1f0d55d Leszek Koltunski
    for(int i=0; i<=mMax; i++)
426
      for(int j=0; j<=mMax; j++)
427 b8b71f52 Leszek Koltunski
        if( mPoints[i][j]==0 )
428
          {
429
          x = i;
430
          y = j;
431 b1f0d55d Leszek Koltunski
          i = j = mMax+1;
432 b8b71f52 Leszek Koltunski
          }
433
434
    for(int s=0; s<numSections; s++)
435
      {
436 630cf5ce Leszek Koltunski
      vertices[6*pointer  ] = x-dx;
437
      vertices[6*pointer+1] = dy-y;
438 b8b71f52 Leszek Koltunski
      vertices[6*pointer+2] = 0.0f;
439
440
      y = isOddVertical(x,y) ? moveDown(x,y) : moveUp(x,y);
441
442 630cf5ce Leszek Koltunski
      vertices[6*pointer+3] = x-dx;
443
      vertices[6*pointer+4] = dy-y;
444 b8b71f52 Leszek Koltunski
      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 b1f0d55d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 b8b71f52 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 630cf5ce Leszek Koltunski
                      vertices[3*i+2] =-vertices[3*i  ];
514 b1f0d55d Leszek Koltunski
                      vertices[3*i  ] = layer-(dX-1.0f);
515 b8b71f52 Leszek Koltunski
                      }
516
                    break;
517
      case AXIS_XM: for(i=0; i<len; i++)
518
                      {
519 630cf5ce Leszek Koltunski
                      vertices[3*i+2] = vertices[3*i  ];
520 b1f0d55d Leszek Koltunski
                      vertices[3*i  ] = layer-dX;
521 b8b71f52 Leszek Koltunski
                      }
522
                    break;
523
      case AXIS_YP: for(i=0; i<len; i++)
524
                      {
525 630cf5ce Leszek Koltunski
                      vertices[3*i+2] =-vertices[3*i+1];
526 b1f0d55d Leszek Koltunski
                      vertices[3*i+1] = layer-(dY-1.0f);
527 b8b71f52 Leszek Koltunski
                      }
528
                    break;
529
      case AXIS_YM: for(i=0; i<len; i++)
530
                      {
531
                      vertices[3*i+2] = vertices[3*i+1];
532 b1f0d55d Leszek Koltunski
                      vertices[3*i+1] = layer-dY;
533 b8b71f52 Leszek Koltunski
                      }
534
                    break;
535
      case AXIS_ZP: for(i=0; i<len; i++)
536
                      {
537 b1f0d55d Leszek Koltunski
                      vertices[3*i+2] = layer-(dZ-1.0f);
538 b8b71f52 Leszek Koltunski
                      }
539
                    break;
540
      case AXIS_ZM: for(i=0; i<len; i++)
541
                      {
542 b1f0d55d Leszek Koltunski
                      vertices[3*i+2] = layer-dZ;
543 630cf5ce Leszek Koltunski
                      vertices[3*i  ] =-vertices[3*i  ];
544 b8b71f52 Leszek Koltunski
                      }
545
                    break;
546
      }
547 a7c10d03 Leszek Koltunski
    }
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 b1f0d55d Leszek Koltunski
  private void createVertices(ArrayList<float[]> list, int[][] wall, int axis, int layer)
558 a7c10d03 Leszek Koltunski
    {
559
    int sections = markSections(wall);
560
561 630cf5ce Leszek Koltunski
    float dx = (axis==AXIS_XP || axis==AXIS_XM) ? dZ : dX;
562
    float dy = (axis==AXIS_YP || axis==AXIS_YM) ? dZ : dY;
563
564 a7c10d03 Leszek Koltunski
    for(int i=0; i<sections; i++)
565
      {
566 630cf5ce Leszek Koltunski
      float[] vertices = buildVertices(wall,i+1,dx,dy);
567
568 b8b71f52 Leszek Koltunski
      rotateAndMoveVertices(vertices,axis,layer);
569 a7c10d03 Leszek Koltunski
      list.add(vertices);
570 b8b71f52 Leszek Koltunski
/*
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 630cf5ce Leszek Koltunski
      android.util.Log.e("D", "1 section: "+i+" axis: "+axis+" layer: "+layer+" vertices after: "+w);
579
*/
580 a7c10d03 Leszek Koltunski
      }
581
    }
582
583
///////////////////////////////////////////////////////////////////////////////////////////////////
584 786098dd Leszek Koltunski
585 e3302253 Leszek Koltunski
  private static boolean vertInFace(float[] vertex, float[] move, Static3D faceAxis, float dist)
586 786098dd Leszek Koltunski
    {
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 e3302253 Leszek Koltunski
    float a = (vertex[0]+move[0])*x + (vertex[1]+move[1])*y + (vertex[2]+move[2])*z;
594 786098dd Leszek Koltunski
    float diff = a - dist;
595
596
    return diff>-MAX_ERROR && diff<MAX_ERROR;
597
    }
598
599
///////////////////////////////////////////////////////////////////////////////////////////////////
600 b1f0d55d Leszek Koltunski
// (vertices,indices) define a cubit face, i.e. a connected subset of the NxN grid.
601 786098dd Leszek Koltunski
// Return its 'diameter', i.e. max(width,height)
602
603
  private int faceDiameter(float[][] vertices, int[] indices)
604
    {
605 b1f0d55d Leszek Koltunski
    float maxX = -dX;
606 84a17011 Leszek Koltunski
    float minX =  dX;
607 b1f0d55d Leszek Koltunski
    float maxY = -dY;
608 84a17011 Leszek Koltunski
    float minY =  dY;
609 b1f0d55d Leszek Koltunski
    float maxZ = -dZ;
610 84a17011 Leszek Koltunski
    float minZ =  dZ;
611 786098dd Leszek Koltunski
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 b1f0d55d Leszek Koltunski
// 0 if this is an inner face, 1 if its diameter is 1, 2 if diameter is 2, 3 if 3, etc
636 87d3d50a Leszek Koltunski
// but only up to 5 (because the number of bands is 6 - see createIrregularFaceShape() )
637 a7c10d03 Leszek Koltunski
638 29ad5fc9 Leszek Koltunski
  private int[] generateBandIndices(float[][] vertices, int[][] indices, float[] move)
639 a7c10d03 Leszek Koltunski
    {
640 786098dd Leszek Koltunski
    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 e3302253 Leszek Koltunski
        int vertBelongsBitmap = 0x00000000;
651 b1f0d55d Leszek Koltunski
        float[] vert = vertices[ indices[cubitFace][vertex] ];
652 e3302253 Leszek Koltunski
653 84a17011 Leszek Koltunski
        if( vertInFace(vert, move, TouchControlHexahedron.FACE_AXIS[0], dX) ) vertBelongsBitmap |= (1   );
654 b1f0d55d Leszek Koltunski
        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 786098dd Leszek Koltunski
660
        bandIndices[cubitFace] &= vertBelongsBitmap;
661
        }
662
663
      if( bandIndices[cubitFace]!=0 ) // outer face
664
        {
665 87d3d50a Leszek Koltunski
        int diameter = faceDiameter(vertices, indices[cubitFace]);
666
        bandIndices[cubitFace] = (diameter>=6 ? 5:diameter);
667 786098dd Leszek Koltunski
        }
668 e3302253 Leszek Koltunski
669
      //android.util.Log.e("D", "cubit face "+cubitFace+" : "+bandIndices[cubitFace]);
670 786098dd Leszek Koltunski
      }
671 b8b71f52 Leszek Koltunski
672
    return bandIndices;
673 a7c10d03 Leszek Koltunski
    }
674
675 b8b71f52 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
676 a7c10d03 Leszek Koltunski
677 5987822f Leszek Koltunski
  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 a7c10d03 Leszek Koltunski
    {
744 b8b71f52 Leszek Koltunski
    int len = vertices.length;
745 5987822f Leszek Koltunski
    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 84a17011 Leszek Koltunski
  private void debug(float[][] vert, int[][] ind)
758 5987822f Leszek Koltunski
    {
759 84a17011 Leszek Koltunski
    String vv="VERTICES: ";
760
    for (float[] floats : vert)
761 5987822f Leszek Koltunski
      {
762 84a17011 Leszek Koltunski
      vv += "\n";
763
      int lenV2 = floats.length / 3;
764 5987822f Leszek Koltunski
765 84a17011 Leszek Koltunski
      for (int v2 = 0; v2 < lenV2; v2++)
766 5987822f Leszek Koltunski
        {
767 84a17011 Leszek Koltunski
        vv += " {";
768
        vv += (floats[3 * v2] + " ");
769
        vv += (floats[3 * v2 + 1] + " ");
770
        vv += (floats[3 * v2 + 2] + " ");
771
        vv += "}";
772 5987822f Leszek Koltunski
        }
773
      }
774 84a17011 Leszek Koltunski
    android.util.Log.e("D", vv);
775 5987822f Leszek Koltunski
776 84a17011 Leszek Koltunski
    String ii="INDICES: ";
777
    for (int[] ints : ind)
778 5987822f Leszek Koltunski
      {
779 84a17011 Leszek Koltunski
      ii += "\n";
780
      int lenI2 = ints.length;
781
782
      for (int i2 = 0; i2 < lenI2; i2++)
783 5987822f Leszek Koltunski
        {
784 84a17011 Leszek Koltunski
        ii += (ints[i2] + " ");
785 5987822f Leszek Koltunski
        }
786
      }
787 84a17011 Leszek Koltunski
    android.util.Log.e("D", ii);
788 a7c10d03 Leszek Koltunski
    }
789
790
///////////////////////////////////////////////////////////////////////////////////////////////////
791
// PUBLIC API
792
793 c18507d9 Leszek Koltunski
  public static FactoryBandagedPyraminx getInstance()
794 a7c10d03 Leszek Koltunski
    {
795 c18507d9 Leszek Koltunski
    if( mThis==null ) mThis = new FactoryBandagedPyraminx();
796 a7c10d03 Leszek Koltunski
    return mThis;
797
    }
798
799
///////////////////////////////////////////////////////////////////////////////////////////////////
800
801 c18507d9 Leszek Koltunski
  public void prepare(int numVariants, int x)
802 a7c10d03 Leszek Koltunski
    {
803
    if( mVertexArray==null ) mVertexArray = new ArrayList<>();
804
    mVertices= new float[numVariants][][];
805
    mIndices = new int[numVariants][][];
806 29ad5fc9 Leszek Koltunski
    mMove = new float[numVariants][3];
807 84a17011 Leszek Koltunski
    mBandIndices = new int[numVariants][];
808 b1f0d55d Leszek Koltunski
809 52e3d46b Leszek Koltunski
    mX = x;
810 c18507d9 Leszek Koltunski
811 b1f0d55d Leszek Koltunski
812
    dX = mX/2.0f;
813
    dY = mY/2.0f;
814
    dZ = mZ/2.0f;
815
816
    mMax = mX>mY ? Math.max(mX,mZ) : Math.max(mY,mZ);
817
818
    mWall   = new int[mMax][mMax];
819
    mPoints = new int[mMax+1][mMax+1];
820
    mTmp    = new boolean[mX][mY][mZ];
821 a7c10d03 Leszek Koltunski
    }
822
823
///////////////////////////////////////////////////////////////////////////////////////////////////
824
825
  public ObjectShape createIrregularShape(int variant, float[] pos)
826
    {
827 786098dd Leszek Koltunski
    mVertexArray.clear();
828
829 96a68289 Leszek Koltunski
    float begX = 0.5f*(1-mX);
830
    float begY = 0.5f*(1-mY);
831
    float begZ = 0.5f*(1-mZ);
832
833 b1f0d55d Leszek Koltunski
    for(int x=0; x<mX; x++)
834
      for(int y=0; y<mY; y++)
835 96a68289 Leszek Koltunski
        for(int z=0; z<mZ; z++) mTmp[x][y][z] = cubitExists(pos,begX+x,begY+y,begZ+z);
836 a7c10d03 Leszek Koltunski
837 b1f0d55d Leszek Koltunski
    for(int x=0; x<mX; x++) createRight (x,mVertexArray);
838
    for(int x=0; x<mX; x++) createLeft  (x,mVertexArray);
839
    for(int y=0; y<mY; y++) createTop   (y,mVertexArray);
840
    for(int y=0; y<mY; y++) createBottom(y,mVertexArray);
841
    for(int z=0; z<mZ; z++) createFront (z,mVertexArray);
842
    for(int z=0; z<mZ; z++) createBack  (z,mVertexArray);
843 a7c10d03 Leszek Koltunski
844 b442e28c Leszek Koltunski
    float[][] verts = getVertices(mVertexArray,pos,variant);
845
    int[][] inds    = getIndices(mVertexArray);
846 b8b71f52 Leszek Koltunski
847 b442e28c Leszek Koltunski
    compressVerticesAndIndices(variant,verts,inds);
848 84a17011 Leszek Koltunski
    mBandIndices[variant] = generateBandIndices(mVertices[variant], mIndices[variant], mMove[variant]);
849 b8b71f52 Leszek Koltunski
850 b442e28c Leszek Koltunski
    return new ObjectShape(mVertices[variant], mIndices[variant]);
851 b8b71f52 Leszek Koltunski
    }
852
853 b442e28c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
854 a7c10d03 Leszek Koltunski
855 84a17011 Leszek Koltunski
  public ObjectVertexEffects createVertexEffects(int variant, boolean roundCorners)
856 b8b71f52 Leszek Koltunski
    {
857 4cb302d5 Leszek Koltunski
    float[][] vertVec= generateVectors(mVertices[variant], mIndices[variant], mBandIndices[variant]);
858
    int numEffects   = mVertices[variant].length;
859
    float S          = 0.04f;
860
    float[] region   = {0,0,0,0.15f};
861
    String[] names   = new String[numEffects];
862
    float[][] regions= new float[numEffects][];
863
    boolean[] uses   = new boolean[numEffects];
864
    float[][] vars   = new float[numEffects][];
865 b442e28c Leszek Koltunski
866 84a17011 Leszek Koltunski
    for(int i=0; i<numEffects; i++)
867 b442e28c Leszek Koltunski
      {
868 80fd07aa Leszek Koltunski
      float[] v = vertVec[i];
869
870
      if( v!=null )
871
        {
872 4cb302d5 Leszek Koltunski
        names[i]  = FactoryCubit.NAME;
873
        regions[i]= region;
874
        uses[i]   = roundCorners;
875
        vars[i]   = new float[] { 0, S*v[0], S*v[1], S*v[2], 1 };
876 80fd07aa Leszek Koltunski
        }
877 b442e28c Leszek Koltunski
      }
878 84a17011 Leszek Koltunski
879 4cb302d5 Leszek Koltunski
    return new ObjectVertexEffects(names,vars,mVertices[variant],regions,uses);
880 a7c10d03 Leszek Koltunski
    }
881
882
///////////////////////////////////////////////////////////////////////////////////////////////////
883
884 84a17011 Leszek Koltunski
  public ObjectFaceShape createIrregularFaceShape(int variant, boolean iconMode)
885 a7c10d03 Leszek Koltunski
    {
886 84a17011 Leszek Koltunski
    float height= iconMode ? 0.001f : 0.048f;
887
    int angle   = 60;
888
    float R     = 0.2f;
889
    float S     = 0.5f;
890
    int numVerts= 5;
891
    int extraI  = 0;
892
    int extraV  = 0;
893 a7c10d03 Leszek Koltunski
894 84a17011 Leszek Koltunski
    float[][] bands  = { {  0.001f,angle,R,S,numVerts,extraV,extraI},
895
                         {height/1,angle,R,S,numVerts,extraV,extraI},
896
                         {height/2,angle,R,S,numVerts,extraV,extraI},
897
                         {height/3,angle,R,S,numVerts,extraV,extraI},
898
                         {height/4,angle,R,S,numVerts,extraV,extraI},
899
                         {height/5,angle,R,S,numVerts,extraV,extraI} };
900 a7c10d03 Leszek Koltunski
901 84a17011 Leszek Koltunski
    return new ObjectFaceShape(bands,mBandIndices[variant],null);
902 a7c10d03 Leszek Koltunski
    }
903 12aa6192 Leszek Koltunski
904
///////////////////////////////////////////////////////////////////////////////////////////////////
905
906 c18507d9 Leszek Koltunski
  public MeshBase createMesh(float[] pos, int x, boolean iconMode, boolean roundCorners)
907 12aa6192 Leszek Koltunski
    {
908 c18507d9 Leszek Koltunski
    prepare(1,x);
909 84a17011 Leszek Koltunski
    ObjectShape shape           = createIrregularShape(0,pos);
910
    ObjectFaceShape face        = createIrregularFaceShape(0,iconMode);
911
    ObjectVertexEffects effects = createVertexEffects(0,roundCorners);
912
    int[][] indices             = shape.getVertIndices();
913
    int numComponents           = indices.length;
914 12aa6192 Leszek Koltunski
915
    FactoryCubit factory = FactoryCubit.getInstance();
916 1c55e462 Leszek Koltunski
    factory.clear();
917 12aa6192 Leszek Koltunski
    factory.createNewFaceTransform(shape,null);
918 84a17011 Leszek Koltunski
    return factory.createRoundedSolid(shape,face,effects,MESH_NICE,numComponents);
919 12aa6192 Leszek Koltunski
    }
920 a7c10d03 Leszek Koltunski
  }