Project

General

Profile

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

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

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objectlib.objects;
21

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

    
25
import java.io.InputStream;
26

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

    
30
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
31
import org.distorted.objectlib.helpers.ObjectShape;
32
import org.distorted.objectlib.helpers.ObjectSticker;
33
import org.distorted.objectlib.helpers.ScrambleState;
34
import org.distorted.objectlib.main.ObjectControl;
35
import org.distorted.objectlib.main.ShapeHexahedron;
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

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

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

    
58
  //private static final int NUM_STICKERS = 4;
59

    
60
  private int[] mDimPointers;
61
  private int[] mBasicAngle;
62
  private Static4D[] mQuats;
63
  private ObjectSticker[] mStickers;
64
  private Static4D[] mInitQuats;
65
  private int[][] mAxisMap;
66
  private int[][] mFaceMap;
67
  private float[][] mCuts;
68
  ScrambleState[] mStates;
69
  float[][] POSITIONS;
70
  int[] QUAT_INDICES;
71

    
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73

    
74
  TwistyBandagedAbstract(int[] numL, int meshState, Static4D quat, Static3D move, float scale, InputStream stream)
75
    {
76
    super(numL, meshState, numL[0], quat, move, scale, stream);
77
    }
78

    
79
///////////////////////////////////////////////////////////////////////////////////////////////////
80

    
81
  abstract float[][] getPositions();
82
  abstract int[] getQuatIndices();
83

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

    
86
  private void initializeQuats()
87
    {
88
    mQuats = new Static4D[]
89
         {
90
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
91
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
92
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
93
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
94

    
95
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
96
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
97
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
98
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
99
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
100
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
101
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
102
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
103
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
104
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
105
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
106
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
107

    
108
         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
109
         new Static4D(  0.5f,   0.5f,  -0.5f,   0.5f),
110
         new Static4D(  0.5f,   0.5f,  -0.5f,  -0.5f),
111
         new Static4D(  0.5f,  -0.5f,   0.5f,  -0.5f),
112
         new Static4D( -0.5f,  -0.5f,  -0.5f,   0.5f),
113
         new Static4D( -0.5f,   0.5f,  -0.5f,  -0.5f),
114
         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
115
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
116
         };
117
    }
118

    
119
///////////////////////////////////////////////////////////////////////////////////////////////////
120

    
121
  public int[] getSolvedQuats(int cubit, int[] numLayers)
122
    {
123
    if( mQuats==null ) initializeQuats();
124
    int status = retCubitSolvedStatus(cubit,numLayers);
125
    return status<0 ? null : buildSolvedQuats(TouchControlHexahedron.FACE_AXIS[status],mQuats);
126
    }
127

    
128
///////////////////////////////////////////////////////////////////////////////////////////////////
129
/*
130
  int getNumCubits()
131
    {
132
    return getPositions().length;
133
    }
134
*/
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

    
137
  private float[] getCubitPosition(int cubit)
138
    {
139
    float[][] pos = getPositions();
140

    
141
    return ( cubit>=0 && cubit< pos.length ) ? pos[cubit] : null;
142
    }
143

    
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145

    
146
  private int getQuatIndex(int cubit)
147
    {
148
    int[] indices = getQuatIndices();
149
    return ( cubit>=0 && cubit< indices.length ) ? indices[cubit] : 0;
150
    }
151

    
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153

    
154
  public ObjectShape getObjectShape(int variant)
155
    {
156
    final int[][] vert_indices =
157
      {
158
        {2,3,1,0},
159
        {7,6,4,5},
160
        {4,0,1,5},
161
        {7,3,2,6},
162
        {6,2,0,4},
163
        {3,7,5,1},
164
      };
165

    
166
    float defHeight = 0.048f;
167
    int[] bandIndices = new int[] { 0,0,1,1,2,2 };
168
    float[][] corners = new float[][] { {0.04f,0.15f} };
169
    int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
170
    int[] centerIndices = new int[] { 0,1,2,3,4,5,6,7 };
171

    
172
    int pointer = mDimPointers[variant];
173
    int X = mDims[pointer][0];
174
    int Y = mDims[pointer][1];
175
    int Z = mDims[pointer][2];
176

    
177
    int maxXY = Math.max(X,Y);
178
    int maxXZ = Math.max(X,Z);
179
    int maxYZ = Math.max(Y,Z);
180

    
181
    float[][] vertices =
182
      {
183
        {+0.5f*X,+0.5f*Y,+0.5f*Z},
184
        {+0.5f*X,+0.5f*Y,-0.5f*Z},
185
        {+0.5f*X,-0.5f*Y,+0.5f*Z},
186
        {+0.5f*X,-0.5f*Y,-0.5f*Z},
187
        {-0.5f*X,+0.5f*Y,+0.5f*Z},
188
        {-0.5f*X,+0.5f*Y,-0.5f*Z},
189
        {-0.5f*X,-0.5f*Y,+0.5f*Z},
190
        {-0.5f*X,-0.5f*Y,-0.5f*Z}
191
      };
192

    
193
    float[][] bands= new float[][]
194
      {
195
        {defHeight/maxYZ,65,0.25f,0.5f,5,1,2},
196
        {defHeight/maxXZ,65,0.25f,0.5f,5,1,2},
197
        {defHeight/maxXY,65,0.25f,0.5f,5,1,2}
198
      };
199

    
200
    float[][] centers = new float[][]
201
      {
202
        {+0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
203
        {+0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
204
        {+0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
205
        {+0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)},
206
        {-0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
207
        {-0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
208
        {-0.5f*(X-1),-0.5f*(Y-1),+0.5f*(Z-1)},
209
        {-0.5f*(X-1),-0.5f*(Y-1),-0.5f*(Z-1)}
210
      };
211

    
212
    return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null, 6);
213
    }
214

    
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216

    
217
  public Static4D getQuat(int cubit, int[] numLayers)
218
    {
219
    if( mInitQuats ==null )
220
      {
221
      mInitQuats = new Static4D[]
222
        {
223
        new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),  // NULL
224
        new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),  // X
225
        new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),  // Y
226
        new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),  // Z
227
        new Static4D( -0.5f,  +0.5f,  -0.5f,  +0.5f),  // ZX
228
        new Static4D( +0.5f,  +0.5f,  +0.5f,  -0.5f),  // YX
229
        };
230
      }
231

    
232
    return mInitQuats[getQuatIndex(cubit)];
233
    }
234

    
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236

    
237
  private void assignDim(int[] table, int index, int len)
238
    {
239
    switch(len)
240
      {
241
      case  3: table[index] = 0; break;
242
      case  6: table[index] = 1; break;
243
      case  9: table[index] = 2; break;
244
      case 12: table[index] = 3; break;
245
      case 24: table[index] = 4; break;
246
      default: android.util.Log.e("D", "ERROR in assignDim: "+len);
247
      }
248
    }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
  public int getNumCubitVariants(int[] numLayers)
253
    {
254
    float[][] pos = getPositions();
255
    int len = pos.length;
256
    int ret = 1;
257

    
258
    for(int i=0; i<len; i++ )
259
      if( i>0 && pos[i].length!=pos[i-1].length ) ret++;
260

    
261
    mDimPointers = new int[ret];
262
    int index=0;
263

    
264
    for(int i=0; i<len; i++ )
265
      {
266
      if( i==0 || pos[i].length!=pos[i-1].length )
267
        {
268
        assignDim(mDimPointers,index,pos[i].length);
269
        index++;
270
        }
271
      }
272

    
273
    return ret;
274
    }
275

    
276
///////////////////////////////////////////////////////////////////////////////////////////////////
277

    
278
  public int getCubitVariant(int cubit, int[] numLayers)
279
    {
280
    float[][] pos = getPositions();
281
    int len = pos.length;
282

    
283
    if( cubit>=0 && cubit<len )
284
      {
285
      int ret = 0;
286

    
287
      for(int i=1; i<=cubit; i++ )
288
        if( i>0 && pos[i].length!=pos[i-1].length ) ret++;
289

    
290
      return ret;
291
      }
292

    
293
    return 0;
294
    }
295

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

    
298
  public ObjectSticker retSticker(int sticker)
299
    {
300
    if( mStickers==null )
301
      {
302
      int numStickers = mStickerCoords.length;
303
      mStickers = new ObjectSticker[numStickers];
304

    
305
      for(int s=0; s<numStickers; s++)
306
        {
307
        float scale = mStickerScales[s];
308
        float radius = 0.10f / scale;
309
        float stroke = 0.08f / scale;
310
        float[] radii = new float[] {radius,radius,radius,radius};
311
        if( ObjectControl.isInIconMode() ) stroke*=2.0f;
312
        mStickers[s] = new ObjectSticker(mStickerCoords[s],null,radii,stroke);
313
        }
314
      }
315

    
316
    return mStickers[sticker];
317
    }
318

    
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320

    
321
  public float[][] getCubitPositions(int[] numLayers)
322
    {
323
    /*
324
    int numCubits = getNumCubits();
325
    float[][] tmp = new float[numCubits][];
326

    
327
    for(int cubit=0; cubit<numCubits; cubit++)
328
      {
329
      tmp[cubit] = getCubitPosition(cubit);
330
      }
331

    
332
    return tmp;
333

    
334
     */
335

    
336
    return getPositions();
337
    }
338

    
339
///////////////////////////////////////////////////////////////////////////////////////////////////
340

    
341
  public Static4D[] getQuats()
342
    {
343
    if( mQuats==null ) initializeQuats();
344
    return mQuats;
345
    }
346

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

    
349
  public float[][] getCuts(int[] numLayers)
350
    {
351
    int numL = numLayers[0];
352

    
353
    if( numL<2 ) return null;
354

    
355
    if( mCuts==null )
356
      {
357
      mCuts = new float[3][numL-1];
358

    
359
      for(int i=0; i<numL-1; i++)
360
        {
361
        float cut = (2-numL)*0.5f + i;
362
        mCuts[0][i] = cut;
363
        mCuts[1][i] = cut;
364
        mCuts[2][i] = cut;
365
        }
366
      }
367

    
368
    return mCuts;
369
    }
370

    
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

    
373
  public boolean[][] getLayerRotatable(int[] numLayers)
374
    {
375
    int numAxis = ROT_AXIS.length;
376
    boolean[][] layerRotatable = new boolean[numAxis][];
377

    
378
    for(int i=0; i<numAxis; i++)
379
      {
380
      layerRotatable[i] = new boolean[numLayers[i]];
381
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
382
      }
383

    
384
    return layerRotatable;
385
    }
386

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

    
389
  public int getTouchControlType()
390
    {
391
    return TC_HEXAHEDRON;
392
    }
393

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

    
396
  public int getTouchControlSplit()
397
    {
398
    return TYPE_NOT_SPLIT;
399
    }
400

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

    
403
  public int[][][] getEnabled()
404
    {
405
    return new int[][][]
406
      {
407
          {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}},
408
      };
409
    }
410

    
411
///////////////////////////////////////////////////////////////////////////////////////////////////
412

    
413
  public float[] getDist3D(int[] numLayers)
414
    {
415
    return null;
416
    }
417

    
418
///////////////////////////////////////////////////////////////////////////////////////////////////
419

    
420
  public int getSolvedFunctionIndex()
421
    {
422
    return 0;
423
    }
424

    
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426

    
427
  public int getNumCubitFaces()
428
    {
429
    return 6;
430
    }
431

    
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433

    
434
  private int retStickerIndex(int horzSize, int vertSize)
435
    {
436
    switch(horzSize)
437
      {
438
      case 1: return 0;
439
      case 2: return vertSize==1 ? 1:3;
440
      case 3: return 2;
441
      }
442

    
443
    return 0;
444
    }
445

    
446
///////////////////////////////////////////////////////////////////////////////////////////////////
447

    
448
  public int getVariantFaceColor(int variant, int face, int[] numLayers)
449
    {
450
    return mStickerVariants[variant][face];
451
    /*
452
    int[] dim = mDimensions[variant];
453

    
454
    switch(face)
455
      {
456
      case 0: case 1: return retStickerIndex(dim[2],dim[1]);
457
      case 2: case 3: return retStickerIndex(dim[0],dim[2]);
458
      case 4: case 5: return retStickerIndex(dim[0],dim[1]);
459
      }
460

    
461
    return 0;
462

    
463
     */
464
    }
465

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

    
468
  public int getCubitFaceColor(int cubit, int cubitface, int[] numLayers)
469
    {
470
    if( mFaceMap==null )
471
      {
472
      // cubitface=2 when rotated by quatIndex=1 gets moved to position mFaceMap[2][1]
473
      mFaceMap = new int[][]
474
          {
475
              {0,0,5,2,4,2},
476
              {1,1,4,3,5,3},
477
              {2,4,2,1,1,4},
478
              {3,5,3,0,0,5},
479
              {4,3,0,4,3,0},
480
              {5,2,1,5,2,1}
481
          };
482
      }
483

    
484
    if( mAxisMap==null )
485
      {
486
      // axis=1 when rotated by quatIndex=2 gets moved to axis mAxisMap[1][2]
487
      mAxisMap = new int[][] { {0,0,2,1,2,1}, {1,2,1,0,0,2}, {2,1,0,2,1,0} };
488
      }
489

    
490
    int variant    = getCubitVariant(cubit,numLayers);
491
    int pointer    = mDimPointers[variant];
492
    int[] dim      = mDims[pointer];
493
    float[] pos    = getCubitPosition(cubit);
494
    int quatIndex  = getQuatIndex(cubit);
495
    int face       = mFaceMap[cubitface][quatIndex];
496
    int multiplier = (face%2)==0 ? 1:-1;
497
    int posIndex   = face/2;
498
    int dimIndex   = mAxisMap[posIndex][quatIndex];
499

    
500
    float position = 0.0f;
501
    int len = pos.length/3;
502
    for(int i=0; i<len; i++) position += pos[3*i+posIndex];
503
    position /= len;
504

    
505
    boolean reaches  = multiplier*position + dim[dimIndex]*0.5f > (numLayers[0]-1)*0.5f;
506

    
507
    return reaches ? face : -1;
508
    }
509

    
510
///////////////////////////////////////////////////////////////////////////////////////////////////
511
// PUBLIC API
512

    
513
  public Static3D[] getRotationAxis()
514
    {
515
    return ROT_AXIS;
516
    }
517

    
518
///////////////////////////////////////////////////////////////////////////////////////////////////
519

    
520
  public int[] getBasicAngle()
521
    {
522
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
523
    return mBasicAngle;
524
    }
525
}
(3-3/26)