Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyBandagedCuboid.java @ e50246a8

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

    
12
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_CUBOID;
13
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
14

    
15
import java.io.InputStream;
16

    
17
import org.distorted.library.effect.EffectName;
18
import org.distorted.library.main.DistortedLibrary;
19
import org.distorted.library.type.Static3D;
20
import org.distorted.library.type.Static4D;
21

    
22
import org.distorted.objectlib.helpers.FactoryBandagedCubit;
23
import org.distorted.objectlib.helpers.ObjectFaceShape;
24
import org.distorted.objectlib.helpers.ObjectSignature;
25
import org.distorted.objectlib.helpers.ObjectVertexEffects;
26
import org.distorted.objectlib.main.InitData;
27
import org.distorted.objectlib.main.ObjectType;
28
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
29
import org.distorted.objectlib.helpers.ObjectShape;
30
import org.distorted.objectlib.scrambling.ScrambleState;
31
import org.distorted.objectlib.shape.ShapeHexahedron;
32

    
33
///////////////////////////////////////////////////////////////////////////////////////////////////
34

    
35
public class TwistyBandagedCuboid extends ShapeHexahedron
36
{
37
  private static final String OBJECT_NAME = "LOCAL_BANDAGED";
38

    
39
  private static final int CUBIT_111 = 0;
40
  private static final int CUBIT_211 = 1;
41
  private static final int CUBIT_311 = 2;
42
  private static final int CUBIT_221 = 3;
43
  private static final int CUBIT_222 = 4;
44
  private static final int CUBIT_OTH = 5;
45

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

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

    
63
  public static final float[][] POS_1 = new float[][]
64
        {
65
          {-1.0f, -1.0f, +0.0f,
66
           -1.0f, -1.0f, +1.0f,
67
           -1.0f,  0.0f, +0.0f,
68
           -1.0f,  0.0f, +1.0f,
69
            0.0f, -1.0f, +0.0f,
70
            0.0f, -1.0f, +1.0f,
71
            0.0f,  0.0f, +0.0f,
72
            0.0f,  0.0f, +1.0f},
73
          {-1.0f, +1.0f, +1.0f},
74
          {-1.0f, +1.0f, +0.0f},
75
          {-1.0f, +1.0f, -1.0f},
76
          { 0.0f, +1.0f, +1.0f},
77
          { 0.0f, +1.0f, +0.0f},
78
          { 0.0f, +1.0f, -1.0f},
79
          { 1.0f, +1.0f, +1.0f},
80
          { 1.0f, +1.0f, +0.0f},
81
          { 1.0f, +1.0f, -1.0f},
82
          { 1.0f,  0.0f, +1.0f},
83
          { 1.0f,  0.0f, +0.0f},
84
          { 1.0f,  0.0f, -1.0f},
85
          { 1.0f, -1.0f, +1.0f},
86
          { 1.0f, -1.0f, +0.0f},
87
          { 1.0f, -1.0f, -1.0f},
88
          {-1.0f, -1.0f, -1.0f},
89
          {-1.0f,  0.0f, -1.0f},
90
          { 0.0f, -1.0f, -1.0f},
91
          { 0.0f,  0.0f, -1.0f}
92
        };
93

    
94
  public static final float[][] POS_2 = new float[][]
95
        {
96
          { 0.0f, +1.0f,  1.0f, 0.0f, +1.0f,  0.0f, 0.0f, +1.0f, -1.0f},
97
          {-1.0f, -1.0f,  0.0f, 0.0f, -1.0f,  0.0f, 1.0f, -1.0f,  0.0f},
98
          {-1.0f, +1.0f, +1.0f},
99
          {-1.0f, +1.0f,  0.0f},
100
          {-1.0f, +1.0f, -1.0f},
101
          {-1.0f,  0.0f, +1.0f},
102
          {-1.0f,  0.0f,  0.0f},
103
          {-1.0f,  0.0f, -1.0f},
104
          {-1.0f, -1.0f, +1.0f},
105
          {-1.0f, -1.0f, -1.0f},
106
          {+1.0f, +1.0f, +1.0f},
107
          {+1.0f, +1.0f,  0.0f},
108
          {+1.0f, +1.0f, -1.0f},
109
          {+1.0f,  0.0f, +1.0f},
110
          {+1.0f,  0.0f,  0.0f},
111
          {+1.0f,  0.0f, -1.0f},
112
          {+1.0f, -1.0f, +1.0f},
113
          {+1.0f, -1.0f, -1.0f},
114
          { 0.0f,  0.0f, +1.0f},
115
          { 0.0f, -1.0f, +1.0f},
116
          { 0.0f,  0.0f, -1.0f},
117
          { 0.0f, -1.0f, -1.0f}
118
        };
119

    
120
  public static final float[][] POS_3 = new float[][]
121
        {
122
          {-1.0f,  1.0f,  1.0f, -1.0f,  0.0f,  1.0f,  0.0f,  1.0f,  1.0f,  0.0f,  0.0f,  1.0f},
123
          { 1.0f,  0.0f, -1.0f,  1.0f,  0.0f,  0.0f,  1.0f,  1.0f, -1.0f,  1.0f,  1.0f,  0.0f},
124
          {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f,  0.0f,  0.0f, -1.0f, -1.0f,  0.0f, -1.0f,  0.0f},
125
          { 1.0f,  1.0f,  1.0f},
126
          { 1.0f,  0.0f,  1.0f},
127
          { 1.0f, -1.0f,  1.0f},
128
          {-1.0f, -1.0f,  1.0f},
129
          { 0.0f, -1.0f,  1.0f},
130
          { 1.0f, -1.0f,  0.0f},
131
          { 1.0f, -1.0f, -1.0f},
132
          {-1.0f,  1.0f, -1.0f},
133
          {-1.0f,  1.0f,  0.0f},
134
          { 0.0f,  1.0f, -1.0f},
135
          { 0.0f,  1.0f,  0.0f},
136
          {-1.0f,  0.0f, -1.0f},
137
          {-1.0f,  0.0f,  0.0f},
138
          { 0.0f,  0.0f, -1.0f}
139
        };
140

    
141
  public static final float[][] POS_4 = new float[][]
142
        {
143
          { 1.0f,  1.0f, -1.0f},
144
          {-1.0f, -1.0f,  0.0f, -1.0f,  0.0f,  0.0f, 0.0f, -1.0f,  0.0f,  0.0f,  0.0f,  0.0f},
145
          {-1.0f,  1.0f, -1.0f,  0.0f,  1.0f, -1.0f},
146
          {-1.0f,  0.0f, -1.0f,  0.0f,  0.0f, -1.0f},
147
          {-1.0f, -1.0f, -1.0f,  0.0f, -1.0f, -1.0f},
148
          {-1.0f,  1.0f,  0.0f, -1.0f,  1.0f,  1.0f},
149
          { 0.0f,  1.0f,  0.0f,  0.0f,  1.0f,  1.0f},
150
          { 1.0f,  1.0f,  0.0f,  1.0f,  1.0f,  1.0f},
151
          {-1.0f, -1.0f,  1.0f, -1.0f,  0.0f,  1.0f},
152
          { 0.0f, -1.0f,  1.0f,  0.0f,  0.0f,  1.0f},
153
          { 1.0f, -1.0f,  1.0f,  1.0f,  0.0f,  1.0f},
154
          { 1.0f, -1.0f,  0.0f,  1.0f,  0.0f,  0.0f},
155
          { 1.0f, -1.0f, -1.0f,  1.0f,  0.0f, -1.0f}
156
        };
157

    
158
  private int[][] mBasicAngle;
159
  private Static4D[] mInitQuats;
160
  private float[][] mCuts;
161
  private int[] mCubitVariantMap;
162
  private int[] mTypeVariantMap;
163
  private int[][] mSolvedQuatsAbstract;
164
  private float[][] mPosition;
165
  private ObjectSignature mSignature;
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  public TwistyBandagedCuboid(InitData data, int meshState, int iconMode, Static4D quat, Static3D move, float scale, InputStream stream)
170
    {
171
    super(data, meshState, iconMode, (data.getNumLayers()[0]+data.getNumLayers()[1]+data.getNumLayers()[2])/3.0f, quat, move, scale, stream);
172
    }
173

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

    
182
  private int cubitIsExternal(float[] pos, float dx, float dy, float dz)
183
    {
184
    int len = pos.length/3;
185
    int x=0, y=0, z=0;
186

    
187
    for(int i=0; i<len; i++)
188
      {
189
      float cx = pos[3*i  ];
190
      float cy = pos[3*i+1];
191
      float cz = pos[3*i+2];
192

    
193
      if( cx>dx || cx<-dx ) x=1;
194
      if( cy>dy || cy<-dy ) y=1;
195
      if( cz>dz || cz<-dz ) z=1;
196
      }
197

    
198
    if( x+y+z>=2 ) return 0;
199

    
200
    if( x==1 ) return 1;
201
    if( y==1 ) return 4;
202
    if( z==1 ) return 7;
203

    
204
    android.util.Log.e("D", "ERROR: unsupported: internal cubit! ");
205
    return 0;
206
    }
207

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

    
217
  @Override
218
  public int[][] getSolvedQuats()
219
    {
220
    if( mSolvedQuatsAbstract==null )
221
      {
222
      int[] numLayers = getNumLayers();
223
      float dx = 0.5f*(numLayers[0]-1) - 0.1f;
224
      float dy = 0.5f*(numLayers[1]-1) - 0.1f;
225
      float dz = 0.5f*(numLayers[2]-1) - 0.1f;
226

    
227
      float[][] pos = getPositions();
228
      int numTotal = pos.length;
229
      boolean[] isExternal = new boolean[numTotal];
230
      int[] internalQuat = new int[numTotal];
231
      int numExternal = 0;
232
      int pointer = 0;
233

    
234
      for(int cubit=0; cubit<numTotal; cubit++)
235
        {
236
        int q = cubitIsExternal(pos[cubit],dx,dy,dz);
237

    
238
        if( q<=0 )
239
          {
240
          isExternal[cubit] = true;
241
          numExternal++;
242
          }
243
        else
244
          {
245
          isExternal[cubit] = false;
246
          internalQuat[pointer] = q;
247
          pointer++;
248
          }
249
        }
250

    
251
      int numInternal = numTotal - numExternal;
252

    
253
      mSolvedQuatsAbstract = new int[numInternal+1][];
254
      mSolvedQuatsAbstract[0] = new int[numExternal+1];
255
      mSolvedQuatsAbstract[0][0] = numExternal;
256

    
257
      for(int i=0; i<numInternal; i++)
258
        {
259
        int q = internalQuat[i];
260
        mSolvedQuatsAbstract[i+1] = new int[5];
261
        mSolvedQuatsAbstract[i+1][0] = 1;
262
        mSolvedQuatsAbstract[i+1][2] = q;
263
        mSolvedQuatsAbstract[i+1][3] = q+1;
264
        mSolvedQuatsAbstract[i+1][4] = q+2;
265
        }
266

    
267
      int pointerExternal = 1;
268
      int pointerInternal = 1;
269

    
270
      for(int cubit=0; cubit<numTotal; cubit++)
271
        {
272
        if( isExternal[cubit] ) mSolvedQuatsAbstract[0][pointerExternal++] = cubit;
273
        else                    mSolvedQuatsAbstract[pointerInternal++][1] = cubit;
274
        }
275
      }
276

    
277
    return mSolvedQuatsAbstract;
278
    }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281
// Computing scramble states of many a bandaged cubes takes way too long time and too much space.
282
// Return null here and turn to construction of scramble tables just-in-time.
283

    
284
  @Override
285
  public ScrambleState[] getScrambleStates()
286
    {
287
    return null;
288
    }
289

    
290
///////////////////////////////////////////////////////////////////////////////////////////////////
291

    
292
  @Override
293
  public int getScrambleType()
294
    {
295
    return 2;
296
    }
297

    
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299

    
300
  private int getType(float[] pos)
301
    {
302
    switch(pos.length)
303
      {
304
      case  3: return CUBIT_111;
305
      case  6: return CUBIT_211;
306
      case  9: boolean x1 = (pos[0]==pos[3] && pos[0]==pos[6]);
307
               boolean y1 = (pos[1]==pos[4] && pos[1]==pos[7]);
308
               boolean z1 = (pos[2]==pos[5] && pos[2]==pos[8]);
309
               return ( (x1&&y1) || (x1&&z1) || (y1&&z1) ) ? CUBIT_311 : CUBIT_OTH;
310
      case 12: float x = (pos[0]+pos[3]+pos[6]+pos[ 9])/4;
311
               float y = (pos[1]+pos[4]+pos[7]+pos[10])/4;
312
               float z = (pos[2]+pos[5]+pos[8]+pos[11])/4;
313
               float d1 = (pos[0]-x)*(pos[0]-x) + (pos[ 1]-y)*(pos[ 1]-y) + (pos[ 2]-z)*(pos[ 2]-z);
314
               float d2 = (pos[3]-x)*(pos[3]-x) + (pos[ 4]-y)*(pos[ 4]-y) + (pos[ 5]-z)*(pos[ 5]-z);
315
               float d3 = (pos[6]-x)*(pos[6]-x) + (pos[ 7]-y)*(pos[ 7]-y) + (pos[ 8]-z)*(pos[ 8]-z);
316
               float d4 = (pos[9]-x)*(pos[9]-x) + (pos[10]-y)*(pos[10]-y) + (pos[11]-z)*(pos[11]-z);
317
               return ( d1==0.5f && d2==0.5f && d3==0.5f && d4==0.5f ) ? CUBIT_221 : CUBIT_OTH;
318
      case 24: float x3 = pos[0];
319
               float y3 = pos[1];
320
               float z3 = pos[2];
321
               float x4=-10,y4=-10,z4=-10;
322
               int i;
323

    
324
               for(i=0; i<8; i++)
325
                 {
326
                 if( pos[3*i]!=x3 && pos[3*i+1]!=y3 && pos[3*i+2]!=z3 )
327
                   {
328
                   x4 = pos[3*i  ];
329
                   y4 = pos[3*i+1];
330
                   z4 = pos[3*i+2];
331
                   break;
332
                   }
333
                 }
334
               if( i==9 ) return CUBIT_OTH;
335

    
336
               float dX = x4-x3;
337
               float dY = y4-y3;
338
               float dZ = z4-z3;
339

    
340
               if( (dX==1.0f || dX==-1.0f) && (dY==1.0f || dY==-1.0f) && (dZ==1.0f || dZ==-1.0f) )
341
                 {
342
                 for(i=0; i<8; i++)
343
                   {
344
                   if( (pos[3*i  ]!=x3 && pos[3*i  ]!=x4) ||
345
                       (pos[3*i+1]!=y3 && pos[3*i+1]!=y4) ||
346
                       (pos[3*i+2]!=z3 && pos[3*i+2]!=z4)  ) return CUBIT_OTH;
347
                   }
348

    
349
                 return CUBIT_222;
350
                 }
351

    
352
      default: return CUBIT_OTH;
353
      }
354
    }
355

    
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357

    
358
  private int getQuatIndex(int cubit)
359
    {
360
    float[][] positions = getPositions();
361
    int len = positions.length;
362

    
363
    if( cubit>=0 && cubit<len )
364
      {
365
      float[] pos = positions[cubit];
366
      int type = getType(pos);
367

    
368
      switch(type)
369
        {
370
        case CUBIT_222:
371
        case CUBIT_111: return 0;
372
        case CUBIT_211:
373
        case CUBIT_311: return (pos[1]==pos[4]) ? (pos[0]==pos[3] ? 2 : 0) : 3;
374
        case CUBIT_221: if( pos[0]==pos[3] && pos[0]==pos[6] ) return 3;
375
                        if( pos[1]==pos[4] && pos[1]==pos[7] ) return 0;
376
                        if( pos[2]==pos[5] && pos[2]==pos[8] ) return 1;
377
        }
378
      }
379

    
380
    return 0;
381
    }
382

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

    
385
  public ObjectShape getObjectShape(int variant)
386
    {
387
    int type,numTypes = mDims.length;
388
    for(type=0; type<numTypes; type++) if( mTypeVariantMap[type]==variant ) break;
389

    
390
    if( type<numTypes )
391
      {
392
      int X = mDims[type][0];
393
      int Y = mDims[type][1];
394
      int Z = mDims[type][2];
395

    
396
      float[][] vertices =
397
        {
398
          { 0.5f*X, 0.5f*Y, 0.5f*Z},
399
          { 0.5f*X, 0.5f*Y,-0.5f*Z},
400
          { 0.5f*X,-0.5f*Y, 0.5f*Z},
401
          { 0.5f*X,-0.5f*Y,-0.5f*Z},
402
          {-0.5f*X, 0.5f*Y, 0.5f*Z},
403
          {-0.5f*X, 0.5f*Y,-0.5f*Z},
404
          {-0.5f*X,-0.5f*Y, 0.5f*Z},
405
          {-0.5f*X,-0.5f*Y,-0.5f*Z}
406
        };
407

    
408
      int[][] indices =
409
        {
410
          {2,3,1,0},
411
          {7,6,4,5},
412
          {4,0,1,5},
413
          {7,3,2,6},
414
          {6,2,0,4},
415
          {3,7,5,1},
416
        };
417

    
418
      return new ObjectShape(vertices, indices);
419
      }
420

    
421
    float[][] positions = getPositions();
422
    int cubit,numCubits = positions.length;
423

    
424
    for(cubit=0; cubit<numCubits; cubit++)
425
      {
426
      if( mCubitVariantMap[cubit]==variant ) break;
427
      }
428

    
429
    if( cubit>=numCubits )
430
      {
431
      android.util.Log.e("D", "unknown variant: "+variant);
432
      return null;
433
      }
434

    
435
    FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
436
    return factory.createIrregularShape(variant,positions[cubit]);
437
    }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440

    
441
  public ObjectFaceShape getObjectFaceShape(int variant)
442
    {
443
    int[] numLayers = getNumLayers();
444
    int size = (numLayers[0]+numLayers[1]+numLayers[2])/3;
445
    int type,numTypes = mDims.length;
446
    for(type=0; type<numTypes; type++) if( mTypeVariantMap[type]==variant ) break;
447

    
448
    if( type<numTypes )
449
      {
450
      int X = mDims[type][0];
451
      int Y = mDims[type][1];
452
      int Z = mDims[type][2];
453

    
454
      float height     = isInIconMode() ? 0.001f : size<=5 ? 0.048f : 0.020f;
455
      int[] bandIndices= { 0,0,1,1,2,2 };
456

    
457
      int maxXY = Math.max(X,Y);
458
      int maxXZ = Math.max(X,Z);
459
      int maxYZ = Math.max(Y,Z);
460

    
461
      int angle = 45;
462
      float R = 0.25f;
463
      float S = 0.50f;
464
      float N = size<=4 ? 5 : size<=5 ? 4 : 3;
465

    
466
      float[][] bands =
467
        {
468
          {height/maxYZ,angle,R,S,N,0,0},
469
          {height/maxXZ,angle,R,S,N,0,0},
470
          {height/maxXY,angle,R,S,N,0,0}
471
        };
472

    
473
      return new ObjectFaceShape(bands,bandIndices,null);
474
      }
475

    
476
    FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
477
    return factory.createIrregularFaceShape(variant, isInIconMode() );
478
    }
479

    
480
///////////////////////////////////////////////////////////////////////////////////////////////////
481

    
482
  public ObjectVertexEffects getVertexEffects(int variant)
483
    {
484
    int[] numLayers = getNumLayers();
485
    int size = (numLayers[0]+numLayers[1]+numLayers[2])/3;
486
    boolean round = (DistortedLibrary.fastCompilationTF() && size<=5 && !isInIconMode());
487
    int type,numTypes = mDims.length;
488
    for(type=0; type<numTypes; type++) if( mTypeVariantMap[type]==variant ) break;
489

    
490
    if( type<numTypes )
491
      {
492
      int X = mDims[type][0];
493
      int Y = mDims[type][1];
494
      int Z = mDims[type][2];
495

    
496
      float[][] centers =
497
        {
498
          { 0.5f*X, 0.5f*Y, 0.5f*Z},
499
          { 0.5f*X, 0.5f*Y,-0.5f*Z},
500
          { 0.5f*X,-0.5f*Y, 0.5f*Z},
501
          { 0.5f*X,-0.5f*Y,-0.5f*Z},
502
          {-0.5f*X, 0.5f*Y, 0.5f*Z},
503
          {-0.5f*X, 0.5f*Y,-0.5f*Z},
504
          {-0.5f*X,-0.5f*Y, 0.5f*Z},
505
          {-0.5f*X,-0.5f*Y,-0.5f*Z}
506
        };
507

    
508
      float strength = -0.04f;
509

    
510
      float[][] variables =
511
        {
512
          { 0, strength*centers[0][0], strength*centers[0][1], strength*centers[0][2], 1  },
513
          { 0, strength*centers[1][0], strength*centers[1][1], strength*centers[1][2], 1  },
514
          { 0, strength*centers[2][0], strength*centers[2][1], strength*centers[2][2], 1  },
515
          { 0, strength*centers[3][0], strength*centers[3][1], strength*centers[3][2], 1  },
516
          { 0, strength*centers[4][0], strength*centers[4][1], strength*centers[4][2], 1  },
517
          { 0, strength*centers[5][0], strength*centers[5][1], strength*centers[5][2], 1  },
518
          { 0, strength*centers[6][0], strength*centers[6][1], strength*centers[6][2], 1  },
519
          { 0, strength*centers[7][0], strength*centers[7][1], strength*centers[7][2], 1  },
520
        };
521

    
522
      String name = EffectName.DEFORM.name();
523
      float[] reg = {0,0,0,0.15f};
524

    
525
      String[] names = {name,name,name,name,name,name,name,name};
526
      float[][] regions = {reg,reg,reg,reg,reg,reg,reg,reg};
527
      boolean[] uses = {round,round,round,round,round,round,round,round};
528

    
529
      return new ObjectVertexEffects(names,variables,centers,regions,uses);
530
      }
531

    
532
    FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
533
    return factory.createVertexEffects(variant,round);
534
    }
535

    
536
///////////////////////////////////////////////////////////////////////////////////////////////////
537

    
538
  public float[][] getCubitPositions(int[] numLayers)
539
    {
540
    return getPositions();
541
    }
542

    
543
///////////////////////////////////////////////////////////////////////////////////////////////////
544

    
545
  public Static4D getCubitQuats(int cubit, int[] numLayers)
546
    {
547
    if( mInitQuats ==null )
548
      {
549
      mInitQuats = new Static4D[]
550
        {
551
        new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),  // NULL
552
        new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),  // X
553
        new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),  // Y
554
        new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),  // Z
555
        new Static4D( -0.5f,  +0.5f,  -0.5f,  +0.5f),  // ZX
556
        new Static4D( +0.5f,  +0.5f,  +0.5f,  -0.5f),  // YX
557
        };
558
      }
559

    
560
    return mInitQuats[getQuatIndex(cubit)];
561
    }
562

    
563
///////////////////////////////////////////////////////////////////////////////////////////////////
564

    
565
  public int getNumCubitVariants(int[] numLayers)
566
    {
567
    int numVariants = 0;
568
    float[][] positions = getPositions();
569
    boolean C111=false;
570
    boolean C211=false;
571
    boolean C311=false;
572
    boolean C221=false;
573
    boolean C222=false;
574

    
575
    int numCubits = positions.length;
576
    mCubitVariantMap = new int[numCubits];
577

    
578
    int numTypes = mDims.length;
579
    mTypeVariantMap = new int[numTypes];
580
    for(int i=0; i<numTypes; i++) mTypeVariantMap[i] = -1;
581

    
582
    for (int cubit=0; cubit<numCubits; cubit++)
583
      {
584
      int type = getType(positions[cubit]);
585

    
586
      switch (type)
587
        {
588
        case CUBIT_111: if (!C111) { C111 = true; mTypeVariantMap[CUBIT_111]=numVariants++; }
589
                        mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_111];
590
                        break;
591
        case CUBIT_211: if (!C211) { C211 = true; mTypeVariantMap[CUBIT_211]=numVariants++; }
592
                        mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_211];
593
                        break;
594
        case CUBIT_311: if (!C311) { C311 = true; mTypeVariantMap[CUBIT_311]=numVariants++; }
595
                        mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_311];
596
                        break;
597
        case CUBIT_221: if (!C221) { C221 = true; mTypeVariantMap[CUBIT_221]=numVariants++; }
598
                        mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_221];
599
                        break;
600
        case CUBIT_222: if (!C222) { C222 = true; mTypeVariantMap[CUBIT_222]=numVariants++; }
601
                        mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_222];
602
                        break;
603
        default       : mCubitVariantMap[cubit] = numVariants++;
604
        }
605
      }
606

    
607
    FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
608
    factory.prepare(numVariants,numLayers[0],numLayers[1],numLayers[2]);
609

    
610
    return numVariants;
611
    }
612

    
613
///////////////////////////////////////////////////////////////////////////////////////////////////
614

    
615
  public int getCubitVariant(int cubit, int[] numLayers)
616
    {
617
    return mCubitVariantMap[cubit];
618
    }
619

    
620
///////////////////////////////////////////////////////////////////////////////////////////////////
621

    
622
  public float[][] getCuts(int[] numLayers)
623
    {
624
    if( mCuts==null )
625
      {
626
      mCuts = new float[3][];
627

    
628
      for(int axis=0; axis<3; axis++)
629
        {
630
        int len = numLayers[axis];
631
        float start = (2-len)*0.5f;
632

    
633
        if( len>=2 )
634
          {
635
          mCuts[axis] = new float[len-1];
636
          for(int i=0; i<len-1; i++) mCuts[axis][i] = start+i;
637
          }
638
        }
639
      }
640

    
641
    return mCuts;
642
    }
643

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

    
646
  public boolean[][] getLayerRotatable(int[] numLayers)
647
    {
648
    int numAxis = ROT_AXIS.length;
649
    boolean[][] layerRotatable = new boolean[numAxis][];
650

    
651
    for(int i=0; i<numAxis; i++)
652
      {
653
      layerRotatable[i] = new boolean[numLayers[i]];
654
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
655
      }
656

    
657
    return layerRotatable;
658
    }
659

    
660
///////////////////////////////////////////////////////////////////////////////////////////////////
661

    
662
  public int getTouchControlType()
663
    {
664
    return TC_CUBOID;
665
    }
666

    
667
///////////////////////////////////////////////////////////////////////////////////////////////////
668

    
669
  public int getTouchControlSplit()
670
    {
671
    return TYPE_NOT_SPLIT;
672
    }
673

    
674
///////////////////////////////////////////////////////////////////////////////////////////////////
675

    
676
  public int[][][] getEnabled()
677
    {
678
    return new int[][][] { {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}} };
679
    }
680

    
681
///////////////////////////////////////////////////////////////////////////////////////////////////
682

    
683
  public float[] getDist3D(int[] numLayers)
684
    {
685
    float x = numLayers[0];
686
    float y = numLayers[1];
687
    float z = numLayers[2];
688
    float a = (x+y+z)/1.5f;
689

    
690
    return new float[] {x/a,x/a,y/a,y/a,z/a,z/a};
691
    }
692

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

    
695
  public Static3D[] getFaceAxis()
696
    {
697
    return TouchControlHexahedron.FACE_AXIS;
698
    }
699

    
700
///////////////////////////////////////////////////////////////////////////////////////////////////
701

    
702
  public float getStickerRadius()
703
    {
704
    return 0.10f;
705
    }
706

    
707
///////////////////////////////////////////////////////////////////////////////////////////////////
708

    
709
  public float getStickerStroke()
710
    {
711
    return isInIconMode() ? 0.16f : 0.08f;
712
    }
713

    
714
///////////////////////////////////////////////////////////////////////////////////////////////////
715

    
716
  public float[][] getStickerAngles()
717
    {
718
    return null;
719
    }
720

    
721
///////////////////////////////////////////////////////////////////////////////////////////////////
722
// PUBLIC API
723

    
724
  public Static3D[] getRotationAxis()
725
    {
726
    return ROT_AXIS;
727
    }
728

    
729
///////////////////////////////////////////////////////////////////////////////////////////////////
730

    
731
  public int[][] getBasicAngles()
732
    {
733
     if( mBasicAngle==null )
734
      {
735
      int[] num = getNumLayers();
736
      int numX = num[0];
737
      int numY = num[1];
738
      int numZ = num[2];
739

    
740
      int x = numY==numZ ? 4 : 2;
741
      int y = numX==numZ ? 4 : 2;
742
      int z = numX==numY ? 4 : 2;
743

    
744
      int[] tmpX = new int[numX];
745
      for(int i=0; i<numX; i++) tmpX[i] = x;
746
      int[] tmpY = new int[numY];
747
      for(int i=0; i<numY; i++) tmpY[i] = y;
748
      int[] tmpZ = new int[numZ];
749
      for(int i=0; i<numZ; i++) tmpZ[i] = z;
750

    
751
      mBasicAngle = new int[][] { tmpX,tmpY,tmpZ };
752
      }
753

    
754
    return mBasicAngle;
755
    }
756

    
757
///////////////////////////////////////////////////////////////////////////////////////////////////
758

    
759
  float[][] getPositions()
760
    {
761
    if( mPosition==null ) mPosition = getInitData().getPos();
762
    return mPosition;
763
    }
764

    
765
///////////////////////////////////////////////////////////////////////////////////////////////////
766

    
767
  public static int getType(String shortName, String longName)
768
    {
769
    if( shortName.equals(ObjectType.BAN1_3.name()) ||
770
        shortName.equals(ObjectType.BAN2_3.name()) ||
771
        shortName.equals(ObjectType.BAN3_3.name()) ||
772
        shortName.equals(ObjectType.BAN4_3.name())  ) return 2;
773

    
774
    if( longName.equals(OBJECT_NAME) ) return 1;
775

    
776
    return 0;
777
    }
778

    
779
///////////////////////////////////////////////////////////////////////////////////////////////////
780
// PUBLIC APi
781

    
782
  public String getShortName()
783
    {
784
    if( mPosition==null ) mPosition = getInitData().getPos();
785

    
786
    if( mPosition==POS_1 ) return ObjectType.BAN1_3.name();
787
    if( mPosition==POS_2 ) return ObjectType.BAN2_3.name();
788
    if( mPosition==POS_3 ) return ObjectType.BAN3_3.name();
789
    if( mPosition==POS_4 ) return ObjectType.BAN4_3.name();
790

    
791
    if( mSignature==null ) mSignature = getSignature();
792
    int[] numLayers = getNumLayers();
793
    int number = 100*numLayers[0]+10*numLayers[1]+numLayers[2];
794

    
795
    return number+"_"+mSignature.getString();
796
    }
797

    
798
///////////////////////////////////////////////////////////////////////////////////////////////////
799

    
800
  public ObjectSignature getSignature()
801
    {
802
    if( mSignature==null )
803
      {
804
      int[] numLayers = getNumLayers();
805
      mSignature = new ObjectSignature(numLayers[0],numLayers[1],numLayers[2],mPosition);
806
      }
807
    return mSignature;
808
    }
809

    
810
///////////////////////////////////////////////////////////////////////////////////////////////////
811

    
812
  public String getObjectName()
813
    {
814
    if( mPosition==null ) mPosition = getInitData().getPos();
815

    
816
    if( mPosition==POS_1 ) return "Fused Cube";
817
    if( mPosition==POS_2 ) return "2Bar Cube";
818
    if( mPosition==POS_3 ) return "Bandaged Cube C";
819
    if( mPosition==POS_4 ) return "BiCube";
820

    
821
    return OBJECT_NAME;
822
    }
823

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

    
826
  public String getInventor()
827
    {
828
    if( mPosition==null ) mPosition = getInitData().getPos();
829

    
830
    if( mPosition==POS_1 ) return "Ting Huang";
831
    if( mPosition==POS_2 ) return "Unknown";
832
    if( mPosition==POS_3 ) return "Andreas Nortmann";
833
    if( mPosition==POS_4 ) return "Uwe Meffert";
834

    
835
    return "??";
836
    }
837

    
838
///////////////////////////////////////////////////////////////////////////////////////////////////
839

    
840
  public int getYearOfInvention()
841
    {
842
    if( mPosition==null ) mPosition = getInitData().getPos();
843

    
844
    if( mPosition==POS_1 ) return 2011;
845
    if( mPosition==POS_2 ) return 0;
846
    if( mPosition==POS_3 ) return 2005;
847
    if( mPosition==POS_4 ) return 1999;
848

    
849
    return 0;
850
    }
851

    
852
///////////////////////////////////////////////////////////////////////////////////////////////////
853

    
854
  public int getComplexity()
855
    {
856
    if( mPosition==null ) mPosition = getInitData().getPos();
857

    
858
    if( mPosition==POS_1 ) return 1;
859
    if( mPosition==POS_2 ) return 2;
860
    if( mPosition==POS_3 ) return 2;
861
    if( mPosition==POS_4 ) return 3;
862

    
863
    return 4;
864
    }
865

    
866
///////////////////////////////////////////////////////////////////////////////////////////////////
867

    
868
  public String[][] getTutorials()
869
    {
870
    if( mPosition==null ) mPosition = getInitData().getPos();
871

    
872
    if( mPosition==POS_1 )
873
      {
874
      return new String[][]{
875
                            {"gb","F_iJk_IvpVo","Bandaged Cube","CanChrisSolve"},
876
                            {"es","_lTgw5aEFOg","Tutorial 3x3 Fuse Cube","QBAndo"},
877
                            {"ru","raYDwFEXIq4","Как собрать Fused Cube","Алексей Ярыгин"},
878
                            {"fr","9Cfi4rhKzIw","Tutoriel: résolution du Fused Cube","Skieur Cubb"},
879
                            {"pl","0PcUoGxQa6s","Bandaged 3x3 v.A cube","MrUK"},
880
                            {"kr","1RePOLrzJNE","밴디지 타입 A 해법","듀나메스 큐브 해법연구소"},
881
                            {"vn","vg4J0U0n1oA","Tutorial N.1 - Bandaged VA","Duy Thích Rubik"},
882
                           };
883
      }
884
    if( mPosition==POS_2 )
885
      {
886
      return new String[][]{
887
                            {"ru","lS_EK0PMWI8","Как собрать 2-bar Cube","Алексей Ярыгин"},
888
                            {"pl","tX8ubTLh6p8","Bandaged 3x3 (Two bar)","MrUK"},
889
                            {"kr","NE6XuC1r8xw","밴디지 큐브","Denzel Washington"},
890
                           };
891
      }
892
    if( mPosition==POS_3 )
893
      {
894
      return new String[][]{
895
                            {"gb","7UiCVGygUT4","Bandage Cube C Tutorial","PolyakB"},
896
                            {"ru","gXenRA92Wdc","Как собрать Bandaged 3x3 Type C","YG Cuber"},
897
                            {"pl","sKfdFLm79Zs","Bandaged 3x3 v.C cube","MrUK"},
898
                            {"kr","BcCFgeFy6Ec","밴디지 타입 C 해법","듀나메스 큐브 해법연구소"},
899
                            {"vn","9674LLkPSog","Tutorial N.2 - Bandaged VC","Duy Thích Rubik"},
900
                           };
901
      }
902
    if( mPosition==POS_4 )
903
      {
904
      return new String[][]{
905
                            {"gb","AnpdIKICBpM","Trying to Solve a Bandaged Cube","RedKB"},
906
                            {"es","cUyo5fycrvI","Tutorial Bandaged Cube en español","Rafa Garcia Benacazon"},
907
                            {"ru","-MTzeEJptsg","Как собрать bandaged Cube B","стратегия знаний"},
908
                            {"fr","3rsfIJ3roT0","Tutoriel: résolution du Bicube","Skieur Cubb"},
909
                            {"de","sqWVRwkXX9w","Bandaged Cube - Tutorial","GerCubing"},
910
                            {"pl","XcHzTvVR6Po","Bandaged 3x3 v.B cube","MrUK"},
911
                            {"kr","1gsoijF_5q0","BiCube Tutorial (해법)","듀나메스 큐브 해법연구소"},
912
                            {"vn","ZCJDaF4jEbc","Tutorial N.3 - BiCube","Duy Thích Rubik"},
913
                           };
914
      }
915

    
916
    return null;
917
    }
918
}
(2-2/38)