Project

General

Profile

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

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

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
  public int[][] getScrambleEdges()
68
    {
69
    if( mEdges==null )
70
      {
71
      int[] numLayers = getNumLayers();
72
      initializeScrambleEdges(numLayers[0]);
73
      }
74

    
75
    return mEdges;
76
    }
77

    
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

    
80
  void initializeCornerV()
81
    {
82
    mBasicCornerV = new Static4D[3];
83
    mCurrCornerV  = new Static4D[3];
84

    
85
    mBasicCornerV[0] = new Static4D( (SQ5+1)*0.375f, (SQ5-1)*0.375f, -0.750f, 0.0f );
86
    mBasicCornerV[1] = new Static4D(-(SQ5+1)*0.375f, (SQ5-1)*0.375f, -0.750f, 0.0f );
87
    mBasicCornerV[2] = new Static4D(              0,        -1.500f,    0.0f, 0.0f );
88
    }
89

    
90
///////////////////////////////////////////////////////////////////////////////////////////////////
91
// the five vertices that form a given face. Order: the same as colors of the faces in TwistyMinx.
92

    
93
  void initializeCenterMap()
94
    {
95
    mCenterMap = new int[][]
96
         {
97
           { 0, 12,  8, 10, 16},
98
           { 0, 12,  4, 14,  2},
99
           { 0,  2, 18,  6, 16},
100
           { 6, 18, 11, 19,  7},
101
           { 3, 15,  9, 11, 19},
102
           { 4,  5, 15,  9, 14},
103
           { 1, 13,  5, 15,  3},
104
           { 1,  3, 19,  7, 17},
105
           {10, 16,  6,  7, 17},
106
           { 8, 13,  5,  4, 12},
107
           { 1, 13,  8, 10, 17},
108
           { 2, 14,  9, 11, 18},
109
         };
110
    }
111

    
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113
// the quadruple ( corner1, corner2, face1, face2 ) defining an edge.
114
// In fact the 2 corners already define it, the faces only provide easy
115
// way to get to know the colors. Order: arbitrary. Face1 arbitrarily on
116
// the 'left' or right of vector corner1 --> corner2, according to Quat.
117

    
118
  void initializeEdgeMap()
119
    {
120
    mEdgeMap = new int[][]
121
         {
122
           {  2,  0,  1,  2}, //0
123
           {  0, 12,  1,  0},
124
           { 12,  4,  1,  9},
125
           {  4, 14,  1,  5},
126
           { 14,  2,  1, 11},
127
           { 14,  9, 11,  5}, //5
128
           {  9, 11, 11,  4},
129
           { 11, 18, 11,  3},
130
           { 18,  2, 11,  2},
131
           { 18,  6,  2,  3},
132
           {  6, 16,  2,  8}, //10
133
           { 16,  0,  2,  0},
134
           { 16, 10,  0,  8},
135
           { 10,  8,  0, 10},
136
           {  8, 12,  0,  9},
137
           {  8, 13,  9, 10}, //15
138
           { 13,  5,  9,  6},
139
           {  5,  4,  9,  5},
140
           {  5, 15,  5,  6},
141
           { 15,  9,  5,  4},
142
           { 11, 19,  3,  4}, //20
143
           { 19,  7,  3,  7},
144
           {  7,  6,  3,  8},
145
           {  7, 17,  8,  7},
146
           { 17, 10,  8, 10},
147
           { 17,  1, 10,  7}, //25
148
           {  1,  3,  6,  7},
149
           {  3, 19,  4,  7},
150
           {  1, 13, 10,  6},
151
           {  3, 15,  6,  4},
152
         };
153
    }
154

    
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156

    
157
  void initializeQuatIndices()
158
    {
159
    mQuatEdgeIndices = new int[]
160
      {
161
         0, 17, 18, 19, 20, 56, 25,  5, 24, 16,
162
         9, 44,  1, 34, 35, 27, 41, 50, 26, 54,
163
        15, 49, 39, 28, 10,  2, 48,  6, 46,  3
164
      };
165
    mQuatCornerIndices = new int[]
166
      {
167
         0, 29, 59, 48, 18, 53, 22, 49, 11, 54,
168
        10, 52, 17, 27, 19, 26,  9, 28, 23, 45
169
      };
170
    }
171

    
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173
// Coordinates of all 20 corners of a Minx
174

    
175
  void initializeCorners()
176
    {
177
    float cA = 1.5f;
178
    float cB = 3*C2;
179
    float cC = 3*SIN54;
180

    
181
    mCorners = new float[][]
182
         {
183
             {  0, cA, cB},
184
             {  0, cA,-cB},
185
             {  0,-cA, cB},
186
             {  0,-cA,-cB},
187
             { cB,  0, cA},
188
             { cB,  0,-cA},
189
             {-cB,  0, cA},
190
             {-cB,  0,-cA},
191
             { cA, cB,  0},
192
             { cA,-cB,  0},
193
             {-cA, cB,  0},
194
             {-cA,-cB,  0},
195
             { cC, cC, cC},
196
             { cC, cC,-cC},
197
             { cC,-cC, cC},
198
             { cC,-cC,-cC},
199
             {-cC, cC, cC},
200
             {-cC, cC,-cC},
201
             {-cC,-cC, cC},
202
             {-cC,-cC,-cC},
203
         };
204
    }
205

    
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

    
208
  void initializeCenterCoords()
209
    {
210
    if( mCorners==null ) initializeCorners();
211
    if( mCenterMap==null ) initializeCenterMap();
212

    
213
    mCenterCoords = new float[NUM_CENTERS][3];
214

    
215
    for(int center=0; center<NUM_CENTERS; center++)
216
      {
217
      int[] map = mCenterMap[center];
218

    
219
      float x = mCorners[map[0]][0] +
220
                mCorners[map[1]][0] +
221
                mCorners[map[2]][0] +
222
                mCorners[map[3]][0] +
223
                mCorners[map[4]][0] ;
224

    
225
      float y = mCorners[map[0]][1] +
226
                mCorners[map[1]][1] +
227
                mCorners[map[2]][1] +
228
                mCorners[map[3]][1] +
229
                mCorners[map[4]][1] ;
230

    
231
      float z = mCorners[map[0]][2] +
232
                mCorners[map[1]][2] +
233
                mCorners[map[2]][2] +
234
                mCorners[map[3]][2] +
235
                mCorners[map[4]][2] ;
236

    
237
      mCenterCoords[center][0] = x/5;
238
      mCenterCoords[center][1] = y/5;
239
      mCenterCoords[center][2] = z/5;
240
      }
241
    }
242

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244

    
245
  private void fillRet(int[] table, int index, int count, int startMove, int graphVertex)
246
    {
247
    int num = count/2;
248
    int move= startMove*num;
249

    
250
    for(int i=0; i<num; i++)
251
      {
252
      table[index+2*i  ] = move++;
253
      table[index+2*i+1] = graphVertex;
254
      }
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

    
259
  private int[] genEdge(int numLayers, int x0, int x1, int x2, int x3, int x4, int x5,
260
                                       int x6, int x7, int x8, int x9, int x10,int x11)
261
    {
262
    int layers = (numLayers-1)/2;
263
    int num = 8*layers;
264
    int size = 0;
265

    
266
    if( x0 >=0 ) size += num;
267
    if( x1 >=0 ) size += num;
268
    if( x2 >=0 ) size += num;
269
    if( x3 >=0 ) size += num;
270
    if( x4 >=0 ) size += num;
271
    if( x5 >=0 ) size += num;
272
    if( x6 >=0 ) size += num;
273
    if( x7 >=0 ) size += num;
274
    if( x8 >=0 ) size += num;
275
    if( x9 >=0 ) size += num;
276
    if( x10>=0 ) size += num;
277
    if( x11>=0 ) size += num;
278

    
279
    int[] ret = new int[size];
280
    int index = 0;
281

    
282
    if( x0 >=0 ) { fillRet(ret,index,num,0 ,x0 ); index+=num; }
283
    if( x1 >=0 ) { fillRet(ret,index,num,1 ,x1 ); index+=num; }
284
    if( x2 >=0 ) { fillRet(ret,index,num,2 ,x2 ); index+=num; }
285
    if( x3 >=0 ) { fillRet(ret,index,num,3 ,x3 ); index+=num; }
286
    if( x4 >=0 ) { fillRet(ret,index,num,4 ,x4 ); index+=num; }
287
    if( x5 >=0 ) { fillRet(ret,index,num,5 ,x5 ); index+=num; }
288
    if( x6 >=0 ) { fillRet(ret,index,num,6 ,x6 ); index+=num; }
289
    if( x7 >=0 ) { fillRet(ret,index,num,7 ,x7 ); index+=num; }
290
    if( x8 >=0 ) { fillRet(ret,index,num,8 ,x8 ); index+=num; }
291
    if( x9 >=0 ) { fillRet(ret,index,num,9 ,x9 ); index+=num; }
292
    if( x10>=0 ) { fillRet(ret,index,num,10,x10); index+=num; }
293
    if( x11>=0 ) { fillRet(ret,index,num,11,x11);             }
294

    
295
    return ret;
296
    }
297

    
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299

    
300
  private void initializeScrambleEdges(int numLayers)
301
    {
302
    mEdges = new int[][]
303
      {
304
      genEdge(numLayers, 1, 2,  3, 4,  5, 6,  7, 8,  9,10, 11,12),  // 0
305
      genEdge(numLayers,-1,-1, -1, 4,  5,-1, -1, 8,  9,-1, 11,-1),  // 0L
306
      genEdge(numLayers,-1,-1,  3,-1, -1, 6,  7,-1, -1,10, -1,12),  // 0R
307
      genEdge(numLayers,-1, 2, -1,-1,  5,-1, -1, 8, -1,10, -1,12),  // 1L
308
      genEdge(numLayers, 1,-1, -1,-1, -1, 6,  7,-1,  9,-1, 11,-1),  // 1R
309
      genEdge(numLayers, 1,-1,  3,-1, -1,-1, -1, 8,  9,-1, -1,12),  // 2L
310
      genEdge(numLayers,-1, 2, -1, 4, -1,-1,  7,-1, -1,10, 11,-1),  // 2R
311
      genEdge(numLayers,-1, 2, -1, 4, -1, 6, -1,-1,  9,-1, -1,12),  // 3L
312
      genEdge(numLayers, 1,-1,  3,-1,  5,-1, -1,-1, -1,10, 11,-1),  // 3R
313
      genEdge(numLayers, 1,-1, -1, 4,  5,-1,  7,-1, -1,-1, -1,12),  // 4L
314
      genEdge(numLayers,-1, 2,  3,-1,  5,-1, -1, 8, -1,-1, 11,-1),  // 4R
315
      genEdge(numLayers, 1,-1, -1, 4, -1, 6, -1, 8, -1,10, -1,-1),  // 5L
316
      genEdge(numLayers,-1, 2,  3,-1,  5,-1,  7,-1,  9,-1, -1,-1),  // 5R
317
      };
318
    }
319

    
320
///////////////////////////////////////////////////////////////////////////////////////////////////
321

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

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

    
354
    return mCuts;
355
    }
356

    
357
///////////////////////////////////////////////////////////////////////////////////////////////////
358

    
359
  public boolean[][] getLayerRotatable(int[] numLayers)
360
    {
361
    int numAxis = ROT_AXIS.length;
362
    boolean[][] layerRotatable = new boolean[numAxis][];
363

    
364
    for(int i=0; i<numAxis; i++)
365
      {
366
      layerRotatable[i] = new boolean[numLayers[i]];
367
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
368
      layerRotatable[i][numLayers[i]/2] = false;
369
      }
370

    
371
    return layerRotatable;
372
    }
373

    
374
///////////////////////////////////////////////////////////////////////////////////////////////////
375

    
376
  public int getTouchControlType()
377
    {
378
    return TC_DODECAHEDRON;
379
    }
380

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

    
383
  public int getTouchControlSplit()
384
    {
385
    return TYPE_SPLIT_EDGE;
386
    }
387

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

    
390
  public int[][][] getEnabled()
391
    {
392
    return new int[][][]
393
      {
394
          {{2,3},{3,5},{1,5},{1,4},{2,4}},
395
          {{0,5},{2,5},{2,3},{3,4},{0,4}},
396
          {{2,3},{2,5},{0,5},{0,4},{3,4}},
397
          {{1,5},{3,5},{2,3},{2,4},{1,4}},
398
          {{0,3},{0,4},{4,5},{1,5},{1,3}},
399
          {{1,2},{1,4},{4,5},{0,5},{0,2}},
400
          {{4,5},{1,4},{1,2},{0,2},{0,5}},
401
          {{4,5},{0,4},{0,3},{1,3},{1,5}},
402
          {{0,2},{0,1},{1,3},{3,5},{2,5}},
403
          {{3,4},{2,4},{1,2},{0,1},{0,3}},
404
          {{2,4},{3,4},{0,3},{0,1},{1,2}},
405
          {{1,3},{0,1},{0,2},{2,5},{3,5}},
406
      };
407
    }
408

    
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410

    
411
  public float[] getDist3D(int[] numLayers)
412
    {
413
    return TouchControlDodecahedron.D3D;
414
    }
415

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

    
418
  public Static3D[] getFaceAxis()
419
    {
420
    return TouchControlDodecahedron.FACE_AXIS;
421
    }
422

    
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424
// PUBLIC API
425

    
426
  public Static3D[] getRotationAxis()
427
    {
428
    return ROT_AXIS;
429
    }
430

    
431
///////////////////////////////////////////////////////////////////////////////////////////////////
432

    
433
  public int[][] getBasicAngles()
434
    {
435
    if( mBasicAngle ==null )
436
      {
437
      int num = getNumLayers()[0];
438
      int[] tmp = new int[num];
439
      for(int i=0; i<num; i++) tmp[i] = 5;
440
      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp,tmp,tmp };
441
      }
442

    
443
    return mBasicAngle;
444
    }
445
}
(14-14/41)