Project

General

Profile

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

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

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[][] mDimensions = 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[] mBasicAngle;
61
  private Static4D[] mQuats;
62
  private ObjectSticker[] mStickers;
63
  private Static4D[] mInitQuats;
64
  private int[][] mAxisMap;
65
  private int[][] mFaceMap;
66
  private float[][] mCuts;
67
  ScrambleState[] mStates;
68
  float[][] POSITIONS;
69
  int[] QUAT_INDICES;
70

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

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

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

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

    
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84

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

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

    
107
         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
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
         };
116
    }
117

    
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119

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

    
127
///////////////////////////////////////////////////////////////////////////////////////////////////
128

    
129
  int getNumCubits()
130
    {
131
    return getPositions().length;
132
    }
133

    
134
///////////////////////////////////////////////////////////////////////////////////////////////////
135

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

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

    
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144

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

    
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152

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

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

    
171
    int X = mDimensions[variant][0];
172
    int Y = mDimensions[variant][1];
173
    int Z = mDimensions[variant][2];
174

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

    
179
    float[][] vertices =
180
      {
181
        {+0.5f*X,+0.5f*Y,+0.5f*Z},
182
        {+0.5f*X,+0.5f*Y,-0.5f*Z},
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
      };
190

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

    
198
    float[][] centers = new float[][]
199
      {
200
        {+0.5f*(X-1),+0.5f*(Y-1),+0.5f*(Z-1)},
201
        {+0.5f*(X-1),+0.5f*(Y-1),-0.5f*(Z-1)},
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
      };
209

    
210
    return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
211
    }
212

    
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214

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

    
230
    return mInitQuats[getQuatIndex(cubit)];
231
    }
232

    
233
///////////////////////////////////////////////////////////////////////////////////////////////////
234

    
235
  public int getNumCubitVariants(int[] numLayers)
236
    {
237
    return mDimensions.length;
238
    }
239

    
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241

    
242
  public int getCubitVariant(int cubit, int[] numLayers)
243
    {
244
    float[][] pos = getPositions();
245

    
246
    if( cubit>=0 && cubit<pos.length )
247
      {
248
      int numPoints = pos[cubit].length/3;
249
      return numPoints==8 ? 4 : numPoints-1;
250
      }
251

    
252
    return 1;
253
    }
254

    
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256

    
257
  public ObjectSticker retSticker(int sticker)
258
    {
259
    if( mStickers==null )
260
      {
261
      mStickers = new ObjectSticker[NUM_STICKERS];
262

    
263
      int[][] stickerDimensions = new int[][]
264
        {
265
         {1,1},  // dimensions of the faces of
266
         {2,1},  // the cuboids defined in mDimensions
267
         {3,1},
268
         {2,2}
269
        };
270

    
271
      for(int s=0; s<NUM_STICKERS; s++)
272
        {
273
        float X = stickerDimensions[s][0];
274
        float Y = stickerDimensions[s][1];
275
        float MAX = Math.max(X,Y);
276
        X /= (2*MAX);
277
        Y /= (2*MAX);
278

    
279
        float radius = 0.10f / MAX;
280
        float stroke = 0.08f / MAX;
281
        float[] coords = { -X,-Y, +X,-Y, +X,+Y, -X,+Y};
282
        float[] radii = new float[] {radius,radius,radius,radius};
283

    
284
        if( ObjectControl.isInIconMode() )
285
          {
286
          stroke*=2.0f;
287
          }
288

    
289
        mStickers[s] = new ObjectSticker(coords,null,radii,stroke);
290
        }
291
      }
292

    
293
    return mStickers[sticker];
294
    }
295

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

    
298
  public float[][] getCubitPositions(int[] numLayers)
299
    {
300
    int numCubits = getNumCubits();
301
    float[][] tmp = new float[numCubits][];
302

    
303
    for(int cubit=0; cubit<numCubits; cubit++)
304
      {
305
      tmp[cubit] = getCubitPosition(cubit);
306
      }
307

    
308
    return tmp;
309
    }
310

    
311
///////////////////////////////////////////////////////////////////////////////////////////////////
312

    
313
  public Static4D[] getQuats()
314
    {
315
    if( mQuats==null ) initializeQuats();
316
    return mQuats;
317
    }
318

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

    
321
  public float[][] getCuts(int[] numLayers)
322
    {
323
    int numL = numLayers[0];
324

    
325
    if( numL<2 ) return null;
326

    
327
    if( mCuts==null )
328
      {
329
      mCuts = new float[3][numL-1];
330

    
331
      for(int i=0; i<numL-1; i++)
332
        {
333
        float cut = (2-numL)*0.5f + i;
334
        mCuts[0][i] = cut;
335
        mCuts[1][i] = cut;
336
        mCuts[2][i] = cut;
337
        }
338
      }
339

    
340
    return mCuts;
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

    
345
  public boolean[][] getLayerRotatable(int[] numLayers)
346
    {
347
    int numAxis = ROT_AXIS.length;
348
    boolean[][] layerRotatable = new boolean[numAxis][];
349

    
350
    for(int i=0; i<numAxis; i++)
351
      {
352
      layerRotatable[i] = new boolean[numLayers[i]];
353
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
354
      }
355

    
356
    return layerRotatable;
357
    }
358

    
359
///////////////////////////////////////////////////////////////////////////////////////////////////
360

    
361
  public int getMovementType()
362
    {
363
    return TC_HEXAHEDRON;
364
    }
365

    
366
///////////////////////////////////////////////////////////////////////////////////////////////////
367

    
368
  public int getMovementSplit()
369
    {
370
    return TYPE_NOT_SPLIT;
371
    }
372

    
373
///////////////////////////////////////////////////////////////////////////////////////////////////
374

    
375
  public int[][][] getEnabled()
376
    {
377
    return new int[][][]
378
      {
379
          {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}},
380
      };
381
    }
382

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

    
385
  public float[] getDist3D(int[] numLayers)
386
    {
387
    return null;
388
    }
389

    
390
///////////////////////////////////////////////////////////////////////////////////////////////////
391

    
392
  public int getSolvedFunctionIndex()
393
    {
394
    return 0;
395
    }
396

    
397
///////////////////////////////////////////////////////////////////////////////////////////////////
398

    
399
  public int getNumStickerTypes(int[] numLayers)
400
    {
401
    return NUM_STICKERS;
402
    }
403

    
404
///////////////////////////////////////////////////////////////////////////////////////////////////
405

    
406
  public int getNumCubitFaces()
407
    {
408
    return 6;
409
    }
410

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

    
413
  private int retStickerIndex(int horzSize, int vertSize)
414
    {
415
    switch(horzSize)
416
      {
417
      case 1: return 0;
418
      case 2: return vertSize==1 ? 1:3;
419
      case 3: return 2;
420
      }
421

    
422
    return 0;
423
    }
424

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

    
427
  public int getVariantFaceColor(int variant, int face, int[] numLayers)
428
    {
429
    int[] dim = mDimensions[variant];
430

    
431
    switch(face)
432
      {
433
      case 0: case 1: return retStickerIndex(dim[2],dim[1]);
434
      case 2: case 3: return retStickerIndex(dim[0],dim[2]);
435
      case 4: case 5: return retStickerIndex(dim[0],dim[1]);
436
      }
437

    
438
    return 0;
439
    }
440

    
441
///////////////////////////////////////////////////////////////////////////////////////////////////
442

    
443
  public int getCubitFaceColor(int cubit, int cubitface, int[] numLayers)
444
    {
445
    if( mFaceMap==null )
446
      {
447
      // cubitface=2 when rotated by quatIndex=1 gets moved to position mFaceMap[2][1]
448
      mFaceMap = new int[][]
449
          {
450
              {0,0,5,2,4,2},
451
              {1,1,4,3,5,3},
452
              {2,4,2,1,1,4},
453
              {3,5,3,0,0,5},
454
              {4,3,0,4,3,0},
455
              {5,2,1,5,2,1}
456
          };
457
      }
458

    
459
    if( mAxisMap==null )
460
      {
461
      // axis=1 when rotated by quatIndex=2 gets moved to axis mAxisMap[1][2]
462
      mAxisMap = new int[][] { {0,0,2,1,2,1}, {1,2,1,0,0,2}, {2,1,0,2,1,0} };
463
      }
464

    
465
    int variant    = getCubitVariant(cubit,numLayers);
466
    int[] dim      = mDimensions[variant];
467
    float[] pos    = getCubitPosition(cubit);
468
    int quatIndex  = getQuatIndex(cubit);
469
    int face       = mFaceMap[cubitface][quatIndex];
470
    int multiplier = (face%2)==0 ? 1:-1;
471
    int posIndex   = face/2;
472
    int dimIndex   = mAxisMap[posIndex][quatIndex];
473

    
474
    float position = 0.0f;
475
    int len = pos.length/3;
476
    for(int i=0; i<len; i++) position += pos[3*i+posIndex];
477
    position /= len;
478

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

    
481
    return reaches ? face : -1;
482
    }
483

    
484
///////////////////////////////////////////////////////////////////////////////////////////////////
485
// PUBLIC API
486

    
487
  public Static3D[] getRotationAxis()
488
    {
489
    return ROT_AXIS;
490
    }
491

    
492
///////////////////////////////////////////////////////////////////////////////////////////////////
493

    
494
  public int[] getBasicAngle()
495
    {
496
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 4,4,4 };
497
    return mBasicAngle;
498
    }
499
}
(3-3/25)