Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyDiamond.java @ c9c71c3f

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objectlib.objects;
21

    
22
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_OCTAHEDRON;
23
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
24

    
25
import java.io.InputStream;
26

    
27
import org.distorted.library.type.Static3D;
28
import org.distorted.library.type.Static4D;
29

    
30
import org.distorted.objectlib.touchcontrol.TouchControlOctahedron;
31
import org.distorted.objectlib.main.ObjectControl;
32
import org.distorted.objectlib.main.ObjectType;
33
import org.distorted.objectlib.helpers.ObjectShape;
34
import org.distorted.objectlib.helpers.ObjectSticker;
35
import org.distorted.objectlib.helpers.ScrambleState;
36
import org.distorted.objectlib.main.ShapeOctahedron;
37

    
38
///////////////////////////////////////////////////////////////////////////////////////////////////
39

    
40
public class TwistyDiamond extends ShapeOctahedron
41
{
42
  // the four rotation axis of a Diamond. Must be normalized.
43
  static final Static3D[] ROT_AXIS = new Static3D[]
44
         {
45
           new Static3D(+SQ6/3,+SQ3/3,     0),
46
           new Static3D(-SQ6/3,+SQ3/3,     0),
47
           new Static3D(     0,-SQ3/3,-SQ6/3),
48
           new Static3D(     0,-SQ3/3,+SQ6/3)
49
         };
50

    
51
  private ScrambleState[] mStates;
52
  private int[] mBasicAngle;
53
  private int[] mFaceMap;
54
  private float[][] mCuts;
55
  private Static4D[] mQuats;
56
  private int[] mTetraToFaceMap;
57
  private ObjectSticker[] mStickers;
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

    
61
  public TwistyDiamond(int[] numL, Static4D quat, Static3D move, float scale, InputStream stream)
62
    {
63
    super(numL, numL[0], quat, move, scale, stream);
64
    }
65

    
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67

    
68
  public ScrambleState[] getScrambleStates()
69
    {
70
    if( mStates==null )
71
      {
72
      int[] numLayers = getNumLayers();
73
      int numL = numLayers[0];
74
      int[] tmp = new int[3*2*numL];
75

    
76
      for(int i=0; i<2*numL; i++)
77
        {
78
        tmp[3*i  ] = (i<numL) ?  i:i-numL;
79
        tmp[3*i+1] = (i%2==0) ? -1:1;
80
        tmp[3*i+2] = 0;
81
        }
82

    
83
      mStates = new ScrambleState[]
84
        {
85
        new ScrambleState( new int[][] {tmp,tmp,tmp,tmp} )
86
        };
87
      }
88

    
89
    return mStates;
90
    }
91

    
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93

    
94
  private void initializeQuats()
95
    {
96
    mQuats = new Static4D[]
97
         {
98
          new Static4D(  0.0f,  0.0f,   0.0f,  1.0f ),
99
          new Static4D(  0.0f,  1.0f,   0.0f,  0.0f ),
100
          new Static4D(+SQ2/2,  0.0f, -SQ2/2,  0.0f ),
101
          new Static4D(-SQ2/2,  0.0f, -SQ2/2,  0.0f ),
102

    
103
          new Static4D(+SQ2/2,  0.5f,   0.0f,  0.5f ),
104
          new Static4D(-SQ2/2,  0.5f,   0.0f,  0.5f ),
105
          new Static4D(  0.0f,  0.5f, +SQ2/2,  0.5f ),
106
          new Static4D(  0.0f,  0.5f, -SQ2/2,  0.5f ),
107
          new Static4D(+SQ2/2,  0.5f,   0.0f, -0.5f ),
108
          new Static4D(-SQ2/2,  0.5f,   0.0f, -0.5f ),
109
          new Static4D(  0.0f,  0.5f, +SQ2/2, -0.5f ),
110
          new Static4D(  0.0f,  0.5f, -SQ2/2, -0.5f )
111
         };
112
    }
113

    
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115

    
116
  public int[] getSolvedQuats(int cubit, int[] numLayers)
117
    {
118
    if( mQuats==null ) initializeQuats();
119
    if( mFaceMap==null ) mFaceMap = new int[] {4,0,6,2,7,3,5,1};
120
    int status = retCubitSolvedStatus(cubit,numLayers);
121
    return status<0 ? null : buildSolvedQuats(TouchControlOctahedron.FACE_AXIS[mFaceMap[status]],mQuats);
122
    }
123

    
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125

    
126
  public Static4D[] getQuats()
127
    {
128
    if( mQuats==null ) initializeQuats();
129
    return mQuats;
130
    }
131

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

    
134
  public int getSolvedFunctionIndex()
135
    {
136
    return 0;
137
    }
138

    
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140

    
141
  public int getNumStickerTypes(int[] numLayers)
142
    {
143
    return 1;
144
    }
145

    
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147

    
148
  public float[][] getCuts(int[] numLayers)
149
    {
150
    int numL = numLayers[0];
151
    if( numL<2 ) return null;
152

    
153
    if( mCuts==null )
154
      {
155
      mCuts = new float[4][numL-1];
156
      float cut = (SQ6/6)*(2-numL);
157

    
158
      for(int i=0; i<numL-1; i++)
159
        {
160
        mCuts[0][i] = cut;
161
        mCuts[1][i] = cut;
162
        mCuts[2][i] = cut;
163
        mCuts[3][i] = cut;
164
        cut += SQ6/3;
165
        }
166
      }
167

    
168
    return mCuts;
169
    }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172

    
173
  public boolean[][] getLayerRotatable(int[] numLayers)
174
    {
175
    int numAxis = ROT_AXIS.length;
176
    boolean[][] layerRotatable = new boolean[numAxis][];
177

    
178
    for(int i=0; i<numAxis; i++)
179
      {
180
      layerRotatable[i] = new boolean[numLayers[i]];
181
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
182
      }
183

    
184
    return layerRotatable;
185
    }
186

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

    
189
  public int getMovementType()
190
    {
191
    return TC_OCTAHEDRON;
192
    }
193

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

    
196
  public int getMovementSplit()
197
    {
198
    return TYPE_NOT_SPLIT;
199
    }
200

    
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202

    
203
  public int[][][] getEnabled()
204
    {
205
    return new int[][][]
206
      {
207
          {{1,2,3}},{{1,2,3}},{{0,2,3}},{{0,2,3}},{{0,1,3}},{{0,1,3}},{{0,1,2}},{{0,1,2}}
208
      };
209
    }
210

    
211
///////////////////////////////////////////////////////////////////////////////////////////////////
212

    
213
  public float[] getDist3D(int[] numLayers)
214
    {
215
    return null;
216
    }
217

    
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219

    
220
  public int getNumCubitFaces()
221
    {
222
    return 8;
223
    }
224

    
225
///////////////////////////////////////////////////////////////////////////////////////////////////
226

    
227
  private int getNumOctahedrons(int layers)
228
    {
229
    return layers==1 ? 1 : 4*(layers-1)*(layers-1) + 2;
230
    }
231

    
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233

    
234
  private int getNumTetrahedrons(int layers)
235
    {
236
    return 4*layers*(layers-1);
237
    }
238

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

    
241
  private int createOctaPositions(float[][] centers, int index, int layers, float height)
242
    {
243
    float x = (layers-1)*0.5f;
244
    float z = (layers+1)*0.5f;
245

    
246
    for(int i=0; i<layers; i++, index++)
247
      {
248
      z -= 1;
249
      centers[index][0] = x;
250
      centers[index][1] = height;
251
      centers[index][2] = z;
252
      }
253

    
254
    for(int i=0; i<layers-1; i++, index++)
255
      {
256
      x -= 1;
257
      centers[index][0] = x;
258
      centers[index][1] = height;
259
      centers[index][2] = z;
260
      }
261

    
262
    for(int i=0; i<layers-1; i++, index++)
263
      {
264
      z += 1;
265
      centers[index][0] = x;
266
      centers[index][1] = height;
267
      centers[index][2] = z;
268
      }
269

    
270
    for(int i=0; i<layers-2; i++, index++)
271
      {
272
      x += 1;
273
      centers[index][0] = x;
274
      centers[index][1] = height;
275
      centers[index][2] = z;
276
      }
277

    
278
    return index;
279
    }
280

    
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

    
283
  private int createTetraPositions(float[][] centers, int index, int layers, float height)
284
    {
285
    float x = (layers-1)*0.5f;
286
    float z =  layers*0.5f;
287

    
288
    for(int i=0; i<layers-1; i++, index++)
289
      {
290
      z -= 1;
291
      centers[index][0] = x;
292
      centers[index][1] = height;
293
      centers[index][2] = z;
294
      }
295

    
296
    x += 0.5f;
297
    z -= 0.5f;
298

    
299
    for(int i=0; i<layers-1; i++, index++)
300
      {
301
      x -= 1;
302
      centers[index][0] = x;
303
      centers[index][1] = height;
304
      centers[index][2] = z;
305
      }
306

    
307
    x -= 0.5f;
308
    z -= 0.5f;
309

    
310
    for(int i=0; i<layers-1; i++, index++)
311
      {
312
      z += 1;
313
      centers[index][0] = x;
314
      centers[index][1] = height;
315
      centers[index][2] = z;
316
      }
317

    
318
    x -= 0.5f;
319
    z += 0.5f;
320

    
321
    for(int i=0; i<layers-1; i++, index++)
322
      {
323
      x += 1;
324
      centers[index][0] = x;
325
      centers[index][1] = height;
326
      centers[index][2] = z;
327
      }
328

    
329
    return index;
330
    }
331

    
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333

    
334
  public float[][] getCubitPositions(int[] numLayers)
335
    {
336
    int layers = numLayers[0];
337
    int numO = getNumOctahedrons(layers);
338
    int numT = getNumTetrahedrons(layers);
339
    int index = 0;
340
    float height = 0.0f;
341

    
342
    float[][] CENTERS = new float[numO+numT][3];
343

    
344
    index = createOctaPositions(CENTERS,index,layers,height);
345

    
346
    for(int i=layers-1; i>0; i--)
347
      {
348
      height += SQ2/2;
349
      index = createOctaPositions(CENTERS,index,i,+height);
350
      index = createOctaPositions(CENTERS,index,i,-height);
351
      }
352

    
353
    height = SQ2/4;
354

    
355
    for(int i=layers; i>1; i--)
356
      {
357
      index = createTetraPositions(CENTERS,index,i,+height);
358
      index = createTetraPositions(CENTERS,index,i,-height);
359
      height += SQ2/2;
360
      }
361

    
362
    return CENTERS;
363
    }
364

    
365
///////////////////////////////////////////////////////////////////////////////////////////////////
366

    
367
  private int retFaceTetraBelongsTo(int tetra, int numLayers)
368
    {
369
    if( mTetraToFaceMap==null ) mTetraToFaceMap = new int[] {1,2,3,0,5,6,7,4};
370

    
371
    for(int i=numLayers-1; i>0; i--)
372
      {
373
      if( tetra < 8*i ) return mTetraToFaceMap[tetra/i];
374
      tetra -= 8*i;
375
      }
376

    
377
    return -1;
378
    }
379

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

    
382
  public ObjectShape getObjectShape(int variant)
383
    {
384
    int numL = getNumLayers()[0];
385
    int N = numL>3 ? 5:6;
386
    int E = numL>2 ? (numL>3 ? 0:1):2;
387

    
388
    if( variant==0 )
389
      {
390
      double[][] vertices = new double[][]
391
          {
392
             { 0.5,   0.0, 0.5},
393
             { 0.5,   0.0,-0.5},
394
             {-0.5,   0.0,-0.5},
395
             {-0.5,   0.0, 0.5},
396
             { 0.0, SQ2/2, 0.0},
397
             { 0.0,-SQ2/2, 0.0}
398
          };
399

    
400
      int[][] vert_indices = new int[][]
401
          {
402
             {3,0,4},
403
             {0,1,4},
404
             {1,2,4},
405
             {2,3,4},
406
             {5,0,3},
407
             {5,1,0},
408
             {5,2,1},
409
             {5,3,2}
410
          };
411

    
412
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
413
      int[] bandIndices   = new int[] { 0,0,0,0,0,0,0,0 };
414
      float[][] corners   = new float[][] { {0.04f,0.20f} };
415
      int[] cornerIndices = new int[] { 0,0,0,0,0,0 };
416
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
417
      int[] centerIndices = new int[] { 0,0,0,0,0,0 };
418
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
419
      }
420
    else
421
      {
422
      double[][] vertices = new double[][] { {-0.5, SQ2/4, 0.0}, { 0.5, SQ2/4, 0.0}, { 0.0,-SQ2/4, 0.5}, { 0.0,-SQ2/4,-0.5} };
423
      int[][] vert_indices = new int[][]  { {2,1,0}, {2,3,1}, {3,2,0}, {3,0,1} };
424
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
425
      int[] bandIndices   = new int[] { 0,0,0,0 };
426
      float[][] corners   = new float[][] { {0.08f,0.15f} };
427
      int[] cornerIndices = new int[] { 0,0,0,0 };
428
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
429
      int[] centerIndices = new int[] { 0,0,0,0 };
430
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
431
      }
432
    }
433

    
434
///////////////////////////////////////////////////////////////////////////////////////////////////
435

    
436
  public Static4D getQuat(int cubit, int[] numLayers)
437
    {
438
    if( mQuats==null ) initializeQuats();
439

    
440
    int numL = numLayers[0];
441
    int numO = getNumOctahedrons(numL);
442

    
443
    if( cubit<numO ) return mQuats[0];
444

    
445
    switch( retFaceTetraBelongsTo(cubit-numO, numL) )
446
      {
447
      case 0: return mQuats[0];                         // unit quat
448
      case 1: return new Static4D(0,-SQ2/2,0,SQ2/2);    //  90 along Y
449
      case 2: return mQuats[1];                         // 180 along Y
450
      case 3: return new Static4D(0,+SQ2/2,0,SQ2/2);    //  90 along
451
      case 4: return new Static4D(0,     0,1,    0);    // 180 along Z
452
      case 5: return new Static4D(SQ2/2, 0,SQ2/2,0);    //
453
      case 6: return new Static4D(     1,0,0,    0);    // 180 along X
454
      case 7: return new Static4D(-SQ2/2,0,SQ2/2,0);    //
455
      }
456

    
457
    return null;
458
    }
459

    
460
///////////////////////////////////////////////////////////////////////////////////////////////////
461

    
462
  public int getNumCubitVariants(int[] numLayers)
463
    {
464
    return 2;
465
    }
466

    
467
///////////////////////////////////////////////////////////////////////////////////////////////////
468

    
469
  public int getCubitVariant(int cubit, int[] numLayers)
470
    {
471
    return cubit<getNumOctahedrons(numLayers[0]) ? 0 : 1;
472
    }
473

    
474
///////////////////////////////////////////////////////////////////////////////////////////////////
475

    
476
  public int getVariantFaceColor(int variant, int face, int[] numLayers)
477
    {
478
    return 0;
479
    }
480

    
481
///////////////////////////////////////////////////////////////////////////////////////////////////
482

    
483
  public int getCubitFaceColor(int cubit, int face, int[] numLayers)
484
    {
485
    int numL = numLayers[0];
486
    int numO = getNumOctahedrons(numL);
487

    
488
    if( cubit<numO )
489
      {
490
      int axis = 0;
491
      int layer= 1;
492

    
493
      switch(face)
494
        {
495
        case 0: axis = 2; layer =             1; break;
496
        case 1: axis = 0; layer = (1<<(numL-1)); break;
497
        case 2: axis = 3; layer =             1; break;
498
        case 3: axis = 1; layer = (1<<(numL-1)); break;
499
        case 4: axis = 3; layer = (1<<(numL-1)); break;
500
        case 5: axis = 1; layer =             1; break;
501
        case 6: axis = 2; layer = (1<<(numL-1)); break;
502
        case 7: axis = 0; layer =             1; break;
503
        }
504

    
505
      return CUBITS[cubit].getRotRow(axis) == layer ? face : -1;
506
      }
507
    else
508
      {
509
      return face>0 ? -1 : retFaceTetraBelongsTo(cubit-numO, numL);
510
      }
511
    }
512

    
513
///////////////////////////////////////////////////////////////////////////////////////////////////
514

    
515
  public ObjectSticker retSticker(int sticker)
516
    {
517
    if( mStickers==null )
518
      {
519
      float[][] STICKERS = new float[][] { { -0.4330127f, -0.25f, 0.4330127f, -0.25f, 0.0f, 0.5f } };
520
      float radius = 0.06f;
521
      float stroke = 0.07f;
522
      float[] radii = new float[] {radius,radius,radius};
523

    
524
      if( ObjectControl.isInIconMode() )
525
        {
526
        int[] numLayers = getNumLayers();
527

    
528
        switch(numLayers[0])
529
          {
530
          case 2: stroke*=1.4f; break;
531
          case 3: stroke*=2.0f; break;
532
          case 4: stroke*=2.1f; break;
533
          default:stroke*=2.2f; break;
534
          }
535
        }
536

    
537
      mStickers     = new ObjectSticker[STICKERS.length];
538
      mStickers[0]  = new ObjectSticker(STICKERS[0],null,radii,stroke);
539
      }
540

    
541
    return mStickers[sticker];
542
    }
543

    
544
///////////////////////////////////////////////////////////////////////////////////////////////////
545
// PUBLIC API
546

    
547
  public Static3D[] getRotationAxis()
548
    {
549
    return ROT_AXIS;
550
    }
551

    
552
///////////////////////////////////////////////////////////////////////////////////////////////////
553

    
554
  public int[] getBasicAngle()
555
    {
556
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
557
    return mBasicAngle;
558
    }
559

    
560
///////////////////////////////////////////////////////////////////////////////////////////////////
561

    
562
  public ObjectType intGetObjectType(int[] numLayers)
563
    {
564
    switch(numLayers[0])
565
      {
566
      case 2: return ObjectType.DIAM_2;
567
      case 3: return ObjectType.DIAM_3;
568
      case 4: return ObjectType.DIAM_4;
569
      }
570

    
571
    return ObjectType.DIAM_2;
572
    }
573

    
574
///////////////////////////////////////////////////////////////////////////////////////////////////
575

    
576
  public String getObjectName()
577
    {
578
    switch(getNumLayers()[0])
579
      {
580
      case 2: return "Skewb Diamond";
581
      case 3: return "Face Turning Octahedron";
582
      case 4: return "Master Face Turning Octahedron";
583
      }
584

    
585
    return "Skewb Diamond";
586
    }
587

    
588
///////////////////////////////////////////////////////////////////////////////////////////////////
589

    
590
  public String getInventor()
591
    {
592
    switch(getNumLayers()[0])
593
      {
594
      case 2: return "Uwe Meffert";
595
      case 3: return "David Pitcher";
596
      case 4: return "Timur Evbatyrov";
597
      }
598

    
599
    return "Uwe Meffert";
600
    }
601

    
602
///////////////////////////////////////////////////////////////////////////////////////////////////
603

    
604
  public int getYearOfInvention()
605
    {
606
    switch(getNumLayers()[0])
607
      {
608
      case 2: return 1984;
609
      case 3: return 2003;
610
      case 4: return 2011;
611
      }
612
    return 1984;
613
    }
614

    
615
///////////////////////////////////////////////////////////////////////////////////////////////////
616

    
617
  public int getComplexity()
618
    {
619
    switch(getNumLayers()[0])
620
      {
621
      case 2: return 4;
622
      case 3: return 6;
623
      case 4: return 8;
624
      }
625

    
626
    return 0;
627
    }
628
}
(7-7/25)