Project

General

Profile

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

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

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
    for(int i=0; i<count; i++)
70
      {
71
      table[index+2*i  ] = startMove++;
72
      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
    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
    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
    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

    
130
    return ret;
131
    }
132

    
133
///////////////////////////////////////////////////////////////////////////////////////////////////
134

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

    
159
    return mEdges;
160
    }
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
  void initializeCenterMap()
178
    {
179
    mCenterMap = new int[][]
180
         {
181
           { 0, 12,  8, 10, 16},
182
           { 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
  void initializeEdgeMap()
203
    {
204
    mEdgeMap = new int[][]
205
         {
206
           {  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
           {  8, 13,  9, 10}, //15
222
           { 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
         };
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

    
241
  void initializeQuatIndices()
242
    {
243
    mQuatEdgeIndices = new int[]
244
      {
245
         0, 17, 18, 19, 20, 56, 25,  5, 24, 16,
246
         9, 44,  1, 34, 35, 27, 41, 50, 26, 54,
247
        15, 49, 39, 28, 10,  2, 48,  6, 46,  3
248
      };
249
    mQuatCornerIndices = new int[]
250
      {
251
         0, 29, 59, 48, 18, 53, 22, 49, 11, 54,
252
        10, 52, 17, 27, 19, 26,  9, 28, 23, 45
253
      };
254
    }
255

    
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257
// Coordinates of all 20 corners of a Minx
258

    
259
  void initializeCorners()
260
    {
261
    float cA = 1.5f;
262
    float cB = 3*C2;
263
    float cC = 3*SIN54;
264

    
265
    mCorners = new float[][]
266
         {
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
    if( mCorners==null ) initializeCorners();
295
    if( mCenterMap==null ) initializeCenterMap();
296

    
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
      float D = numLayers* TouchControlDodecahedron.DIST3D;
335
      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
        mCuts[0][i] =  cut;
347
        mCuts[0][j] = -cut;
348
        mCuts[1][i] =  cut;
349
        mCuts[1][j] = -cut;
350
        mCuts[2][i] =  cut;
351
        mCuts[2][j] = -cut;
352
        mCuts[3][i] =  cut;
353
        mCuts[3][j] = -cut;
354
        mCuts[4][i] =  cut;
355
        mCuts[4][j] = -cut;
356
        mCuts[5][i] =  cut;
357
        mCuts[5][j] = -cut;
358
        }
359
      }
360

    
361
    return mCuts;
362
    }
363

    
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365

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

    
371
    for(int i=0; i<numAxis; i++)
372
      {
373
      layerRotatable[i] = new boolean[numLayers[i]];
374
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
375
      layerRotatable[i][numLayers[i]/2] = false;
376
      }
377

    
378
    return layerRotatable;
379
    }
380

    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

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

    
388
///////////////////////////////////////////////////////////////////////////////////////////////////
389

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

    
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396

    
397
  public int[][][] getEnabled()
398
    {
399
    return new int[][][]
400
      {
401
          {{2,3},{3,5},{1,5},{1,4},{2,4}},
402
          {{0,5},{2,5},{2,3},{3,4},{0,4}},
403
          {{2,3},{2,5},{0,5},{0,4},{3,4}},
404
          {{1,5},{3,5},{2,3},{2,4},{1,4}},
405
          {{0,3},{0,4},{4,5},{1,5},{1,3}},
406
          {{1,2},{1,4},{4,5},{0,5},{0,2}},
407
          {{4,5},{1,4},{1,2},{0,2},{0,5}},
408
          {{4,5},{0,4},{0,3},{1,3},{1,5}},
409
          {{0,2},{0,1},{1,3},{3,5},{2,5}},
410
          {{3,4},{2,4},{1,2},{0,1},{0,3}},
411
          {{2,4},{3,4},{0,3},{0,1},{1,2}},
412
          {{1,3},{0,1},{0,2},{2,5},{3,5}},
413
      };
414
    }
415

    
416
///////////////////////////////////////////////////////////////////////////////////////////////////
417

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

    
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424

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

    
430
///////////////////////////////////////////////////////////////////////////////////////////////////
431
// PUBLIC API
432

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

    
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439

    
440
  public int[][] getBasicAngles()
441
    {
442
    if( mBasicAngle ==null )
443
      {
444
      int num = getNumLayers()[0];
445
      int[] tmp = new int[num];
446
      for(int i=0; i<num; i++) tmp[i] = 5;
447
      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp,tmp,tmp };
448
      }
449

    
450
    return mBasicAngle;
451
    }
452
}
(14-14/41)