Project

General

Profile

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

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

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