Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyDodecahedron.java @ 3a0990b1

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