Project

General

Profile

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

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

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