Project

General

Profile

« Previous | Next » 

Revision e7569064

Added by Leszek Koltunski over 1 year ago

Beginnings of support for the Camouflage 3x3x3.

View differences:

src/main/java/org/distorted/objectlib/main/ObjectSignatures.java
79 79
  public static final int PDUO_2 = ObjectType.PDUO_2.ordinal();
80 80
  public static final int PDIA_3 = ObjectType.PDIA_3.ordinal();
81 81
  public static final int BALL_4 = ObjectType.BALL_4.ordinal();
82
  public static final int CA_333 = ObjectType.CA_333.ordinal();
82 83
  }
src/main/java/org/distorted/objectlib/main/ObjectType.java
98 98
  MIXP_3 ( TwistyMixup3x3Plus.class   , 28, R.drawable.mixp_3, true,    70, new InitData(new int[] {3,3,3})),
99 99
  DINO_3 ( TwistyDino6.class          , 10, R.drawable.dino_3, true,     0, new InitData(new int[] {3,3,3,3})),
100 100
  DIN4_3 ( TwistyDino4.class          ,  9, R.drawable.din4_3, true,    30, new InitData(new int[] {3,3,3,3})),
101

  
102
  CA_333 ( TwistyCamouflage.class     , 32, R.drawable.din4_3, true,    50, new InitData(new int[] {3,3,3}, TwistyCamouflage.CAM_333)),
103

  
101 104
  PDUO_2 ( TwistyPyraminxDuo.class    ,  4, R.drawable.pduo_2, false,    0, new InitData(new int[] {2,2,2,2})),
102 105
  PDIA_3 ( TwistyPyraminxDiamond.class, 12, R.drawable.pdia_3, false,   40, new InitData(new int[] {3,3,3})),
103 106
  BALL_4 ( TwistyMasterball.class     , 28, R.drawable.ball_4, false,   70, new InitData(new int[] {4,2,2,2,2})),
src/main/java/org/distorted/objectlib/objects/TwistyBandagedAbstract.java
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 org.distorted.library.effect.EffectName;
16
import org.distorted.library.main.DistortedLibrary;
17
import org.distorted.library.type.Static3D;
18
import org.distorted.library.type.Static4D;
19
import org.distorted.objectlib.helpers.FactoryBandagedCubit;
20
import org.distorted.objectlib.helpers.ObjectFaceShape;
21
import org.distorted.objectlib.helpers.ObjectShape;
22
import org.distorted.objectlib.helpers.ObjectSignature;
23
import org.distorted.objectlib.helpers.ObjectVertexEffects;
24
import org.distorted.objectlib.main.InitData;
25
import org.distorted.objectlib.scrambling.ScrambleState;
26
import org.distorted.objectlib.shape.ShapeHexahedron;
27
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
28

  
29
import java.io.InputStream;
30

  
31
///////////////////////////////////////////////////////////////////////////////////////////////////
32

  
33
public abstract class TwistyBandagedAbstract extends ShapeHexahedron
34
{
35
  private static final int CUBIT_111 = 0;
36
  private static final int CUBIT_211 = 1;
37
  private static final int CUBIT_311 = 2;
38
  private static final int CUBIT_221 = 3;
39
  private static final int CUBIT_222 = 4;
40
  private static final int CUBIT_OTH = 5;
41

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

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

  
59
  private int[][] mBasicAngle;
60
  private Static4D[] mInitQuats;
61
  private float[][] mCuts;
62
  private int[] mCubitVariantMap;
63
  private int[] mTypeVariantMap;
64
  private int[][] mSolvedQuatsAbstract;
65

  
66
  protected ObjectShape[] mTmpShapes;
67
  protected int mNumVariants;
68
  protected float[][] mPosition;
69
  protected ObjectSignature mSignature;
70

  
71
///////////////////////////////////////////////////////////////////////////////////////////////////
72

  
73
  public TwistyBandagedAbstract(InitData data, int meshState, int iconMode, float size, Static4D quat, Static3D move, float scale, InputStream stream)
74
    {
75
    super(data, meshState, iconMode, size, quat, move, scale, stream);
76
    }
77

  
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

  
80
  abstract float[][] getVertices(int variant);
81

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

  
90
  private int cubitIsExternal(float[] pos, float dx, float dy, float dz)
91
    {
92
    int len = pos.length/3;
93
    int x=0, y=0, z=0;
94

  
95
    for(int i=0; i<len; i++)
96
      {
97
      float cx = pos[3*i  ];
98
      float cy = pos[3*i+1];
99
      float cz = pos[3*i+2];
100

  
101
      if( cx>dx || cx<-dx ) x=1;
102
      if( cy>dy || cy<-dy ) y=1;
103
      if( cz>dz || cz<-dz ) z=1;
104
      }
105

  
106
    if( x+y+z>=2 ) return 0;
107

  
108
    if( x==1 ) return 1;
109
    if( y==1 ) return 4;
110
    if( z==1 ) return 7;
111

  
112
    android.util.Log.e("D", "ERROR: unsupported: internal cubit! ");
113
    return 0;
114
    }
115

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

  
125
  @Override
126
  public int[][] getSolvedQuats()
127
    {
128
    if( mSolvedQuatsAbstract==null )
129
      {
130
      int[] numLayers = getNumLayers();
131
      float dx = 0.5f*(numLayers[0]-1) - 0.1f;
132
      float dy = 0.5f*(numLayers[1]-1) - 0.1f;
133
      float dz = 0.5f*(numLayers[2]-1) - 0.1f;
134

  
135
      float[][] pos = getPositions();
136
      int numTotal = pos.length;
137
      boolean[] isExternal = new boolean[numTotal];
138
      int[] internalQuat = new int[numTotal];
139
      int numExternal = 0;
140
      int pointer = 0;
141

  
142
      for(int cubit=0; cubit<numTotal; cubit++)
143
        {
144
        int q = cubitIsExternal(pos[cubit],dx,dy,dz);
145

  
146
        if( q<=0 )
147
          {
148
          isExternal[cubit] = true;
149
          numExternal++;
150
          }
151
        else
152
          {
153
          isExternal[cubit] = false;
154
          internalQuat[pointer] = q;
155
          pointer++;
156
          }
157
        }
158

  
159
      int numInternal = numTotal - numExternal;
160

  
161
      mSolvedQuatsAbstract = new int[numInternal+1][];
162
      mSolvedQuatsAbstract[0] = new int[numExternal+1];
163
      mSolvedQuatsAbstract[0][0] = numExternal;
164

  
165
      for(int i=0; i<numInternal; i++)
166
        {
167
        int q = internalQuat[i];
168
        mSolvedQuatsAbstract[i+1] = new int[5];
169
        mSolvedQuatsAbstract[i+1][0] = 1;
170
        mSolvedQuatsAbstract[i+1][2] = q;
171
        mSolvedQuatsAbstract[i+1][3] = q+1;
172
        mSolvedQuatsAbstract[i+1][4] = q+2;
173
        }
174

  
175
      int pointerExternal = 1;
176
      int pointerInternal = 1;
177

  
178
      for(int cubit=0; cubit<numTotal; cubit++)
179
        {
180
        if( isExternal[cubit] ) mSolvedQuatsAbstract[0][pointerExternal++] = cubit;
181
        else                    mSolvedQuatsAbstract[pointerInternal++][1] = cubit;
182
        }
183
      }
184

  
185
    return mSolvedQuatsAbstract;
186
    }
187

  
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189
// Computing scramble states of many a bandaged cubes takes way too long time and too much space.
190
// Return null here and turn to construction of scramble tables just-in-time.
191

  
192
  @Override
193
  public ScrambleState[] getScrambleStates()
194
    {
195
    return null;
196
    }
197

  
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199

  
200
  @Override
201
  public int getScrambleType()
202
    {
203
    return 2;
204
    }
205

  
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

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

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

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

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

  
257
                 return CUBIT_222;
258
                 }
259

  
260
      default: return CUBIT_OTH;
261
      }
262
    }
263

  
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

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

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

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

  
288
    return 0;
289
    }
290

  
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292

  
293
  protected int[] getDim(int variant)
294
    {
295
    int type,numTypes = mDims.length;
296
    for(type=0; type<numTypes; type++) if( mTypeVariantMap[type]==variant ) break;
297
    return type<numTypes ? mDims[type] : null;
298
    }
299

  
300
///////////////////////////////////////////////////////////////////////////////////////////////////
301

  
302
  protected void produceTmpShape(int variant)
303
    {
304
    float[][] positions = getPositions();
305
    int cubit,numCubits = positions.length;
306

  
307
    for(cubit=0; cubit<numCubits; cubit++)
308
      {
309
      if( mCubitVariantMap[cubit]==variant ) break;
310
      }
311

  
312
    if( cubit>=numCubits )
313
      {
314
      android.util.Log.e("D", "unknown variant: "+variant);
315
      }
316
    else
317
      {
318
      FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
319
      mTmpShapes[variant] = factory.createIrregularShape(variant,positions[cubit]);
320
      }
321
    }
322

  
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324

  
325
  public ObjectShape getObjectShape(int variant)
326
    {
327
    if( getDim(variant)!=null )
328
      {
329
      int[][] indices =
330
        {
331
          {2,3,1,0},
332
          {7,6,4,5},
333
          {4,0,1,5},
334
          {7,3,2,6},
335
          {6,2,0,4},
336
          {3,7,5,1},
337
        };
338

  
339
      return new ObjectShape( getVertices(variant), indices);
340
      }
341

  
342
    if( mTmpShapes==null ) mTmpShapes = new ObjectShape[mNumVariants];
343
    if( mTmpShapes[variant]==null )produceTmpShape(variant);
344
    return mTmpShapes[variant];
345
    }
346

  
347
///////////////////////////////////////////////////////////////////////////////////////////////////
348

  
349
  public ObjectFaceShape getObjectFaceShape(int variant)
350
    {
351
    int[] numLayers = getNumLayers();
352
    int size = (numLayers[0]+numLayers[1]+numLayers[2])/3;
353
    int[] dim = getDim(variant);
354

  
355
    if( dim!=null )
356
      {
357
      int X = dim[0];
358
      int Y = dim[1];
359
      int Z = dim[2];
360

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

  
364
      int maxXY = Math.max(X,Y);
365
      int maxXZ = Math.max(X,Z);
366
      int maxYZ = Math.max(Y,Z);
367

  
368
      int angle = 45;
369
      float R = 0.25f;
370
      float S = 0.50f;
371
      float N = size<=4 ? 5 : size<=5 ? 4 : 3;
372

  
373
      float[][] bands =
374
        {
375
          {height/maxYZ,angle,R,S,N,0,0},
376
          {height/maxXZ,angle,R,S,N,0,0},
377
          {height/maxXY,angle,R,S,N,0,0}
378
        };
379

  
380
      return new ObjectFaceShape(bands,bandIndices,null);
381
      }
382

  
383
    FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
384
    return factory.createIrregularFaceShape(variant, isInIconMode() );
385
    }
386

  
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388

  
389
  public ObjectVertexEffects getVertexEffects(int variant)
390
    {
391
    int[] numLayers = getNumLayers();
392
    int size = (numLayers[0]+numLayers[1]+numLayers[2])/3;
393
    boolean round = (DistortedLibrary.fastCompilationTF() && size<=5 && !isInIconMode());
394

  
395
    if( getDim(variant)!=null )
396
      {
397
      float[][] vertices = getVertices(variant);
398
      float strength = -0.04f;
399

  
400
      float[][] variables =
401
        {
402
          { 0, strength*vertices[0][0], strength*vertices[0][1], strength*vertices[0][2], 1  },
403
          { 0, strength*vertices[1][0], strength*vertices[1][1], strength*vertices[1][2], 1  },
404
          { 0, strength*vertices[2][0], strength*vertices[2][1], strength*vertices[2][2], 1  },
405
          { 0, strength*vertices[3][0], strength*vertices[3][1], strength*vertices[3][2], 1  },
406
          { 0, strength*vertices[4][0], strength*vertices[4][1], strength*vertices[4][2], 1  },
407
          { 0, strength*vertices[5][0], strength*vertices[5][1], strength*vertices[5][2], 1  },
408
          { 0, strength*vertices[6][0], strength*vertices[6][1], strength*vertices[6][2], 1  },
409
          { 0, strength*vertices[7][0], strength*vertices[7][1], strength*vertices[7][2], 1  },
410
        };
411

  
412
      String name = EffectName.DEFORM.name();
413
      float[] reg = {0,0,0,0.15f};
414

  
415
      String[] names = {name,name,name,name,name,name,name,name};
416
      float[][] regions = {reg,reg,reg,reg,reg,reg,reg,reg};
417
      boolean[] uses = {round,round,round,round,round,round,round,round};
418

  
419
      return new ObjectVertexEffects(names,variables,vertices,regions,uses);
420
      }
421

  
422
    FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
423
    return factory.createVertexEffects(variant,round);
424
    }
425

  
426
///////////////////////////////////////////////////////////////////////////////////////////////////
427

  
428
  public float[][] getCubitPositions(int[] numLayers)
429
    {
430
    return getPositions();
431
    }
432

  
433
///////////////////////////////////////////////////////////////////////////////////////////////////
434

  
435
  public Static4D getCubitQuats(int cubit, int[] numLayers)
436
    {
437
    if( mInitQuats ==null )
438
      {
439
      mInitQuats = new Static4D[]
440
        {
441
        new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),  // NULL
442
        new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),  // X
443
        new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),  // Y
444
        new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),  // Z
445
        new Static4D( -0.5f,  +0.5f,  -0.5f,  +0.5f),  // ZX
446
        new Static4D( +0.5f,  +0.5f,  +0.5f,  -0.5f),  // YX
447
        };
448
      }
449

  
450
    return mInitQuats[getQuatIndex(cubit)];
451
    }
452

  
453
///////////////////////////////////////////////////////////////////////////////////////////////////
454

  
455
  public int getNumCubitVariants(int[] numLayers)
456
    {
457
    if( mNumVariants==0 )
458
      {
459
      float[][] positions = getPositions();
460
      boolean C111=false;
461
      boolean C211=false;
462
      boolean C311=false;
463
      boolean C221=false;
464
      boolean C222=false;
465

  
466
      int numCubits = positions.length;
467
      mCubitVariantMap = new int[numCubits];
468

  
469
      int numTypes = mDims.length;
470
      mTypeVariantMap = new int[numTypes];
471
      for(int i=0; i<numTypes; i++) mTypeVariantMap[i] = -1;
472

  
473
      for (int cubit=0; cubit<numCubits; cubit++)
474
        {
475
        int type = getType(positions[cubit]);
476

  
477
        switch (type)
478
          {
479
          case CUBIT_111: if (!C111) { C111 = true; mTypeVariantMap[CUBIT_111]=mNumVariants++; }
480
                          mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_111];
481
                          break;
482
          case CUBIT_211: if (!C211) { C211 = true; mTypeVariantMap[CUBIT_211]=mNumVariants++; }
483
                          mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_211];
484
                          break;
485
          case CUBIT_311: if (!C311) { C311 = true; mTypeVariantMap[CUBIT_311]=mNumVariants++; }
486
                          mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_311];
487
                          break;
488
          case CUBIT_221: if (!C221) { C221 = true; mTypeVariantMap[CUBIT_221]=mNumVariants++; }
489
                          mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_221];
490
                          break;
491
          case CUBIT_222: if (!C222) { C222 = true; mTypeVariantMap[CUBIT_222]=mNumVariants++; }
492
                          mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_222];
493
                          break;
494
          default       : mCubitVariantMap[cubit] = mNumVariants++;
495
          }
496
        }
497

  
498
      FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
499
      factory.prepare(mNumVariants,numLayers[0],numLayers[1],numLayers[2]);
500
      }
501

  
502
    return mNumVariants;
503
    }
504

  
505
///////////////////////////////////////////////////////////////////////////////////////////////////
506

  
507
  public int getCubitVariant(int cubit, int[] numLayers)
508
    {
509
    return mCubitVariantMap[cubit];
510
    }
511

  
512
///////////////////////////////////////////////////////////////////////////////////////////////////
513

  
514
  public float[][] getCuts(int[] numLayers)
515
    {
516
    if( mCuts==null )
517
      {
518
      mCuts = new float[3][];
519

  
520
      for(int axis=0; axis<3; axis++)
521
        {
522
        int len = numLayers[axis];
523
        float start = (2-len)*0.5f;
524

  
525
        if( len>=2 )
526
          {
527
          mCuts[axis] = new float[len-1];
528
          for(int i=0; i<len-1; i++) mCuts[axis][i] = start+i;
529
          }
530
        }
531
      }
532

  
533
    return mCuts;
534
    }
535

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

  
538
  public boolean[][] getLayerRotatable(int[] numLayers)
539
    {
540
    int numAxis = ROT_AXIS.length;
541
    boolean[][] layerRotatable = new boolean[numAxis][];
542

  
543
    for(int i=0; i<numAxis; i++)
544
      {
545
      layerRotatable[i] = new boolean[numLayers[i]];
546
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
547
      }
548

  
549
    return layerRotatable;
550
    }
551

  
552
///////////////////////////////////////////////////////////////////////////////////////////////////
553

  
554
  public int getTouchControlType()
555
    {
556
    return TC_CUBOID;
557
    }
558

  
559
///////////////////////////////////////////////////////////////////////////////////////////////////
560

  
561
  public int getTouchControlSplit()
562
    {
563
    return TYPE_NOT_SPLIT;
564
    }
565

  
566
///////////////////////////////////////////////////////////////////////////////////////////////////
567

  
568
  public int[][][] getEnabled()
569
    {
570
    return new int[][][] { {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}} };
571
    }
572

  
573
///////////////////////////////////////////////////////////////////////////////////////////////////
574

  
575
  public float[] getDist3D(int[] numLayers)
576
    {
577
    float x = numLayers[0];
578
    float y = numLayers[1];
579
    float z = numLayers[2];
580
    float a = (x+y+z)/1.5f;
581

  
582
    return new float[] {x/a,x/a,y/a,y/a,z/a,z/a};
583
    }
584

  
585
///////////////////////////////////////////////////////////////////////////////////////////////////
586

  
587
  public Static3D[] getFaceAxis()
588
    {
589
    return TouchControlHexahedron.FACE_AXIS;
590
    }
591

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

  
594
  public float getStickerRadius()
595
    {
596
    return 0.10f;
597
    }
598

  
599
///////////////////////////////////////////////////////////////////////////////////////////////////
600

  
601
  public float getStickerStroke()
602
    {
603
    return isInIconMode() ? 0.16f : 0.08f;
604
    }
605

  
606
///////////////////////////////////////////////////////////////////////////////////////////////////
607

  
608
  public float[][] getStickerAngles()
609
    {
610
    return null;
611
    }
612

  
613
///////////////////////////////////////////////////////////////////////////////////////////////////
614
// PUBLIC API
615

  
616
  public Static3D[] getRotationAxis()
617
    {
618
    return ROT_AXIS;
619
    }
620

  
621
///////////////////////////////////////////////////////////////////////////////////////////////////
622

  
623
  public int[][] getBasicAngles()
624
    {
625
     if( mBasicAngle==null )
626
      {
627
      int[] num = getNumLayers();
628
      int numX = num[0];
629
      int numY = num[1];
630
      int numZ = num[2];
631

  
632
      int x = numY==numZ ? 4 : 2;
633
      int y = numX==numZ ? 4 : 2;
634
      int z = numX==numY ? 4 : 2;
635

  
636
      int[] tmpX = new int[numX];
637
      for(int i=0; i<numX; i++) tmpX[i] = x;
638
      int[] tmpY = new int[numY];
639
      for(int i=0; i<numY; i++) tmpY[i] = y;
640
      int[] tmpZ = new int[numZ];
641
      for(int i=0; i<numZ; i++) tmpZ[i] = z;
642

  
643
      mBasicAngle = new int[][] { tmpX,tmpY,tmpZ };
644
      }
645

  
646
    return mBasicAngle;
647
    }
648

  
649
///////////////////////////////////////////////////////////////////////////////////////////////////
650

  
651
  float[][] getPositions()
652
    {
653
    if( mPosition==null ) mPosition = getInitData().getPos();
654
    return mPosition;
655
    }
656
}
src/main/java/org/distorted/objectlib/objects/TwistyBandagedCuboid.java
9 9

  
10 10
package org.distorted.objectlib.objects;
11 11

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

  
15 12
import java.io.InputStream;
16 13

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

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

  
33 22
///////////////////////////////////////////////////////////////////////////////////////////////////
34 23

  
35
public class TwistyBandagedCuboid extends ShapeHexahedron
24
public class TwistyBandagedCuboid extends TwistyBandagedAbstract
36 25
{
37 26
  private static final String OBJECT_NAME = "LOCAL_BANDAGED";
38 27

  
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 28
  public static final float[][] POS_1 = new float[][]
64 29
        {
65 30
          {-1.0f, -1.0f, +0.0f,
......
155 120
          { 1.0f, -1.0f, -1.0f,  1.0f,  0.0f, -1.0f}
156 121
        };
157 122

  
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
  private ObjectShape[] mTmpShapes;
167
  private int mNumVariants;
168

  
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170

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

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

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

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

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

  
200
    if( x+y+z>=2 ) return 0;
201

  
202
    if( x==1 ) return 1;
203
    if( y==1 ) return 4;
204
    if( z==1 ) return 7;
205

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

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

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

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

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

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

  
253
      int numInternal = numTotal - numExternal;
254

  
255
      mSolvedQuatsAbstract = new int[numInternal+1][];
256
      mSolvedQuatsAbstract[0] = new int[numExternal+1];
257
      mSolvedQuatsAbstract[0][0] = numExternal;
258

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

  
269
      int pointerExternal = 1;
270
      int pointerInternal = 1;
271

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

  
279
    return mSolvedQuatsAbstract;
280
    }
281

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

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

  
292 123
///////////////////////////////////////////////////////////////////////////////////////////////////
293 124

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

  
300
///////////////////////////////////////////////////////////////////////////////////////////////////
301

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

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

  
338
               float dX = x4-x3;
339
               float dY = y4-y3;
340
               float dZ = z4-z3;
341

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

  
351
                 return CUBIT_222;
352
                 }
353

  
354
      default: return CUBIT_OTH;
355
      }
356
    }
357

  
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359

  
360
  private int getQuatIndex(int cubit)
125
  public static int getType(String shortName, String longName)
361 126
    {
362
    float[][] positions = getPositions();
363
    int len = positions.length;
364

  
365
    if( cubit>=0 && cubit<len )
366
      {
367
      float[] pos = positions[cubit];
368
      int type = getType(pos);
127
    if( shortName.equals(ObjectType.BAN1_3.name()) ||
128
        shortName.equals(ObjectType.BAN2_3.name()) ||
129
        shortName.equals(ObjectType.BAN3_3.name()) ||
130
        shortName.equals(ObjectType.BAN4_3.name())  ) return 2;
369 131

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

  
382 134
    return 0;
383 135
    }
384 136

  
385 137
///////////////////////////////////////////////////////////////////////////////////////////////////
386 138

  
387
  private void produceTmpShape(int variant)
139
  public TwistyBandagedCuboid(InitData data, int meshState, int iconMode, Static4D quat, Static3D move, float scale, InputStream stream)
388 140
    {
389
    float[][] positions = getPositions();
390
    int cubit,numCubits = positions.length;
391

  
392
    for(cubit=0; cubit<numCubits; cubit++)
393
      {
394
      if( mCubitVariantMap[cubit]==variant ) break;
395
      }
396

  
397
    if( cubit>=numCubits )
398
      {
399
      android.util.Log.e("D", "unknown variant: "+variant);
400
      }
401
    else
402
      {
403
      FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
404
      mTmpShapes[variant] = factory.createIrregularShape(variant,positions[cubit]);
405
      }
141
    super(data, meshState, iconMode, (data.getNumLayers()[0]+data.getNumLayers()[1]+data.getNumLayers()[2])/3.0f, quat, move, scale, stream);
406 142
    }
407 143

  
408 144
///////////////////////////////////////////////////////////////////////////////////////////////////
409 145

  
410
  private float[][] getVertices(int variant)
146
  float[][] getVertices(int variant)
411 147
    {
412
    int type,numTypes = mDims.length;
413
    for(type=0; type<numTypes; type++) if( mTypeVariantMap[type]==variant ) break;
148
    int[] dim = getDim(variant);
414 149

  
415
    if( type<numTypes )
150
    if( dim!=null )
416 151
      {
417
      int X = mDims[type][0];
418
      int Y = mDims[type][1];
419
      int Z = mDims[type][2];
152
      int X = dim[0];
153
      int Y = dim[1];
154
      int Z = dim[2];
420 155

  
421 156
      return new float[][]
422 157
        {
......
436 171
    return mTmpShapes[variant].getVertices();
437 172
    }
438 173

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

  
441
  public ObjectShape getObjectShape(int variant)
442
    {
443
    int type,numTypes = mDims.length;
444
    for(type=0; type<numTypes; type++) if( mTypeVariantMap[type]==variant ) break;
445

  
446
    if( type<numTypes )
447
      {
448
      int[][] indices =
449
        {
450
          {2,3,1,0},
451
          {7,6,4,5},
452
          {4,0,1,5},
453
          {7,3,2,6},
454
          {6,2,0,4},
455
          {3,7,5,1},
456
        };
457

  
458
      return new ObjectShape( getVertices(variant), indices);
459
      }
460

  
461
    if( mTmpShapes==null ) mTmpShapes = new ObjectShape[mNumVariants];
462
    if( mTmpShapes[variant]==null )produceTmpShape(variant);
463
    return mTmpShapes[variant];
464
    }
465

  
466
///////////////////////////////////////////////////////////////////////////////////////////////////
467

  
468
  public ObjectFaceShape getObjectFaceShape(int variant)
469
    {
470
    int[] numLayers = getNumLayers();
471
    int size = (numLayers[0]+numLayers[1]+numLayers[2])/3;
472
    int type,numTypes = mDims.length;
473
    for(type=0; type<numTypes; type++) if( mTypeVariantMap[type]==variant ) break;
474

  
475
    if( type<numTypes )
476
      {
477
      int X = mDims[type][0];
478
      int Y = mDims[type][1];
479
      int Z = mDims[type][2];
480

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

  
484
      int maxXY = Math.max(X,Y);
485
      int maxXZ = Math.max(X,Z);
486
      int maxYZ = Math.max(Y,Z);
487

  
488
      int angle = 45;
489
      float R = 0.25f;
490
      float S = 0.50f;
491
      float N = size<=4 ? 5 : size<=5 ? 4 : 3;
492

  
493
      float[][] bands =
494
        {
495
          {height/maxYZ,angle,R,S,N,0,0},
496
          {height/maxXZ,angle,R,S,N,0,0},
497
          {height/maxXY,angle,R,S,N,0,0}
498
        };
499

  
500
      return new ObjectFaceShape(bands,bandIndices,null);
501
      }
502

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

  
507
///////////////////////////////////////////////////////////////////////////////////////////////////
508

  
509
  public ObjectVertexEffects getVertexEffects(int variant)
510
    {
511
    int[] numLayers = getNumLayers();
512
    int size = (numLayers[0]+numLayers[1]+numLayers[2])/3;
513
    boolean round = (DistortedLibrary.fastCompilationTF() && size<=5 && !isInIconMode());
514

  
515
    int type,numTypes = mDims.length;
516
    for(type=0; type<numTypes; type++) if( mTypeVariantMap[type]==variant ) break;
517

  
518
    if( type<numTypes )
519
      {
520
      float[][] vertices = getVertices(variant);
521
      float strength = -0.04f;
522

  
523
      float[][] variables =
524
        {
525
          { 0, strength*vertices[0][0], strength*vertices[0][1], strength*vertices[0][2], 1  },
526
          { 0, strength*vertices[1][0], strength*vertices[1][1], strength*vertices[1][2], 1  },
527
          { 0, strength*vertices[2][0], strength*vertices[2][1], strength*vertices[2][2], 1  },
528
          { 0, strength*vertices[3][0], strength*vertices[3][1], strength*vertices[3][2], 1  },
529
          { 0, strength*vertices[4][0], strength*vertices[4][1], strength*vertices[4][2], 1  },
530
          { 0, strength*vertices[5][0], strength*vertices[5][1], strength*vertices[5][2], 1  },
531
          { 0, strength*vertices[6][0], strength*vertices[6][1], strength*vertices[6][2], 1  },
532
          { 0, strength*vertices[7][0], strength*vertices[7][1], strength*vertices[7][2], 1  },
533
        };
534

  
535
      String name = EffectName.DEFORM.name();
536
      float[] reg = {0,0,0,0.15f};
537

  
538
      String[] names = {name,name,name,name,name,name,name,name};
539
      float[][] regions = {reg,reg,reg,reg,reg,reg,reg,reg};
540
      boolean[] uses = {round,round,round,round,round,round,round,round};
541

  
542
      return new ObjectVertexEffects(names,variables,vertices,regions,uses);
543
      }
544

  
545
    FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
546
    return factory.createVertexEffects(variant,round);
547
    }
548

  
549
///////////////////////////////////////////////////////////////////////////////////////////////////
550

  
551
  public float[][] getCubitPositions(int[] numLayers)
552
    {
553
    return getPositions();
554
    }
555

  
556
///////////////////////////////////////////////////////////////////////////////////////////////////
557

  
558
  public Static4D getCubitQuats(int cubit, int[] numLayers)
559
    {
560
    if( mInitQuats ==null )
561
      {
562
      mInitQuats = new Static4D[]
563
        {
564
        new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),  // NULL
565
        new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),  // X
566
        new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),  // Y
567
        new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),  // Z
568
        new Static4D( -0.5f,  +0.5f,  -0.5f,  +0.5f),  // ZX
569
        new Static4D( +0.5f,  +0.5f,  +0.5f,  -0.5f),  // YX
570
        };
571
      }
572

  
573
    return mInitQuats[getQuatIndex(cubit)];
574
    }
575

  
576
///////////////////////////////////////////////////////////////////////////////////////////////////
577

  
578
  public int getNumCubitVariants(int[] numLayers)
579
    {
580
    if( mNumVariants==0 )
581
      {
582
      float[][] positions = getPositions();
583
      boolean C111=false;
584
      boolean C211=false;
585
      boolean C311=false;
586
      boolean C221=false;
587
      boolean C222=false;
588

  
589
      int numCubits = positions.length;
590
      mCubitVariantMap = new int[numCubits];
591

  
592
      int numTypes = mDims.length;
593
      mTypeVariantMap = new int[numTypes];
594
      for(int i=0; i<numTypes; i++) mTypeVariantMap[i] = -1;
595

  
596
      for (int cubit=0; cubit<numCubits; cubit++)
597
        {
598
        int type = getType(positions[cubit]);
599

  
600
        switch (type)
601
          {
602
          case CUBIT_111: if (!C111) { C111 = true; mTypeVariantMap[CUBIT_111]=mNumVariants++; }
603
                          mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_111];
604
                          break;
605
          case CUBIT_211: if (!C211) { C211 = true; mTypeVariantMap[CUBIT_211]=mNumVariants++; }
606
                          mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_211];
607
                          break;
608
          case CUBIT_311: if (!C311) { C311 = true; mTypeVariantMap[CUBIT_311]=mNumVariants++; }
609
                          mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_311];
610
                          break;
611
          case CUBIT_221: if (!C221) { C221 = true; mTypeVariantMap[CUBIT_221]=mNumVariants++; }
612
                          mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_221];
613
                          break;
614
          case CUBIT_222: if (!C222) { C222 = true; mTypeVariantMap[CUBIT_222]=mNumVariants++; }
615
                          mCubitVariantMap[cubit]=mTypeVariantMap[CUBIT_222];
616
                          break;
617
          default       : mCubitVariantMap[cubit] = mNumVariants++;
618
          }
619
        }
620

  
621
      FactoryBandagedCubit factory = FactoryBandagedCubit.getInstance();
622
      factory.prepare(mNumVariants,numLayers[0],numLayers[1],numLayers[2]);
623
      }
624

  
625
    return mNumVariants;
626
    }
627

  
628
///////////////////////////////////////////////////////////////////////////////////////////////////
629

  
630
  public int getCubitVariant(int cubit, int[] numLayers)
631
    {
632
    return mCubitVariantMap[cubit];
633
    }
634

  
635
///////////////////////////////////////////////////////////////////////////////////////////////////
636

  
637
  public float[][] getCuts(int[] numLayers)
638
    {
639
    if( mCuts==null )
640
      {
641
      mCuts = new float[3][];
642

  
643
      for(int axis=0; axis<3; axis++)
644
        {
645
        int len = numLayers[axis];
646
        float start = (2-len)*0.5f;
647

  
648
        if( len>=2 )
649
          {
650
          mCuts[axis] = new float[len-1];
651
          for(int i=0; i<len-1; i++) mCuts[axis][i] = start+i;
652
          }
653
        }
654
      }
655

  
656
    return mCuts;
657
    }
658

  
659
///////////////////////////////////////////////////////////////////////////////////////////////////
660

  
661
  public boolean[][] getLayerRotatable(int[] numLayers)
662
    {
663
    int numAxis = ROT_AXIS.length;
664
    boolean[][] layerRotatable = new boolean[numAxis][];
665

  
666
    for(int i=0; i<numAxis; i++)
667
      {
668
      layerRotatable[i] = new boolean[numLayers[i]];
669
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
670
      }
671

  
672
    return layerRotatable;
673
    }
674

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

  
677
  public int getTouchControlType()
678
    {
679
    return TC_CUBOID;
680
    }
681

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

  
684
  public int getTouchControlSplit()
685
    {
686
    return TYPE_NOT_SPLIT;
687
    }
688

  
689
///////////////////////////////////////////////////////////////////////////////////////////////////
690

  
691
  public int[][][] getEnabled()
692
    {
693
    return new int[][][] { {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}} };
694
    }
695

  
696
///////////////////////////////////////////////////////////////////////////////////////////////////
697

  
698
  public float[] getDist3D(int[] numLayers)
699
    {
700
    float x = numLayers[0];
701
    float y = numLayers[1];
702
    float z = numLayers[2];
703
    float a = (x+y+z)/1.5f;
704

  
705
    return new float[] {x/a,x/a,y/a,y/a,z/a,z/a};
706
    }
707

  
708
///////////////////////////////////////////////////////////////////////////////////////////////////
709

  
710
  public Static3D[] getFaceAxis()
711
    {
712
    return TouchControlHexahedron.FACE_AXIS;
713
    }
714

  
715
///////////////////////////////////////////////////////////////////////////////////////////////////
716

  
717
  public float getStickerRadius()
718
    {
719
    return 0.10f;
720
    }
721

  
722
///////////////////////////////////////////////////////////////////////////////////////////////////
723

  
724
  public float getStickerStroke()
725
    {
726
    return isInIconMode() ? 0.16f : 0.08f;
727
    }
728

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

  
731
  public float[][] getStickerAngles()
732
    {
733
    return null;
734
    }
735

  
736 174
///////////////////////////////////////////////////////////////////////////////////////////////////
737 175
// PUBLIC API
738 176

  
739
  public Static3D[] getRotationAxis()
740
    {
741
    return ROT_AXIS;
742
    }
743

  
744
///////////////////////////////////////////////////////////////////////////////////////////////////
745

  
746
  public int[][] getBasicAngles()
747
    {
748
     if( mBasicAngle==null )
749
      {
750
      int[] num = getNumLayers();
751
      int numX = num[0];
752
      int numY = num[1];
753
      int numZ = num[2];
754

  
755
      int x = numY==numZ ? 4 : 2;
756
      int y = numX==numZ ? 4 : 2;
757
      int z = numX==numY ? 4 : 2;
758

  
759
      int[] tmpX = new int[numX];
760
      for(int i=0; i<numX; i++) tmpX[i] = x;
761
      int[] tmpY = new int[numY];
762
      for(int i=0; i<numY; i++) tmpY[i] = y;
763
      int[] tmpZ = new int[numZ];
764
      for(int i=0; i<numZ; i++) tmpZ[i] = z;
765

  
766
      mBasicAngle = new int[][] { tmpX,tmpY,tmpZ };
767
      }
768

  
769
    return mBasicAngle;
770
    }
771

  
772
///////////////////////////////////////////////////////////////////////////////////////////////////
773

  
774
  float[][] getPositions()
775
    {
776
    if( mPosition==null ) mPosition = getInitData().getPos();
777
    return mPosition;
778
    }
779

  
780
///////////////////////////////////////////////////////////////////////////////////////////////////
781

  
782
  public static int getType(String shortName, String longName)
783
    {
784
    if( shortName.equals(ObjectType.BAN1_3.name()) ||
785
        shortName.equals(ObjectType.BAN2_3.name()) ||
786
        shortName.equals(ObjectType.BAN3_3.name()) ||
787
        shortName.equals(ObjectType.BAN4_3.name())  ) return 2;
788

  
789
    if( longName.equals(OBJECT_NAME) ) return 1;
790

  
791
    return 0;
792
    }
793

  
794
///////////////////////////////////////////////////////////////////////////////////////////////////
795
// PUBLIC APi
796

  
797 177
  public String getShortName()
798 178
    {
799 179
    if( mPosition==null ) mPosition = getInitData().getPos();
src/main/java/org/distorted/objectlib/objects/TwistyCamouflage.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 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 org.distorted.library.type.Static3D;
13
import org.distorted.library.type.Static4D;
14
import org.distorted.objectlib.helpers.ObjectSignature;
15
import org.distorted.objectlib.main.InitData;
16
import org.distorted.objectlib.main.ObjectType;
17

  
18
import java.io.InputStream;
19

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

  
22
public class TwistyCamouflage extends TwistyBandagedAbstract
23
{
24
  public static final float[][] CAM_333 = new float[][]
25
    {
26
    // TODO: define centers of the Camouflage 3x3x3 cube.
27
    };
28

  
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30

  
31
  public TwistyCamouflage(InitData data, int meshState, int iconMode, Static4D quat, Static3D move, float scale, InputStream stream)
32
    {
33
    super(data, meshState, iconMode, (data.getNumLayers()[0]+data.getNumLayers()[1]+data.getNumLayers()[2])/3.0f, quat, move, scale, stream);
34
    }
35

  
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37

  
38
  float[][] getVertices(int variant)
39
    {
40
    if( mPosition==null ) mPosition = getInitData().getPos();
41

  
42
    if( mPosition==CAM_333 )
43
      {
44
      // TODO: vertices of the Camouflage 3x3x3
45
      }
46

  
47
    return null;
48
    }
49

  
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51
// PUBLIC API
52

  
53
  public String getShortName()
54
    {
55
    if( mPosition==null ) mPosition = getInitData().getPos();
56

  
57
    if( mPosition==CAM_333 ) return ObjectType.CA_333.name();
58

  
59
    return null;
60
    }
61

  
62
///////////////////////////////////////////////////////////////////////////////////////////////////
63

  
64
  public ObjectSignature getSignature()
65
    {
66
    if( mSignature==null )
67
      {
68
      if( mPosition==null ) mPosition = getInitData().getPos();
69
      if( mPosition==CAM_333 ) mSignature = new ObjectSignature(ObjectType.CA_333);
70
      }
71
    return mSignature;
72
    }
73

  
74
///////////////////////////////////////////////////////////////////////////////////////////////////
75

  
76
  public String getObjectName()
77
    {
78
    int[] nL = getNumLayers();
79
    return "Camouflage "+nL[0]+"x"+nL[1]+"x"+nL[2];
80
    }
81

  
82
///////////////////////////////////////////////////////////////////////////////////////////////////
83

  
84
  public String getInventor()
85
    {
86
    return "Guan Yang";
87
    }
88

  
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90

  
91
  public int getYearOfInvention()
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff