Project

General

Profile

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

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

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// 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
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.objects;
11

    
12
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

    
18
import org.distorted.library.type.Static3D;
19
import org.distorted.library.type.Static4D;
20
import org.distorted.objectlib.main.InitAssets;
21
import org.distorted.objectlib.main.InitData;
22
import org.distorted.objectlib.touchcontrol.TouchControlDodecahedron;
23
import org.distorted.objectlib.shape.ShapeDodecahedron;
24

    
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26

    
27
abstract class TwistyDodecahedron extends ShapeDodecahedron
28
{
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
  private int[][] mBasicAngle;
50
  private float[][] mCuts;
51
  float[][] mCenterCoords,mCorners;
52
  int[] mQuatEdgeIndices,mQuatCornerIndices;
53
  int[][] mEdgeMap,mCenterMap;
54
  Static4D[] mBasicCornerV, mCurrCornerV;
55
  int[][] mEdges;
56

    
57
///////////////////////////////////////////////////////////////////////////////////////////////////
58

    
59
  TwistyDodecahedron(int meshState, int iconMode, Static4D quat, Static3D move, float scale, InitData data, InitAssets asset)
60
    {
61
    super(meshState, iconMode, data.getNumLayers()[0], quat, move, scale, data, asset);
62
    }
63

    
64
///////////////////////////////////////////////////////////////////////////////////////////////////
65

    
66
  private void fillRet(int[] table, int index, int count, int startMove, int graphVertex)
67
    {
68
    for(int i=0; i<count; i++)
69
      {
70
      table[index+2*i  ] = startMove++;
71
      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
    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
    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
    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

    
129
    return ret;
130
    }
131

    
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133

    
134
  public int[][] getScrambleEdges()
135
    {
136
    if( mEdges==null )
137
      {
138
      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
      }
157

    
158
    return mEdges;
159
    }
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
           { 0, 12,  8, 10, 16},
181
           { 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
           {  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
           {  8, 13,  9, 10}, //15
221
           { 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
         };
236
    }
237

    
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239

    
240
  void initializeQuatIndices()
241
    {
242
    mQuatEdgeIndices = new int[]
243
      {
244
         0, 17, 18, 19, 20, 56, 25,  5, 24, 16,
245
         9, 44,  1, 34, 35, 27, 41, 50, 26, 54,
246
        15, 49, 39, 28, 10,  2, 48,  6, 46,  3
247
      };
248
    mQuatCornerIndices = new int[]
249
      {
250
         0, 29, 59, 48, 18, 53, 22, 49, 11, 54,
251
        10, 52, 17, 27, 19, 26,  9, 28, 23, 45
252
      };
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
      float D = numLayers* TouchControlDodecahedron.DIST3D;
334
      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
        mCuts[0][i] =  cut;
346
        mCuts[0][j] = -cut;
347
        mCuts[1][i] =  cut;
348
        mCuts[1][j] = -cut;
349
        mCuts[2][i] =  cut;
350
        mCuts[2][j] = -cut;
351
        mCuts[3][i] =  cut;
352
        mCuts[3][j] = -cut;
353
        mCuts[4][i] =  cut;
354
        mCuts[4][j] = -cut;
355
        mCuts[5][i] =  cut;
356
        mCuts[5][j] = -cut;
357
        }
358
      }
359

    
360
    return mCuts;
361
    }
362

    
363
///////////////////////////////////////////////////////////////////////////////////////////////////
364

    
365
  public boolean[][] getLayerRotatable(int[] numLayers)
366
    {
367
    int numAxis = ROT_AXIS.length;
368
    boolean[][] layerRotatable = new boolean[numAxis][];
369

    
370
    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
      }
376

    
377
    return layerRotatable;
378
    }
379

    
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381

    
382
  public int getTouchControlType()
383
    {
384
    return TC_DODECAHEDRON;
385
    }
386

    
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388

    
389
  public int getTouchControlSplit()
390
    {
391
    return TYPE_SPLIT_EDGE;
392
    }
393

    
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395

    
396
  public int[][][] getEnabled()
397
    {
398
    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
    }
414

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416

    
417
  public float[] getDist3D(int[] numLayers)
418
    {
419
    return TouchControlDodecahedron.D3D;
420
    }
421

    
422
///////////////////////////////////////////////////////////////////////////////////////////////////
423

    
424
  public Static3D[] getFaceAxis()
425
    {
426
    return TouchControlDodecahedron.FACE_AXIS;
427
    }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430
// PUBLIC API
431

    
432
  public Static3D[] getRotationAxis()
433
    {
434
    return ROT_AXIS;
435
    }
436

    
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438

    
439
  public int[][] getBasicAngles()
440
    {
441
    if( mBasicAngle ==null )
442
      {
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
    return mBasicAngle;
450
    }
451
}
(14-14/41)