Project

General

Profile

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

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

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 java.io.InputStream;
19

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

    
26
///////////////////////////////////////////////////////////////////////////////////////////////////
27

    
28
abstract class TwistyDodecahedron extends ShapeDodecahedron
29
{
30
  static final int NUM_CORNERS = 20;
31
  static final int NUM_CENTERS = 12;
32
  static final int NUM_EDGES   = 30;
33

    
34
  static final float SIN18    = (SQ5-1)/4;
35
  static final float COS18    = (float)(0.25f*Math.sqrt(10.0f+2.0f*SQ5));
36
  static final float COS_HALFD= (float)(Math.sqrt(0.5f-0.1f*SQ5)); // cos(half the dihedral angle)
37
  static final float SIN_HALFD= (float)(Math.sqrt(0.5f+0.1f*SQ5)); // sin(half the dihedral angle)
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
  private int[][] mBasicAngle;
51
  private float[][] mCuts;
52
  float[][] mCenterCoords,mCorners;
53
  int[] mQuatEdgeIndices,mQuatCornerIndices;
54
  int[][] mEdgeMap,mCenterMap;
55
  Static4D[] mBasicCornerV, mCurrCornerV;
56
  int[][] mEdges;
57

    
58
///////////////////////////////////////////////////////////////////////////////////////////////////
59

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

    
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66

    
67
  private void fillRet(int[] table, int index, int count, int startMove, int graphVertex)
68
    {
69
    int num = count/2;
70
    int move= startMove*num;
71

    
72
    for(int i=0; i<num; i++)
73
      {
74
      table[index+2*i  ] = move++;
75
      table[index+2*i+1] = graphVertex;
76
      }
77
    }
78

    
79
///////////////////////////////////////////////////////////////////////////////////////////////////
80

    
81
  private int[] genEdge(int numLayers, int x0, int x1, int x2, int x3, int x4, int x5,
82
                                       int x6, int x7, int x8, int x9, int x10,int x11)
83
    {
84
    int layers = (numLayers-1)/2;
85
    int num = 8*layers;
86
    int size = 0;
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

    
104
    if( x0 >=0 ) { fillRet(ret,index,num,0 ,x0 ); index+=num; }
105
    if( x1 >=0 ) { fillRet(ret,index,num,1 ,x1 ); index+=num; }
106
    if( x2 >=0 ) { fillRet(ret,index,num,2 ,x2 ); index+=num; }
107
    if( x3 >=0 ) { fillRet(ret,index,num,3 ,x3 ); index+=num; }
108
    if( x4 >=0 ) { fillRet(ret,index,num,4 ,x4 ); index+=num; }
109
    if( x5 >=0 ) { fillRet(ret,index,num,5 ,x5 ); index+=num; }
110
    if( x6 >=0 ) { fillRet(ret,index,num,6 ,x6 ); index+=num; }
111
    if( x7 >=0 ) { fillRet(ret,index,num,7 ,x7 ); index+=num; }
112
    if( x8 >=0 ) { fillRet(ret,index,num,8 ,x8 ); index+=num; }
113
    if( x9 >=0 ) { fillRet(ret,index,num,9 ,x9 ); index+=num; }
114
    if( x10>=0 ) { fillRet(ret,index,num,10,x10); index+=num; }
115
    if( x11>=0 ) { fillRet(ret,index,num,11,x11);             }
116

    
117
    return ret;
118
    }
119

    
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121

    
122
  public int[][] getScrambleEdges()
123
    {
124
    if( mEdges==null )
125
      {
126
      int nL = getNumLayers()[0];
127

    
128
      mEdges = new int[][]
129
        {
130
        genEdge(nL, 1, 2,  3, 4,  5, 6,  7, 8,  9,10, 11,12),  // 0
131
        genEdge(nL,-1,-1, -1, 4,  5,-1, -1, 8,  9,-1, 11,-1),  // 0L
132
        genEdge(nL,-1,-1,  3,-1, -1, 6,  7,-1, -1,10, -1,12),  // 0R
133
        genEdge(nL,-1, 2, -1,-1,  5,-1, -1, 8, -1,10, -1,12),  // 1L
134
        genEdge(nL, 1,-1, -1,-1, -1, 6,  7,-1,  9,-1, 11,-1),  // 1R
135
        genEdge(nL, 1,-1,  3,-1, -1,-1, -1, 8,  9,-1, -1,12),  // 2L
136
        genEdge(nL,-1, 2, -1, 4, -1,-1,  7,-1, -1,10, 11,-1),  // 2R
137
        genEdge(nL,-1, 2, -1, 4, -1, 6, -1,-1,  9,-1, -1,12),  // 3L
138
        genEdge(nL, 1,-1,  3,-1,  5,-1, -1,-1, -1,10, 11,-1),  // 3R
139
        genEdge(nL, 1,-1, -1, 4,  5,-1,  7,-1, -1,-1, -1,12),  // 4L
140
        genEdge(nL,-1, 2,  3,-1,  5,-1, -1, 8, -1,-1, 11,-1),  // 4R
141
        genEdge(nL, 1,-1, -1, 4, -1, 6, -1, 8, -1,10, -1,-1),  // 5L
142
        genEdge(nL,-1, 2,  3,-1,  5,-1,  7,-1,  9,-1, -1,-1),  // 5R
143
        };
144
      }
145

    
146
    return mEdges;
147
    }
148

    
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150

    
151
  void initializeCornerV()
152
    {
153
    mBasicCornerV = new Static4D[3];
154
    mCurrCornerV  = new Static4D[3];
155

    
156
    mBasicCornerV[0] = new Static4D( (SQ5+1)*0.375f, (SQ5-1)*0.375f, -0.750f, 0.0f );
157
    mBasicCornerV[1] = new Static4D(-(SQ5+1)*0.375f, (SQ5-1)*0.375f, -0.750f, 0.0f );
158
    mBasicCornerV[2] = new Static4D(              0,        -1.500f,    0.0f, 0.0f );
159
    }
160

    
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162
// the five vertices that form a given face. Order: the same as colors of the faces in TwistyMinx.
163

    
164
  void initializeCenterMap()
165
    {
166
    mCenterMap = new int[][]
167
         {
168
           { 0, 12,  8, 10, 16},
169
           { 0, 12,  4, 14,  2},
170
           { 0,  2, 18,  6, 16},
171
           { 6, 18, 11, 19,  7},
172
           { 3, 15,  9, 11, 19},
173
           { 4,  5, 15,  9, 14},
174
           { 1, 13,  5, 15,  3},
175
           { 1,  3, 19,  7, 17},
176
           {10, 16,  6,  7, 17},
177
           { 8, 13,  5,  4, 12},
178
           { 1, 13,  8, 10, 17},
179
           { 2, 14,  9, 11, 18},
180
         };
181
    }
182

    
183
///////////////////////////////////////////////////////////////////////////////////////////////////
184
// the quadruple ( corner1, corner2, face1, face2 ) defining an edge.
185
// In fact the 2 corners already define it, the faces only provide easy
186
// way to get to know the colors. Order: arbitrary. Face1 arbitrarily on
187
// the 'left' or right of vector corner1 --> corner2, according to Quat.
188

    
189
  void initializeEdgeMap()
190
    {
191
    mEdgeMap = new int[][]
192
         {
193
           {  2,  0,  1,  2}, //0
194
           {  0, 12,  1,  0},
195
           { 12,  4,  1,  9},
196
           {  4, 14,  1,  5},
197
           { 14,  2,  1, 11},
198
           { 14,  9, 11,  5}, //5
199
           {  9, 11, 11,  4},
200
           { 11, 18, 11,  3},
201
           { 18,  2, 11,  2},
202
           { 18,  6,  2,  3},
203
           {  6, 16,  2,  8}, //10
204
           { 16,  0,  2,  0},
205
           { 16, 10,  0,  8},
206
           { 10,  8,  0, 10},
207
           {  8, 12,  0,  9},
208
           {  8, 13,  9, 10}, //15
209
           { 13,  5,  9,  6},
210
           {  5,  4,  9,  5},
211
           {  5, 15,  5,  6},
212
           { 15,  9,  5,  4},
213
           { 11, 19,  3,  4}, //20
214
           { 19,  7,  3,  7},
215
           {  7,  6,  3,  8},
216
           {  7, 17,  8,  7},
217
           { 17, 10,  8, 10},
218
           { 17,  1, 10,  7}, //25
219
           {  1,  3,  6,  7},
220
           {  3, 19,  4,  7},
221
           {  1, 13, 10,  6},
222
           {  3, 15,  6,  4},
223
         };
224
    }
225

    
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227

    
228
  void initializeQuatIndices()
229
    {
230
    mQuatEdgeIndices = new int[]
231
      {
232
         0, 17, 18, 19, 20, 56, 25,  5, 24, 16,
233
         9, 44,  1, 34, 35, 27, 41, 50, 26, 54,
234
        15, 49, 39, 28, 10,  2, 48,  6, 46,  3
235
      };
236
    mQuatCornerIndices = new int[]
237
      {
238
         0, 29, 59, 48, 18, 53, 22, 49, 11, 54,
239
        10, 52, 17, 27, 19, 26,  9, 28, 23, 45
240
      };
241
    }
242

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244
// Coordinates of all 20 corners of a Minx
245

    
246
  void initializeCorners()
247
    {
248
    float cA = 1.5f;
249
    float cB = 3*C2;
250
    float cC = 3*SIN54;
251

    
252
    mCorners = new float[][]
253
         {
254
             {  0, cA, cB},
255
             {  0, cA,-cB},
256
             {  0,-cA, cB},
257
             {  0,-cA,-cB},
258
             { cB,  0, cA},
259
             { cB,  0,-cA},
260
             {-cB,  0, cA},
261
             {-cB,  0,-cA},
262
             { cA, cB,  0},
263
             { cA,-cB,  0},
264
             {-cA, cB,  0},
265
             {-cA,-cB,  0},
266
             { cC, cC, cC},
267
             { cC, cC,-cC},
268
             { cC,-cC, cC},
269
             { cC,-cC,-cC},
270
             {-cC, cC, cC},
271
             {-cC, cC,-cC},
272
             {-cC,-cC, cC},
273
             {-cC,-cC,-cC},
274
         };
275
    }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

    
279
  void initializeCenterCoords()
280
    {
281
    if( mCorners==null ) initializeCorners();
282
    if( mCenterMap==null ) initializeCenterMap();
283

    
284
    mCenterCoords = new float[NUM_CENTERS][3];
285

    
286
    for(int center=0; center<NUM_CENTERS; center++)
287
      {
288
      int[] map = mCenterMap[center];
289

    
290
      float x = mCorners[map[0]][0] +
291
                mCorners[map[1]][0] +
292
                mCorners[map[2]][0] +
293
                mCorners[map[3]][0] +
294
                mCorners[map[4]][0] ;
295

    
296
      float y = mCorners[map[0]][1] +
297
                mCorners[map[1]][1] +
298
                mCorners[map[2]][1] +
299
                mCorners[map[3]][1] +
300
                mCorners[map[4]][1] ;
301

    
302
      float z = mCorners[map[0]][2] +
303
                mCorners[map[1]][2] +
304
                mCorners[map[2]][2] +
305
                mCorners[map[3]][2] +
306
                mCorners[map[4]][2] ;
307

    
308
      mCenterCoords[center][0] = x/5;
309
      mCenterCoords[center][1] = y/5;
310
      mCenterCoords[center][2] = z/5;
311
      }
312
    }
313

    
314
///////////////////////////////////////////////////////////////////////////////////////////////////
315

    
316
  float[][] genericGetCuts(int numLayers, float dist)
317
    {
318
    if( mCuts==null )
319
      {
320
      mCuts = new float[6][numLayers-1];
321
      float D = numLayers* TouchControlDodecahedron.DIST3D;
322
      float X = 2*D/(2+SIN18);  // height of the 'upper' part of a dodecahedron, i.e. put it on a table,
323
                                // its height is then 2D, it has one 'lower' part of height X, one
324
                                // 'middle' part of height Y and one upper part of height X again.
325
      int num = (numLayers-1)/2;
326
      float G = X*dist/num;     // height of one Layer
327

    
328
      for(int i=0; i<num; i++)
329
        {
330
        float cut = -D + (i+0.85f)*G;  // 0.85? not fully correct; attempt to make it
331
                                       // easier to rotate the outer layers
332
        int j = 2*num-1-i;
333
        mCuts[0][i] =  cut;
334
        mCuts[0][j] = -cut;
335
        mCuts[1][i] =  cut;
336
        mCuts[1][j] = -cut;
337
        mCuts[2][i] =  cut;
338
        mCuts[2][j] = -cut;
339
        mCuts[3][i] =  cut;
340
        mCuts[3][j] = -cut;
341
        mCuts[4][i] =  cut;
342
        mCuts[4][j] = -cut;
343
        mCuts[5][i] =  cut;
344
        mCuts[5][j] = -cut;
345
        }
346
      }
347

    
348
    return mCuts;
349
    }
350

    
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352

    
353
  public boolean[][] getLayerRotatable(int[] numLayers)
354
    {
355
    int numAxis = ROT_AXIS.length;
356
    boolean[][] layerRotatable = new boolean[numAxis][];
357

    
358
    for(int i=0; i<numAxis; i++)
359
      {
360
      layerRotatable[i] = new boolean[numLayers[i]];
361
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
362
      layerRotatable[i][numLayers[i]/2] = false;
363
      }
364

    
365
    return layerRotatable;
366
    }
367

    
368
///////////////////////////////////////////////////////////////////////////////////////////////////
369

    
370
  public int getTouchControlType()
371
    {
372
    return TC_DODECAHEDRON;
373
    }
374

    
375
///////////////////////////////////////////////////////////////////////////////////////////////////
376

    
377
  public int getTouchControlSplit()
378
    {
379
    return TYPE_SPLIT_EDGE;
380
    }
381

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383

    
384
  public int[][][] getEnabled()
385
    {
386
    return new int[][][]
387
      {
388
          {{2,3},{3,5},{1,5},{1,4},{2,4}},
389
          {{0,5},{2,5},{2,3},{3,4},{0,4}},
390
          {{2,3},{2,5},{0,5},{0,4},{3,4}},
391
          {{1,5},{3,5},{2,3},{2,4},{1,4}},
392
          {{0,3},{0,4},{4,5},{1,5},{1,3}},
393
          {{1,2},{1,4},{4,5},{0,5},{0,2}},
394
          {{4,5},{1,4},{1,2},{0,2},{0,5}},
395
          {{4,5},{0,4},{0,3},{1,3},{1,5}},
396
          {{0,2},{0,1},{1,3},{3,5},{2,5}},
397
          {{3,4},{2,4},{1,2},{0,1},{0,3}},
398
          {{2,4},{3,4},{0,3},{0,1},{1,2}},
399
          {{1,3},{0,1},{0,2},{2,5},{3,5}},
400
      };
401
    }
402

    
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404

    
405
  public float[] getDist3D(int[] numLayers)
406
    {
407
    return TouchControlDodecahedron.D3D;
408
    }
409

    
410
///////////////////////////////////////////////////////////////////////////////////////////////////
411

    
412
  public Static3D[] getFaceAxis()
413
    {
414
    return TouchControlDodecahedron.FACE_AXIS;
415
    }
416

    
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418
// PUBLIC API
419

    
420
  public Static3D[] getRotationAxis()
421
    {
422
    return ROT_AXIS;
423
    }
424

    
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426

    
427
  public int[][] getBasicAngles()
428
    {
429
    if( mBasicAngle ==null )
430
      {
431
      int num = getNumLayers()[0];
432
      int[] tmp = new int[num];
433
      for(int i=0; i<num; i++) tmp[i] = 5;
434
      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp,tmp,tmp };
435
      }
436

    
437
    return mBasicAngle;
438
    }
439
}
(14-14/41)