Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyBandagedAbstract.java @ d8e03a81

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 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.objects;
21

    
22
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_CUBOID;
23
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
24

    
25
import java.io.InputStream;
26

    
27
import org.distorted.library.main.DistortedLibrary;
28
import org.distorted.library.type.Static3D;
29
import org.distorted.library.type.Static4D;
30

    
31
import org.distorted.objectlib.helpers.FactoryBandagedCubit;
32
import org.distorted.objectlib.helpers.ObjectFaceShape;
33
import org.distorted.objectlib.scrambling.ScrambleStateBandagedCuboid;
34
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
35
import org.distorted.objectlib.helpers.ObjectShape;
36
import org.distorted.objectlib.scrambling.ScrambleState;
37
import org.distorted.objectlib.main.ShapeHexahedron;
38

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

    
41
abstract class TwistyBandagedAbstract extends ShapeHexahedron
42
{
43
  private static final int CUBIT_111 = 0;
44
  private static final int CUBIT_211 = 1;
45
  private static final int CUBIT_311 = 2;
46
  private static final int CUBIT_221 = 3;
47
  private static final int CUBIT_222 = 4;
48
  private static final int CUBIT_OTH = 5;
49

    
50
  // the three rotation axis of a 3x3 Cube. Must be normalized.
51
  static final Static3D[] ROT_AXIS = new Static3D[]
52
         {
53
           new Static3D(1,0,0),
54
           new Static3D(0,1,0),
55
           new Static3D(0,0,1)
56
         };
57

    
58
  private static final int[][] mDims = new int[][]
59
        {
60
         {1,1,1},  // has to be X>=Z>=Y so that all
61
         {2,1,1},  // the faces are horizontal
62
         {3,1,1},
63
         {2,1,2},
64
         {2,2,2},
65
        };
66

    
67
  private int[][] mBasicAngle;
68
  private Static4D[] mInitQuats;
69
  private float[][] mCuts;
70
  private ScrambleState[] mStates;
71
  private int[] mCubitVariantMap;
72
  private int[] mTypeVariantMap;
73
  private int[][] mSolvedQuatsAbstract;
74

    
75
  float[][] POSITIONS;
76

    
77
///////////////////////////////////////////////////////////////////////////////////////////////////
78

    
79
  TwistyBandagedAbstract(int[] numL, int meshState, int iconMode, Static4D quat, Static3D move, float scale, InputStream stream)
80
    {
81
    super(numL, meshState, iconMode, (numL[0]+numL[1]+numL[2])/3.0f, quat, move, scale, stream);
82
    }
83

    
84
///////////////////////////////////////////////////////////////////////////////////////////////////
85

    
86
  abstract float[][] getPositions();
87

    
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89
// return 0 if cubit is 'external' (it has at least two walls which belong to two different faces
90
// of the cuboid, faces which do not both rotate along the same axis! So: it is an edge, a corner,
91
// or a bandaged cubit which 'comes out' in two different, non-opposite, faces.
92
// Otherwise, if the cubit only comes out in one face or in two faces which are opposite to each other,
93
// return the index of the first of the three quats which rotate stuff in this face (so right or left
94
// return 1 because quats 1,2,3 are the ones rotating along the X axis)
95

    
96
  private int cubitIsExternal(float[] pos, float dx, float dy, float dz)
97
    {
98
    int len = pos.length/3;
99
    int x=0, y=0, z=0;
100

    
101
    for(int i=0; i<len; i++)
102
      {
103
      float cx = pos[3*i  ];
104
      float cy = pos[3*i+1];
105
      float cz = pos[3*i+2];
106

    
107
      if( cx>dx || cx<-dx ) x=1;
108
      if( cy>dy || cy<-dy ) y=1;
109
      if( cz>dz || cz<-dz ) z=1;
110
      }
111

    
112
    if( x+y+z>=2 ) return 0;
113

    
114
    if( x==1 ) return 1;
115
    if( y==1 ) return 4;
116
    if( z==1 ) return 7;
117

    
118
    android.util.Log.e("D", "ERROR: unsupported: internal cubit! ");
119
    return 0;
120
    }
121

    
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123
// If we have a flat cuboid than retCubitSolvedStatus() wrongly reports that the internal cubits
124
// are edges (they do have two non-black faces after all!) which leads to wrong solvedQuats and
125
// mis-detection of a solved status. Correct this manually here.
126
//
127
// Note that this is still not completely good in case of bandaged cuboids - there can be a 4x4x2
128
// bandaged cuboid whose 4 'internal' cubits from the 4x4 face are fused with the other 4 internal
129
// cubits from the other 4x4 face - and those would again get mis-detected as edges...
130

    
131
  @Override
132
  public int[][] getSolvedQuats()
133
    {
134
    if( mSolvedQuatsAbstract==null )
135
      {
136
      int[] numLayers = getNumLayers();
137
      float dx = 0.5f*(numLayers[0]-1) - 0.1f;
138
      float dy = 0.5f*(numLayers[1]-1) - 0.1f;
139
      float dz = 0.5f*(numLayers[2]-1) - 0.1f;
140

    
141
      float[][] pos = getPositions();
142
      int numTotal = pos.length;
143
      boolean[] isExternal = new boolean[numTotal];
144
      int[] internalQuat = new int[numTotal];
145
      int numExternal = 0;
146
      int pointer = 0;
147

    
148
      for(int cubit=0; cubit<numTotal; cubit++)
149
        {
150
        int q = cubitIsExternal(pos[cubit],dx,dy,dz);
151

    
152
        if( q<=0 )
153
          {
154
          isExternal[cubit] = true;
155
          numExternal++;
156
          }
157
        else
158
          {
159
          isExternal[cubit] = false;
160
          internalQuat[pointer] = q;
161
          pointer++;
162
          }
163
        }
164

    
165
      int numInternal = numTotal - numExternal;
166

    
167
      mSolvedQuatsAbstract = new int[numInternal+1][];
168
      mSolvedQuatsAbstract[0] = new int[numExternal+1];
169
      mSolvedQuatsAbstract[0][0] = numExternal;
170

    
171
      for(int i=0; i<numInternal; i++)
172
        {
173
        int q = internalQuat[i];
174
        mSolvedQuatsAbstract[i+1] = new int[5];
175
        mSolvedQuatsAbstract[i+1][0] = 1;
176
        mSolvedQuatsAbstract[i+1][2] = q;
177
        mSolvedQuatsAbstract[i+1][3] = q+1;
178
        mSolvedQuatsAbstract[i+1][4] = q+2;
179
        }
180

    
181
      int pointerExternal = 1;
182
      int pointerInternal = 1;
183

    
184
      for(int cubit=0; cubit<numTotal; cubit++)
185
        {
186
        if( isExternal[cubit] ) mSolvedQuatsAbstract[0][pointerExternal++] = cubit;
187
        else                    mSolvedQuatsAbstract[pointerInternal++][1] = cubit;
188
        }
189
      }
190

    
191
    return mSolvedQuatsAbstract;
192
    }
193

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

    
196
  public ScrambleState[] getScrambleStates()
197
    {
198
    if( mStates==null && !isInIconMode() )
199
      {
200
      long signature = getSignature();
201
      mStates = ScrambleStateBandagedCuboid.computeGraph(signature);
202
      }
203

    
204
    return mStates;
205
    }
206

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

    
209
  private int getType(float[] pos)
210
    {
211
    switch(pos.length)
212
      {
213
      case  3: return CUBIT_111;
214
      case  6: return CUBIT_211;
215
      case  9: boolean x1 = (pos[0]==pos[3] && pos[0]==pos[6]);
216
               boolean y1 = (pos[1]==pos[4] && pos[1]==pos[7]);
217
               boolean z1 = (pos[2]==pos[5] && pos[2]==pos[8]);
218
               return ( (x1&&y1) || (x1&&z1) || (y1&&z1) ) ? CUBIT_311 : CUBIT_OTH;
219
      case 12: float x = (pos[0]+pos[3]+pos[6]+pos[ 9])/4;
220
               float y = (pos[1]+pos[4]+pos[7]+pos[10])/4;
221
               float z = (pos[2]+pos[5]+pos[8]+pos[11])/4;
222
               float d1 = (pos[0]-x)*(pos[0]-x) + (pos[ 1]-y)*(pos[ 1]-y) + (pos[ 2]-z)*(pos[ 2]-z);
223
               float d2 = (pos[3]-x)*(pos[3]-x) + (pos[ 4]-y)*(pos[ 4]-y) + (pos[ 5]-z)*(pos[ 5]-z);
224
               float d3 = (pos[6]-x)*(pos[6]-x) + (pos[ 7]-y)*(pos[ 7]-y) + (pos[ 8]-z)*(pos[ 8]-z);
225
               float d4 = (pos[9]-x)*(pos[9]-x) + (pos[10]-y)*(pos[10]-y) + (pos[11]-z)*(pos[11]-z);
226
               return ( d1==0.5f && d2==0.5f && d3==0.5f && d4==0.5f ) ? CUBIT_221 : CUBIT_OTH;
227
      case 24: float x3 = pos[0];
228
               float y3 = pos[1];
229
               float z3 = pos[2];
230
               float x4=-10,y4=-10,z4=-10;
231
               int i;
232

    
233
               for(i=0; i<8; i++)
234
                 {
235
                 if( pos[3*i]!=x3 && pos[3*i+1]!=y3 && pos[3*i+2]!=z3 )
236
                   {
237
                   x4 = pos[3*i  ];
238
                   y4 = pos[3*i+1];
239
                   z4 = pos[3*i+2];
240
                   break;
241
                   }
242
                 }
243
               if( i==9 ) return CUBIT_OTH;
244

    
245
               float dX = x4-x3;
246
               float dY = y4-y3;
247
               float dZ = z4-z3;
248

    
249
               if( (dX==1.0f || dX==-1.0f) && (dY==1.0f || dY==-1.0f) && (dZ==1.0f || dZ==-1.0f) )
250
                 {
251
                 for(i=0; i<8; i++)
252
                   {
253
                   if( (pos[3*i  ]!=x3 && pos[3*i  ]!=x4) ||
254
                       (pos[3*i+1]!=y3 && pos[3*i+1]!=y4) ||
255
                       (pos[3*i+2]!=z3 && pos[3*i+2]!=z4)  ) return CUBIT_OTH;
256
                   }
257

    
258
                 return CUBIT_222;
259
                 }
260

    
261
      default: return CUBIT_OTH;
262
      }
263
    }
264

    
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266

    
267
  private int getQuatIndex(int cubit)
268
    {
269
    float[][] positions = getPositions();
270
    int len = positions.length;
271

    
272
    if( cubit>=0 && cubit<len )
273
      {
274
      float[] pos = positions[cubit];
275
      int type = getType(pos);
276

    
277
      switch(type)
278
        {
279
        case CUBIT_222:
280
        case CUBIT_111: return 0;
281
        case CUBIT_211:
282
        case CUBIT_311: return (pos[1]==pos[4]) ? (pos[0]==pos[3] ? 2 : 0) : 3;
283
        case CUBIT_221: if( pos[0]==pos[3] && pos[0]==pos[6] ) return 3;
284
                        if( pos[1]==pos[4] && pos[1]==pos[7] ) return 0;
285
                        if( pos[2]==pos[5] && pos[2]==pos[8] ) return 1;
286
        }
287
      }
288

    
289
    return 0;
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

    
294
  private int getSigIndex(float x, float y, float z)
295
    {
296
    if( x==-1.0f )
297
      {
298
           if( y==-1.0f ) return z==0.5f ? 4:9;
299
      else if( y==-0.5f ) return z==1.0f ? 14 : (z==0.0f ? 17:20);
300
      else if( y== 0.0f ) return z==0.5f ? 25:30;
301
      else if( y== 0.5f ) return z==1.0f ? 35 : (z==0.0f ? 38:41);
302
      else if( y== 1.0f ) return z==0.5f ? 46:51;
303
      }
304
    else if( x==-0.5f )
305
      {
306
           if( y==-1.0f ) return z==1.0f ? 1  : (z==0.0f ?  6:11);
307
      else if( y== 0.0f ) return z==1.0f ? 22 : (z==0.0f ? 27:32);
308
      else if( y== 1.0f ) return z==1.0f ? 43 : (z==0.0f ? 48:53);
309
      }
310
    else if( x==0.0f )
311
      {
312
           if( y==-1.0f ) return z==0.5f ? 3:8;
313
      else if( y==-0.5f ) return z==1.0f ? 13 : (z==0.0f ? 16:19);
314
      else if( y== 0.0f ) return z==0.5f ? 24:29;
315
      else if( y== 0.5f ) return z==1.0f ? 34 : (z==0.0f ? 37:40);
316
      else if( y== 1.0f ) return z==0.5f ? 45:50;
317
      }
318
    else if( x==0.5f )
319
      {
320
           if( y==-1.0f ) return z==1.0f ? 0  : (z==0.0f ?  5:10);
321
      else if( y== 0.0f ) return z==1.0f ? 21 : (z==0.0f ? 26:31);
322
      else if( y== 1.0f ) return z==1.0f ? 42 : (z==0.0f ? 47:52);
323
      }
324
    else if( x==1.0f )
325
      {
326
           if( y==-1.0f ) return z==0.5f ? 2:7;
327
      else if( y==-0.5f ) return z==1.0f ? 12 : (z==0.0f ? 15:18);
328
      else if( y== 0.0f ) return z==0.5f ? 23:28;
329
      else if( y== 0.5f ) return z==1.0f ? 33 : (z==0.0f ? 36:39);
330
      else if( y== 1.0f ) return z==0.5f ? 44:49;
331
      }
332
    else
333
      {
334
      android.util.Log.e("D", "ERROR! mx="+x);
335
      }
336

    
337
    return -1;
338
    }
339

    
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341

    
342
  private long markConnection(float x1, float y1, float z1, float x2, float y2, float z2)
343
    {
344
    float dx = x1-x2;
345
    float dy = y1-y2;
346
    float dz = z1-z2;
347

    
348
    if( (dx==0 && dy==0 && (dz==1 || dz==-1) ) ||
349
        (dz==0 && dx==0 && (dy==1 || dy==-1) ) ||
350
        (dy==0 && dz==0 && (dx==1 || dx==-1) )  )
351
      {
352
      float mx = (x1+x2)/2;
353
      float my = (y1+y2)/2;
354
      float mz = (z1+z2)/2;
355

    
356
      int index = getSigIndex(mx,my,mz);
357

    
358
      return (1L<<index);
359
      }
360

    
361
    return 0;
362
    }
363

    
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365

    
366
  long markConnections(long signature, float[] position)
367
    {
368
    int len = position.length/3;
369

    
370
    for(int i=0; i<len; i++)
371
      {
372
      float x = position[3*i  ];
373
      float y = position[3*i+1];
374
      float z = position[3*i+2];
375

    
376
      for(int j=i+1; j<len; j++)
377
        {
378
        signature |= markConnection(x,y,z,position[3*j],position[3*j+1],position[3*j+2]);
379
        }
380
      }
381

    
382
    return signature;
383
    }
384

    
385
///////////////////////////////////////////////////////////////////////////////////////////////////
386

    
387
  public long getSignature()
388
    {
389
    long signature = 0;
390
    float[][] positions = getPositions();
391
    for(float[] pos : positions ) signature = markConnections(signature,pos);
392
    return signature;
393
    }
394

    
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396

    
397
  public ObjectShape getObjectShape(int variant)
398
    {
399
    int type,numTypes = mDims.length;
400
    for(type=0; type<numTypes; type++) if( mTypeVariantMap[type]==variant ) break;
401

    
402
    if( type<numTypes )
403
      {
404
      int X = mDims[type][0];
405
      int Y = mDims[type][1];
406
      int Z = mDims[type][2];
407

    
408
      float[][] vertices =
409
        {
410
          {+0.5f*X,+0.5f*Y,+0.5f*Z},
411
          {+0.5f*X,+0.5f*Y,-0.5f*Z},
412
          {+0.5f*X,-0.5f*Y,+0.5f*Z},
413
          {+0.5f*X,-0.5f*Y,-0.5f*Z},
414
          {-0.5f*X,+0.5f*Y,+0.5f*Z},
415
          {-0.5f*X,+0.5f*Y,-0.5f*Z},
416
          {-0.5f*X,-0.5f*Y,+0.5f*Z},
417
          {-0.5f*X,-0.5f*Y,-0.5f*Z}
418
        };
419

    
420
      int[][] indices =
421
        {
422
          {2,3,1,0},
423
          {7,6,4,5},
424
          {4,0,1,5},
425
          {7,3,2,6},
426
          {6,2,0,4},
427
          {3,7,5,1},
428
        };
429

    
430
      return new ObjectShape(vertices, indices);
431
      }
432

    
433
    float[][] positions = getPositions();
434
    int cubit,numCubits = positions.length;
435

    
436
    for(cubit=0; cubit<numCubits; cubit++)
437
      {
438
      if( mCubitVariantMap[cubit]==variant ) break;
439
      }
440

    
441
    if( cubit>=numCubits )
442
      {
443
      android.util.Log.e("D", "unknown variant: "+variant);
444
      return null;
445
      }
446

    
447
    FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
448
    return factory.createIrregularShape(variant,positions[cubit]);
449
    }
450

    
451
///////////////////////////////////////////////////////////////////////////////////////////////////
452

    
453
  public ObjectFaceShape getObjectFaceShape(int variant)
454
    {
455
    boolean roundCorners = DistortedLibrary.fastCompilationTF();
456
    int type,numTypes = mDims.length;
457
    for(type=0; type<numTypes; type++) if( mTypeVariantMap[type]==variant ) break;
458

    
459
    if( type<numTypes )
460
      {
461
      int val = roundCorners ? 0 : -1;
462
      int X = mDims[type][0];
463
      int Y = mDims[type][1];
464
      int Z = mDims[type][2];
465

    
466
      float height        = isInIconMode() ? 0.001f : 0.048f;
467
      int[] bandIndices   = { 0,0,1,1,2,2 };
468
      float[][] corners   = { {0.04f,0.15f} };
469
      int[] cornerIndices = { val,val,val,val,val,val,val,val };
470
      int[] centerIndices = { 0,1,2,3,4,5,6,7 };
471

    
472
      int maxXY = Math.max(X,Y);
473
      int maxXZ = Math.max(X,Z);
474
      int maxYZ = Math.max(Y,Z);
475

    
476
      int angle = 45;
477
      float R = 0.25f;
478
      float S = 0.50f;
479

    
480
      float[][] bands =
481
        {
482
          {height/maxYZ,angle,R,S,5,0,0},
483
          {height/maxXZ,angle,R,S,5,0,0},
484
          {height/maxXY,angle,R,S,5,0,0}
485
        };
486

    
487
      float[][] centers =
488
        {
489
          {+0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
490
          {+0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
491
          {+0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
492
          {+0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)},
493
          {-0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
494
          {-0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
495
          {-0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
496
          {-0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)}
497
        };
498

    
499
      return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
500
      }
501

    
502
    FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
503
    return factory.createIrregularFaceShape(variant, isInIconMode(), roundCorners );
504
    }
505

    
506
///////////////////////////////////////////////////////////////////////////////////////////////////
507

    
508
  public float[][] getCubitPositions(int[] numLayers)
509
    {
510
    return getPositions();
511
    }
512

    
513
///////////////////////////////////////////////////////////////////////////////////////////////////
514

    
515
  public Static4D getCubitQuats(int cubit, int[] numLayers)
516
    {
517
    if( mInitQuats ==null )
518
      {
519
      mInitQuats = new Static4D[]
520
        {
521
        new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),  // NULL
522
        new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),  // X
523
        new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),  // Y
524
        new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),  // Z
525
        new Static4D( -0.5f,  +0.5f,  -0.5f,  +0.5f),  // ZX
526
        new Static4D( +0.5f,  +0.5f,  +0.5f,  -0.5f),  // YX
527
        };
528
      }
529

    
530
    return mInitQuats[getQuatIndex(cubit)];
531
    }
532

    
533
///////////////////////////////////////////////////////////////////////////////////////////////////
534

    
535
  public int getNumCubitVariants(int[] numLayers)
536
    {
537
    int numVariants = 0;
538
    float[][] positions = getPositions();
539
    boolean C111=false;
540
    boolean C211=false;
541
    boolean C311=false;
542
    boolean C221=false;
543
    boolean C222=false;
544

    
545
    int numCubits = positions.length;
546
    mCubitVariantMap = new int[numCubits];
547

    
548
    int numTypes = mDims.length;
549
    mTypeVariantMap = new int[numTypes];
550
    for(int i=0; i<numTypes; i++) mTypeVariantMap[i] = -1;
551

    
552
    for (int cubit=0; cubit<numCubits; cubit++)
553
      {
554
      int type = getType(positions[cubit]);
555

    
556
      switch (type)
557
        {
558
        case CUBIT_111: if (!C111) { C111 = true; mTypeVariantMap[CUBIT_111]=numVariants++; }
559
                        mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_111];
560
                        break;
561
        case CUBIT_211: if (!C211) { C211 = true; mTypeVariantMap[CUBIT_211]=numVariants++; }
562
                        mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_211];
563
                        break;
564
        case CUBIT_311: if (!C311) { C311 = true; mTypeVariantMap[CUBIT_311]=numVariants++; }
565
                        mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_311];
566
                        break;
567
        case CUBIT_221: if (!C221) { C221 = true; mTypeVariantMap[CUBIT_221]=numVariants++; }
568
                        mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_221];
569
                        break;
570
        case CUBIT_222: if (!C222) { C222 = true; mTypeVariantMap[CUBIT_222]=numVariants++; }
571
                        mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_222];
572
                        break;
573
        default       : mCubitVariantMap[cubit] = numVariants++;
574
        }
575
      }
576

    
577
    FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
578
    factory.prepare(numVariants,numLayers[0],numLayers[1],numLayers[2]);
579

    
580
    return numVariants;
581
    }
582

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

    
585
  public int getCubitVariant(int cubit, int[] numLayers)
586
    {
587
    return mCubitVariantMap[cubit];
588
    }
589

    
590
///////////////////////////////////////////////////////////////////////////////////////////////////
591

    
592
  public float[][] getCuts(int[] numLayers)
593
    {
594
    if( mCuts==null )
595
      {
596
      mCuts = new float[3][];
597

    
598
      for(int axis=0; axis<3; axis++)
599
        {
600
        int len = numLayers[axis];
601
        float start = (2-len)*0.5f;
602

    
603
        if( len>=2 )
604
          {
605
          mCuts[axis] = new float[len-1];
606
          for(int i=0; i<len-1; i++) mCuts[axis][i] = start+i;
607
          }
608
        }
609
      }
610

    
611
    return mCuts;
612
    }
613

    
614
///////////////////////////////////////////////////////////////////////////////////////////////////
615

    
616
  public boolean[][] getLayerRotatable(int[] numLayers)
617
    {
618
    int numAxis = ROT_AXIS.length;
619
    boolean[][] layerRotatable = new boolean[numAxis][];
620

    
621
    for(int i=0; i<numAxis; i++)
622
      {
623
      layerRotatable[i] = new boolean[numLayers[i]];
624
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
625
      }
626

    
627
    return layerRotatable;
628
    }
629

    
630
///////////////////////////////////////////////////////////////////////////////////////////////////
631

    
632
  public int getTouchControlType()
633
    {
634
    return TC_CUBOID;
635
    }
636

    
637
///////////////////////////////////////////////////////////////////////////////////////////////////
638

    
639
  public int getTouchControlSplit()
640
    {
641
    return TYPE_NOT_SPLIT;
642
    }
643

    
644
///////////////////////////////////////////////////////////////////////////////////////////////////
645

    
646
  public int[][][] getEnabled()
647
    {
648
    return new int[][][] { {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}} };
649
    }
650

    
651
///////////////////////////////////////////////////////////////////////////////////////////////////
652

    
653
  public float[] getDist3D(int[] numLayers)
654
    {
655
    float x = numLayers[0];
656
    float y = numLayers[1];
657
    float z = numLayers[2];
658
    float a = (x+y+z)/1.5f;
659

    
660
    return new float[] {x/a,x/a,y/a,y/a,z/a,z/a};
661
    }
662

    
663
///////////////////////////////////////////////////////////////////////////////////////////////////
664

    
665
  public Static3D[] getFaceAxis()
666
    {
667
    return TouchControlHexahedron.FACE_AXIS;
668
    }
669

    
670
///////////////////////////////////////////////////////////////////////////////////////////////////
671

    
672
  public float getStickerRadius()
673
    {
674
    return 0.10f;
675
    }
676

    
677
///////////////////////////////////////////////////////////////////////////////////////////////////
678

    
679
  public float getStickerStroke()
680
    {
681
    return isInIconMode() ? 0.16f : 0.08f;
682
    }
683

    
684
///////////////////////////////////////////////////////////////////////////////////////////////////
685

    
686
  public float[][] getStickerAngles()
687
    {
688
    return null;
689
    }
690

    
691
///////////////////////////////////////////////////////////////////////////////////////////////////
692
// PUBLIC API
693

    
694
  public Static3D[] getRotationAxis()
695
    {
696
    return ROT_AXIS;
697
    }
698

    
699
///////////////////////////////////////////////////////////////////////////////////////////////////
700

    
701
  public int[][] getBasicAngles()
702
    {
703
     if( mBasicAngle==null )
704
      {
705
      int[] num = getNumLayers();
706
      int numX = num[0];
707
      int numY = num[1];
708
      int numZ = num[2];
709

    
710
      int x = numY==numZ ? 4 : 2;
711
      int y = numX==numZ ? 4 : 2;
712
      int z = numX==numY ? 4 : 2;
713

    
714
      int[] tmpX = new int[numX];
715
      for(int i=0; i<numX; i++) tmpX[i] = x;
716
      int[] tmpY = new int[numY];
717
      for(int i=0; i<numY; i++) tmpY[i] = y;
718
      int[] tmpZ = new int[numZ];
719
      for(int i=0; i<numZ; i++) tmpZ[i] = z;
720

    
721
      mBasicAngle = new int[][] { tmpX,tmpY,tmpZ };
722
      }
723

    
724
    return mBasicAngle;
725
    }
726
}
(4-4/36)