Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyMinx.java @ 5d09301e

1 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6 6133be67 Leszek Koltunski
// 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 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10
package org.distorted.objectlib.objects;
11
12 c9c71c3f Leszek Koltunski
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_DODECAHEDRON;
13
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_SPLIT_EDGE;
14
import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.C2;
15
import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.LEN;
16
import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.SIN54;
17 29b82486 Leszek Koltunski
18 82eb152a Leszek Koltunski
import java.io.InputStream;
19 29b82486 Leszek Koltunski
20
import org.distorted.library.type.Static3D;
21
import org.distorted.library.type.Static4D;
22 a8295031 Leszek Koltunski
import org.distorted.objectlib.main.InitData;
23 c9c71c3f Leszek Koltunski
import org.distorted.objectlib.touchcontrol.TouchControlDodecahedron;
24 10b7e306 Leszek Koltunski
import org.distorted.objectlib.scrambling.ScrambleState;
25 386af988 Leszek Koltunski
import org.distorted.objectlib.main.ShapeDodecahedron;
26 29b82486 Leszek Koltunski
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28
29 386af988 Leszek Koltunski
abstract class TwistyMinx extends ShapeDodecahedron
30 29b82486 Leszek Koltunski
{
31
  static final int NUM_CORNERS = 20;
32
  static final int NUM_CENTERS = 12;
33
  static final int NUM_EDGES   = 30;
34
35
  static final float SIN18    = (SQ5-1)/4;
36
  static final float COS18    = (float)(0.25f*Math.sqrt(10.0f+2.0f*SQ5));
37
  static final float COS_HALFD= (float)(Math.sqrt(0.5f-0.1f*SQ5)); // cos(half the dihedral angle)
38
  static final float SIN_HALFD= (float)(Math.sqrt(0.5f+0.1f*SQ5)); // sin(half the dihedral angle)
39
40
  // the six rotation axis of a Minx. Must be normalized.
41
  static final Static3D[] ROT_AXIS = new Static3D[]
42
         {
43
           new Static3D(    C2/LEN, SIN54/LEN,    0      ),
44
           new Static3D(   -C2/LEN, SIN54/LEN,    0      ),
45
           new Static3D( 0        ,    C2/LEN, SIN54/LEN ),
46
           new Static3D( 0        ,   -C2/LEN, SIN54/LEN ),
47
           new Static3D( SIN54/LEN,    0     ,    C2/LEN ),
48
           new Static3D( SIN54/LEN,    0     ,   -C2/LEN )
49
         };
50
51 beee90ab Leszek Koltunski
  private int[][] mBasicAngle;
52 29b82486 Leszek Koltunski
  private float[][] mCuts;
53 e8f5f147 Leszek Koltunski
  float[][] mCenterCoords,mCorners;
54
  int[] mQuatEdgeIndices,mQuatCornerIndices;
55
  int[][] mEdgeMap,mCenterMap;
56 89a00832 Leszek Koltunski
  Static4D[] mBasicCornerV, mCurrCornerV;
57 29e1b835 Leszek Koltunski
  ScrambleState[] mStates;
58 29b82486 Leszek Koltunski
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60
61 a8295031 Leszek Koltunski
  TwistyMinx(InitData data, int meshState, int iconMode, Static4D quat, Static3D move, float scale, InputStream stream)
62 29b82486 Leszek Koltunski
    {
63 a8295031 Leszek Koltunski
    super(data, meshState, iconMode, data.getNumLayers()[0], quat, move, scale, stream);
64 29b82486 Leszek Koltunski
    }
65
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67
68 f9a81f52 Leszek Koltunski
  public ScrambleState[] getScrambleStates()
69 29b82486 Leszek Koltunski
    {
70
    if( mStates==null )
71
      {
72 a57e6870 Leszek Koltunski
      int[] numLayers = getNumLayers();
73
      initializeScrambleStates(numLayers[0]);
74 29b82486 Leszek Koltunski
      }
75
76
    return mStates;
77
    }
78
79
///////////////////////////////////////////////////////////////////////////////////////////////////
80
81
  void initializeCornerV()
82
    {
83
    mBasicCornerV = new Static4D[3];
84
    mCurrCornerV  = new Static4D[3];
85
86
    mBasicCornerV[0] = new Static4D( (SQ5+1)*0.375f, (SQ5-1)*0.375f, -0.750f, 0.0f );
87
    mBasicCornerV[1] = new Static4D(-(SQ5+1)*0.375f, (SQ5-1)*0.375f, -0.750f, 0.0f );
88
    mBasicCornerV[2] = new Static4D(              0,        -1.500f,    0.0f, 0.0f );
89
    }
90
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92
// the five vertices that form a given face. Order: the same as colors of the faces in TwistyMinx.
93
94
  void initializeCenterMap()
95
    {
96
    mCenterMap = new int[][]
97
         {
98 a4af26c1 Leszek Koltunski
           { 0, 12,  8, 10, 16},
99 29b82486 Leszek Koltunski
           { 0, 12,  4, 14,  2},
100
           { 0,  2, 18,  6, 16},
101
           { 6, 18, 11, 19,  7},
102
           { 3, 15,  9, 11, 19},
103
           { 4,  5, 15,  9, 14},
104
           { 1, 13,  5, 15,  3},
105
           { 1,  3, 19,  7, 17},
106
           {10, 16,  6,  7, 17},
107
           { 8, 13,  5,  4, 12},
108
           { 1, 13,  8, 10, 17},
109
           { 2, 14,  9, 11, 18},
110
         };
111
    }
112
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114
// the quadruple ( corner1, corner2, face1, face2 ) defining an edge.
115
// In fact the 2 corners already define it, the faces only provide easy
116
// way to get to know the colors. Order: arbitrary. Face1 arbitrarily on
117
// the 'left' or right of vector corner1 --> corner2, according to Quat.
118
119
  void initializeEdgeMap()
120
    {
121
    mEdgeMap = new int[][]
122
         {
123 a4af26c1 Leszek Koltunski
           {  2,  0,  1,  2}, //0
124
           {  0, 12,  1,  0},
125
           { 12,  4,  1,  9},
126
           {  4, 14,  1,  5},
127
           { 14,  2,  1, 11},
128
           { 14,  9, 11,  5}, //5
129
           {  9, 11, 11,  4},
130
           { 11, 18, 11,  3},
131
           { 18,  2, 11,  2},
132
           { 18,  6,  2,  3},
133
           {  6, 16,  2,  8}, //10
134
           { 16,  0,  2,  0},
135
           { 16, 10,  0,  8},
136
           { 10,  8,  0, 10},
137
           {  8, 12,  0,  9},
138 29b82486 Leszek Koltunski
           {  8, 13,  9, 10}, //15
139 a4af26c1 Leszek Koltunski
           { 13,  5,  9,  6},
140
           {  5,  4,  9,  5},
141
           {  5, 15,  5,  6},
142
           { 15,  9,  5,  4},
143
           { 11, 19,  3,  4}, //20
144
           { 19,  7,  3,  7},
145
           {  7,  6,  3,  8},
146
           {  7, 17,  8,  7},
147
           { 17, 10,  8, 10},
148
           { 17,  1, 10,  7}, //25
149
           {  1,  3,  6,  7},
150
           {  3, 19,  4,  7},
151
           {  1, 13, 10,  6},
152
           {  3, 15,  6,  4},
153 29b82486 Leszek Koltunski
         };
154
    }
155
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157
158
  void initializeQuatIndices()
159
    {
160
    mQuatEdgeIndices = new int[]
161
      {
162 a4af26c1 Leszek Koltunski
         0, 17, 18, 19, 20, 56, 25,  5, 24, 16,
163 89a00832 Leszek Koltunski
         9, 44,  1, 34, 35, 27, 41, 50, 26, 54,
164
        15, 49, 39, 28, 10,  2, 48,  6, 46,  3
165 29b82486 Leszek Koltunski
      };
166
    mQuatCornerIndices = new int[]
167
      {
168 89a00832 Leszek Koltunski
         0, 29, 59, 48, 18, 53, 22, 49, 11, 54,
169
        10, 52, 17, 27, 19, 26,  9, 28, 23, 45
170 29b82486 Leszek Koltunski
      };
171
    }
172
173
///////////////////////////////////////////////////////////////////////////////////////////////////
174
// Coordinates of all 20 corners of a Minx
175
176
  void initializeCorners()
177
    {
178
    float cA = 1.5f;
179
    float cB = 3*C2;
180
    float cC = 3*SIN54;
181
182
    mCorners = new float[][]
183
         {
184
             {  0, cA, cB},
185
             {  0, cA,-cB},
186
             {  0,-cA, cB},
187
             {  0,-cA,-cB},
188
             { cB,  0, cA},
189
             { cB,  0,-cA},
190
             {-cB,  0, cA},
191
             {-cB,  0,-cA},
192
             { cA, cB,  0},
193
             { cA,-cB,  0},
194
             {-cA, cB,  0},
195
             {-cA,-cB,  0},
196
             { cC, cC, cC},
197
             { cC, cC,-cC},
198
             { cC,-cC, cC},
199
             { cC,-cC,-cC},
200
             {-cC, cC, cC},
201
             {-cC, cC,-cC},
202
             {-cC,-cC, cC},
203
             {-cC,-cC,-cC},
204
         };
205
    }
206
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208
209
  void initializeCenterCoords()
210
    {
211
    if( mCorners==null ) initializeCorners();
212
    if( mCenterMap==null ) initializeCenterMap();
213
214
    mCenterCoords = new float[NUM_CENTERS][3];
215
216
    for(int center=0; center<NUM_CENTERS; center++)
217
      {
218
      int[] map = mCenterMap[center];
219
220
      float x = mCorners[map[0]][0] +
221
                mCorners[map[1]][0] +
222
                mCorners[map[2]][0] +
223
                mCorners[map[3]][0] +
224
                mCorners[map[4]][0] ;
225
226
      float y = mCorners[map[0]][1] +
227
                mCorners[map[1]][1] +
228
                mCorners[map[2]][1] +
229
                mCorners[map[3]][1] +
230
                mCorners[map[4]][1] ;
231
232
      float z = mCorners[map[0]][2] +
233
                mCorners[map[1]][2] +
234
                mCorners[map[2]][2] +
235
                mCorners[map[3]][2] +
236
                mCorners[map[4]][2] ;
237
238
      mCenterCoords[center][0] = x/5;
239
      mCenterCoords[center][1] = y/5;
240
      mCenterCoords[center][2] = z/5;
241
      }
242
    }
243
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245
246
  private int[] generateL(int numLayers, int index)
247
    {
248
    int rows = (numLayers-1)/2;
249
    int[] ret = new int[3*4*rows];
250
251
    for(int i=0; i<rows; i++)
252
      {
253
      ret[12*i   ] = i;
254
      ret[12*i+ 1] =-2;
255
      ret[12*i+ 2] = index;
256
      ret[12*i+ 3] = i;
257
      ret[12*i+ 4] =-1;
258
      ret[12*i+ 5] = index;
259
      ret[12*i+ 6] = i;
260
      ret[12*i+ 7] =+1;
261
      ret[12*i+ 8] = index;
262
      ret[12*i+ 9] = i;
263
      ret[12*i+10] =+2;
264
      ret[12*i+11] = index;
265
      }
266
267
    return ret;
268
    }
269
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271
272
  private int[] generateR(int numLayers, int index)
273
    {
274
    int rows = (numLayers-1)/2;
275
    int[] ret = new int[3*4*rows];
276
277
    for(int i=0; i<rows; i++)
278
      {
279
      int lay = rows+i+1;
280
281
      ret[12*i   ] = lay;
282
      ret[12*i+ 1] =-2;
283
      ret[12*i+ 2] = index;
284
      ret[12*i+ 3] = lay;
285
      ret[12*i+ 4] =-1;
286
      ret[12*i+ 5] = index;
287
      ret[12*i+ 6] = lay;
288
      ret[12*i+ 7] =+1;
289
      ret[12*i+ 8] = index;
290
      ret[12*i+ 9] = lay;
291
      ret[12*i+10] =+2;
292
      ret[12*i+11] = index;
293
      }
294
295
    return ret;
296
    }
297
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299
300
  private int[] generateB(int numLayers, int index)
301
    {
302
    int rows = (numLayers-1);
303
    int half = rows/2;
304
    int[] ret = new int[3*4*rows];
305
306
    for(int i=0; i<rows; i++)
307
      {
308
      int ind = i<half? index : index+1;
309
      int lay = i<half? i : i+1;
310
311
      ret[12*i   ] = lay;
312
      ret[12*i+ 1] =-2;
313
      ret[12*i+ 2] = ind;
314
      ret[12*i+ 3] = lay;
315
      ret[12*i+ 4] =-1;
316
      ret[12*i+ 5] = ind;
317
      ret[12*i+ 6] = lay;
318
      ret[12*i+ 7] =+1;
319
      ret[12*i+ 8] = ind;
320
      ret[12*i+ 9] = lay;
321
      ret[12*i+10] =+2;
322
      ret[12*i+11] = ind;
323
      }
324
325
    return ret;
326
    }
327
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329
330
  private void initializeScrambleStates(int numLayers)
331
    {
332
    int[] LEFT0 = generateL(numLayers,1);
333
    int[] RIGH0 = generateR(numLayers,2);
334
    int[] LEFT1 = generateL(numLayers,3);
335
    int[] RIGH1 = generateR(numLayers,4);
336
    int[] LEFT2 = generateL(numLayers,5);
337
    int[] RIGH2 = generateR(numLayers,6);
338
    int[] LEFT3 = generateL(numLayers,7);
339
    int[] RIGH3 = generateR(numLayers,8);
340
    int[] LEFT4 = generateL(numLayers,9);
341
    int[] RIGH4 = generateR(numLayers,10);
342
    int[] LEFT5 = generateL(numLayers,11);
343
    int[] RIGH5 = generateR(numLayers,12);
344
345
    int[] BOTH1 = generateB(numLayers,1);
346
    int[] BOTH3 = generateB(numLayers,3);
347
    int[] BOTH5 = generateB(numLayers,5);
348
    int[] BOTH7 = generateB(numLayers,7);
349
    int[] BOTH9 = generateB(numLayers,9);
350
    int[] BOTH11= generateB(numLayers,11);
351
352
    mStates = new ScrambleState[]
353
      {
354
      new ScrambleState( new int[][] { BOTH1,BOTH3,BOTH5,BOTH7,BOTH9,BOTH11 } ), // beg
355
      new ScrambleState( new int[][] { {}   ,RIGH1,LEFT2,RIGH3,LEFT4,LEFT5  } ), // 0L
356
      new ScrambleState( new int[][] { {}   ,LEFT1,RIGH2,LEFT3,RIGH4,RIGH5  } ), // 0R
357
      new ScrambleState( new int[][] { RIGH0,{}   ,LEFT2,RIGH3,RIGH4,RIGH5  } ), // 1L
358
      new ScrambleState( new int[][] { LEFT0,{}   ,RIGH2,LEFT3,LEFT4,LEFT5  } ), // 1R
359
      new ScrambleState( new int[][] { LEFT0,LEFT1,{}   ,RIGH3,LEFT4,RIGH5  } ), // 2L
360
      new ScrambleState( new int[][] { RIGH0,RIGH1,{}   ,LEFT3,RIGH4,LEFT5  } ), // 2R
361
      new ScrambleState( new int[][] { RIGH0,RIGH1,RIGH2,{}   ,LEFT4,RIGH5  } ), // 3L
362
      new ScrambleState( new int[][] { LEFT0,LEFT1,LEFT2,{}   ,RIGH4,LEFT5  } ), // 3R
363
      new ScrambleState( new int[][] { LEFT0,RIGH1,LEFT2,LEFT3,{}   ,RIGH5  } ), // 4L
364
      new ScrambleState( new int[][] { RIGH0,LEFT1,RIGH2,RIGH3,{}   ,LEFT5  } ), // 4R
365
      new ScrambleState( new int[][] { LEFT0,RIGH1,RIGH2,RIGH3,RIGH4,{}     } ), // 5L
366
      new ScrambleState( new int[][] { RIGH0,LEFT1,LEFT2,LEFT3,LEFT4,{}     } ), // 5R
367
      };
368
    }
369
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371
372
  float[][] genericGetCuts(int numLayers, float dist)
373
    {
374
    if( mCuts==null )
375
      {
376
      mCuts = new float[6][numLayers-1];
377 c9c71c3f Leszek Koltunski
      float D = numLayers* TouchControlDodecahedron.DIST3D;
378 29b82486 Leszek Koltunski
      float X = 2*D/(2+SIN18);  // height of the 'upper' part of a dodecahedron, i.e. put it on a table,
379
                                // its height is then 2D, it has one 'lower' part of height X, one
380
                                // 'middle' part of height Y and one upper part of height X again.
381
      int num = (numLayers-1)/2;
382
      float G = X*dist/num;     // height of one Layer
383
384
      for(int i=0; i<num; i++)
385
        {
386
        float cut = -D + (i+0.85f)*G;  // 0.85? not fully correct; attempt to make it
387
                                       // easier to rotate the outer layers
388
        int j = 2*num-1-i;
389
        mCuts[0][i] = +cut;
390
        mCuts[0][j] = -cut;
391
        mCuts[1][i] = +cut;
392
        mCuts[1][j] = -cut;
393
        mCuts[2][i] = +cut;
394
        mCuts[2][j] = -cut;
395
        mCuts[3][i] = +cut;
396
        mCuts[3][j] = -cut;
397
        mCuts[4][i] = +cut;
398
        mCuts[4][j] = -cut;
399
        mCuts[5][i] = +cut;
400
        mCuts[5][j] = -cut;
401
        }
402
      }
403
404
    return mCuts;
405
    }
406
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408
409 59c20632 Leszek Koltunski
  public boolean[][] getLayerRotatable(int[] numLayers)
410 29b82486 Leszek Koltunski
    {
411 59c20632 Leszek Koltunski
    int numAxis = ROT_AXIS.length;
412
    boolean[][] layerRotatable = new boolean[numAxis][];
413 a57e6870 Leszek Koltunski
414 59c20632 Leszek Koltunski
    for(int i=0; i<numAxis; i++)
415
      {
416
      layerRotatable[i] = new boolean[numLayers[i]];
417
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
418
      layerRotatable[i][numLayers[i]/2] = false;
419 29b82486 Leszek Koltunski
      }
420 59c20632 Leszek Koltunski
421
    return layerRotatable;
422 29b82486 Leszek Koltunski
    }
423
424
///////////////////////////////////////////////////////////////////////////////////////////////////
425
426 11fa413d Leszek Koltunski
  public int getTouchControlType()
427 29b82486 Leszek Koltunski
    {
428 c9c71c3f Leszek Koltunski
    return TC_DODECAHEDRON;
429 29b82486 Leszek Koltunski
    }
430
431
///////////////////////////////////////////////////////////////////////////////////////////////////
432
433 11fa413d Leszek Koltunski
  public int getTouchControlSplit()
434 29b82486 Leszek Koltunski
    {
435 59c20632 Leszek Koltunski
    return TYPE_SPLIT_EDGE;
436 29b82486 Leszek Koltunski
    }
437
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439
440 59c20632 Leszek Koltunski
  public int[][][] getEnabled()
441 29b82486 Leszek Koltunski
    {
442 59c20632 Leszek Koltunski
    return new int[][][]
443
      {
444
          {{2,3},{3,5},{1,5},{1,4},{2,4}},
445
          {{0,5},{2,5},{2,3},{3,4},{0,4}},
446
          {{2,3},{2,5},{0,5},{0,4},{3,4}},
447
          {{1,5},{3,5},{2,3},{2,4},{1,4}},
448
          {{0,3},{0,4},{4,5},{1,5},{1,3}},
449
          {{1,2},{1,4},{4,5},{0,5},{0,2}},
450
          {{4,5},{1,4},{1,2},{0,2},{0,5}},
451
          {{4,5},{0,4},{0,3},{1,3},{1,5}},
452
          {{0,2},{0,1},{1,3},{3,5},{2,5}},
453
          {{3,4},{2,4},{1,2},{0,1},{0,3}},
454
          {{2,4},{3,4},{0,3},{0,1},{1,2}},
455
          {{1,3},{0,1},{0,2},{2,5},{3,5}},
456
      };
457 29b82486 Leszek Koltunski
    }
458
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460
461 59c20632 Leszek Koltunski
  public float[] getDist3D(int[] numLayers)
462 29b82486 Leszek Koltunski
    {
463 4c9ca251 Leszek Koltunski
    return TouchControlDodecahedron.D3D;
464
    }
465
466
///////////////////////////////////////////////////////////////////////////////////////////////////
467
468
  public Static3D[] getFaceAxis()
469
    {
470
    return TouchControlDodecahedron.FACE_AXIS;
471 59c20632 Leszek Koltunski
    }
472 e6b45809 Leszek Koltunski
473 59c20632 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
474
// PUBLIC API
475
476
  public Static3D[] getRotationAxis()
477
    {
478
    return ROT_AXIS;
479 29b82486 Leszek Koltunski
    }
480
481
///////////////////////////////////////////////////////////////////////////////////////////////////
482
483 beee90ab Leszek Koltunski
  public int[][] getBasicAngles()
484 29b82486 Leszek Koltunski
    {
485 beee90ab Leszek Koltunski
    if( mBasicAngle ==null )
486
      {
487
      int num = getNumLayers()[0];
488
      int[] tmp = new int[num];
489
      for(int i=0; i<num; i++) tmp[i] = 5;
490
      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp,tmp,tmp };
491
      }
492
493 29b82486 Leszek Koltunski
    return mBasicAngle;
494
    }
495
}