Project

General

Profile

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

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

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.main.Movement.MOVEMENT_OCTAHEDRON;
23
import static org.distorted.objectlib.main.Movement.TYPE_NOT_SPLIT;
24

    
25
import android.content.res.Resources;
26

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

    
30
import org.distorted.objectlib.R;
31
import org.distorted.objectlib.main.Movement8;
32
import org.distorted.objectlib.main.ObjectControl;
33
import org.distorted.objectlib.main.ObjectType;
34
import org.distorted.objectlib.helpers.ObjectShape;
35
import org.distorted.objectlib.helpers.ObjectSticker;
36
import org.distorted.objectlib.helpers.ScrambleState;
37
import org.distorted.objectlib.main.Twisty8;
38

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

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

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

    
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61

    
62
  public TwistyDiamond(int[] numL, Static4D quat, Static3D move, Resources res)
63
    {
64
    super(numL, numL[0], quat, move, res);
65
    }
66

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

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

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

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

    
90
    return mStates;
91
    }
92

    
93
///////////////////////////////////////////////////////////////////////////////////////////////////
94

    
95
  protected int getResource(int[] numLayers)
96
    {
97
    switch(numLayers[0])
98
      {
99
      case 2: return R.raw.diam_2;
100
      case 3: return R.raw.diam_3;
101
      case 4: return R.raw.diam_4;
102
      }
103

    
104
    return 0;
105
    }
106

    
107
///////////////////////////////////////////////////////////////////////////////////////////////////
108

    
109
  private void initializeQuats()
110
    {
111
    mQuats = new Static4D[]
112
         {
113
          new Static4D(  0.0f,  0.0f,   0.0f,  1.0f ),
114
          new Static4D(  0.0f,  1.0f,   0.0f,  0.0f ),
115
          new Static4D(+SQ2/2,  0.0f, -SQ2/2,  0.0f ),
116
          new Static4D(-SQ2/2,  0.0f, -SQ2/2,  0.0f ),
117

    
118
          new Static4D(+SQ2/2,  0.5f,   0.0f,  0.5f ),
119
          new Static4D(-SQ2/2,  0.5f,   0.0f,  0.5f ),
120
          new Static4D(  0.0f,  0.5f, +SQ2/2,  0.5f ),
121
          new Static4D(  0.0f,  0.5f, -SQ2/2,  0.5f ),
122
          new Static4D(+SQ2/2,  0.5f,   0.0f, -0.5f ),
123
          new Static4D(-SQ2/2,  0.5f,   0.0f, -0.5f ),
124
          new Static4D(  0.0f,  0.5f, +SQ2/2, -0.5f ),
125
          new Static4D(  0.0f,  0.5f, -SQ2/2, -0.5f )
126
         };
127
    }
128

    
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130

    
131
  public int[] getSolvedQuats(int cubit, int[] numLayers)
132
    {
133
    if( mQuats==null ) initializeQuats();
134
    if( mFaceMap==null ) mFaceMap = new int[] {4,0,6,2,7,3,5,1};
135
    int status = retCubitSolvedStatus(cubit,numLayers);
136
    return status<0 ? null : buildSolvedQuats(Movement8.FACE_AXIS[mFaceMap[status]],mQuats);
137
    }
138

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

    
141
  public Static4D[] getQuats()
142
    {
143
    if( mQuats==null ) initializeQuats();
144
    return mQuats;
145
    }
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148

    
149
  public int getSolvedFunctionIndex()
150
    {
151
    return 0;
152
    }
153

    
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155

    
156
  public int getNumStickerTypes(int[] numLayers)
157
    {
158
    return 1;
159
    }
160

    
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

    
163
  public float[][] getCuts(int[] numLayers)
164
    {
165
    int numL = numLayers[0];
166
    if( numL<2 ) return null;
167

    
168
    if( mCuts==null )
169
      {
170
      mCuts = new float[4][numL-1];
171
      float cut = (SQ6/6)*(2-numL);
172

    
173
      for(int i=0; i<numL-1; i++)
174
        {
175
        mCuts[0][i] = cut;
176
        mCuts[1][i] = cut;
177
        mCuts[2][i] = cut;
178
        mCuts[3][i] = cut;
179
        cut += SQ6/3;
180
        }
181
      }
182

    
183
    return mCuts;
184
    }
185

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

    
188
  public boolean[][] getLayerRotatable(int[] numLayers)
189
    {
190
    int numAxis = ROT_AXIS.length;
191
    boolean[][] layerRotatable = new boolean[numAxis][];
192

    
193
    for(int i=0; i<numAxis; i++)
194
      {
195
      layerRotatable[i] = new boolean[numLayers[i]];
196
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
197
      }
198

    
199
    return layerRotatable;
200
    }
201

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
  public int getMovementType()
205
    {
206
    return MOVEMENT_OCTAHEDRON;
207
    }
208

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

    
211
  public int getMovementSplit()
212
    {
213
    return TYPE_NOT_SPLIT;
214
    }
215

    
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217

    
218
  public int[][][] getEnabled()
219
    {
220
    return new int[][][]
221
      {
222
          {{1,2,3}},{{1,2,3}},{{0,2,3}},{{0,2,3}},{{0,1,3}},{{0,1,3}},{{0,1,2}},{{0,1,2}}
223
      };
224
    }
225

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

    
228
  public float[] getDist3D(int[] numLayers)
229
    {
230
    return null;
231
    }
232

    
233
///////////////////////////////////////////////////////////////////////////////////////////////////
234

    
235
  public int getNumCubitFaces()
236
    {
237
    return 8;
238
    }
239

    
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241

    
242
  private int getNumOctahedrons(int layers)
243
    {
244
    return layers==1 ? 1 : 4*(layers-1)*(layers-1) + 2;
245
    }
246

    
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248

    
249
  private int getNumTetrahedrons(int layers)
250
    {
251
    return 4*layers*(layers-1);
252
    }
253

    
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255

    
256
  private int createOctaPositions(float[][] centers, int index, int layers, float height)
257
    {
258
    float x = (layers-1)*0.5f;
259
    float z = (layers+1)*0.5f;
260

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

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

    
277
    for(int i=0; i<layers-1; i++, index++)
278
      {
279
      z += 1;
280
      centers[index][0] = x;
281
      centers[index][1] = height;
282
      centers[index][2] = z;
283
      }
284

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

    
293
    return index;
294
    }
295

    
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297

    
298
  private int createTetraPositions(float[][] centers, int index, int layers, float height)
299
    {
300
    float x = (layers-1)*0.5f;
301
    float z =  layers*0.5f;
302

    
303
    for(int i=0; i<layers-1; i++, index++)
304
      {
305
      z -= 1;
306
      centers[index][0] = x;
307
      centers[index][1] = height;
308
      centers[index][2] = z;
309
      }
310

    
311
    x += 0.5f;
312
    z -= 0.5f;
313

    
314
    for(int i=0; i<layers-1; i++, index++)
315
      {
316
      x -= 1;
317
      centers[index][0] = x;
318
      centers[index][1] = height;
319
      centers[index][2] = z;
320
      }
321

    
322
    x -= 0.5f;
323
    z -= 0.5f;
324

    
325
    for(int i=0; i<layers-1; i++, index++)
326
      {
327
      z += 1;
328
      centers[index][0] = x;
329
      centers[index][1] = height;
330
      centers[index][2] = z;
331
      }
332

    
333
    x -= 0.5f;
334
    z += 0.5f;
335

    
336
    for(int i=0; i<layers-1; i++, index++)
337
      {
338
      x += 1;
339
      centers[index][0] = x;
340
      centers[index][1] = height;
341
      centers[index][2] = z;
342
      }
343

    
344
    return index;
345
    }
346

    
347
///////////////////////////////////////////////////////////////////////////////////////////////////
348

    
349
  public float[][] getCubitPositions(int[] numLayers)
350
    {
351
    int layers = numLayers[0];
352
    int numO = getNumOctahedrons(layers);
353
    int numT = getNumTetrahedrons(layers);
354
    int index = 0;
355
    float height = 0.0f;
356

    
357
    float[][] CENTERS = new float[numO+numT][3];
358

    
359
    index = createOctaPositions(CENTERS,index,layers,height);
360

    
361
    for(int i=layers-1; i>0; i--)
362
      {
363
      height += SQ2/2;
364
      index = createOctaPositions(CENTERS,index,i,+height);
365
      index = createOctaPositions(CENTERS,index,i,-height);
366
      }
367

    
368
    height = SQ2/4;
369

    
370
    for(int i=layers; i>1; i--)
371
      {
372
      index = createTetraPositions(CENTERS,index,i,+height);
373
      index = createTetraPositions(CENTERS,index,i,-height);
374
      height += SQ2/2;
375
      }
376

    
377
    return CENTERS;
378
    }
379

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

    
382
  private int retFaceTetraBelongsTo(int tetra, int numLayers)
383
    {
384
    if( mTetraToFaceMap==null ) mTetraToFaceMap = new int[] {1,2,3,0,5,6,7,4};
385

    
386
    for(int i=numLayers-1; i>0; i--)
387
      {
388
      if( tetra < 8*i ) return mTetraToFaceMap[tetra/i];
389
      tetra -= 8*i;
390
      }
391

    
392
    return -1;
393
    }
394

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

    
397
  public ObjectShape getObjectShape(int variant)
398
    {
399
    int numL = getNumLayers()[0];
400
    int N = numL>3 ? 5:6;
401
    int E = numL>2 ? (numL>3 ? 0:1):2;
402

    
403
    if( variant==0 )
404
      {
405
      double[][] vertices = new double[][]
406
          {
407
             { 0.5,   0.0, 0.5},
408
             { 0.5,   0.0,-0.5},
409
             {-0.5,   0.0,-0.5},
410
             {-0.5,   0.0, 0.5},
411
             { 0.0, SQ2/2, 0.0},
412
             { 0.0,-SQ2/2, 0.0}
413
          };
414

    
415
      int[][] vert_indices = new int[][]
416
          {
417
             {3,0,4},
418
             {0,1,4},
419
             {1,2,4},
420
             {2,3,4},
421
             {5,0,3},
422
             {5,1,0},
423
             {5,2,1},
424
             {5,3,2}
425
          };
426

    
427
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
428
      int[] bandIndices   = new int[] { 0,0,0,0,0,0,0,0 };
429
      float[][] corners   = new float[][] { {0.04f,0.20f} };
430
      int[] cornerIndices = new int[] { 0,0,0,0,0,0 };
431
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
432
      int[] centerIndices = new int[] { 0,0,0,0,0,0 };
433
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
434
      }
435
    else
436
      {
437
      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} };
438
      int[][] vert_indices = new int[][]  { {2,1,0}, {2,3,1}, {3,2,0}, {3,0,1} };
439
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
440
      int[] bandIndices   = new int[] { 0,0,0,0 };
441
      float[][] corners   = new float[][] { {0.08f,0.15f} };
442
      int[] cornerIndices = new int[] { 0,0,0,0 };
443
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
444
      int[] centerIndices = new int[] { 0,0,0,0 };
445
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
446
      }
447
    }
448

    
449
///////////////////////////////////////////////////////////////////////////////////////////////////
450

    
451
  public Static4D getQuat(int cubit, int[] numLayers)
452
    {
453
    if( mQuats==null ) initializeQuats();
454

    
455
    int numL = numLayers[0];
456
    int numO = getNumOctahedrons(numL);
457

    
458
    if( cubit<numO ) return mQuats[0];
459

    
460
    switch( retFaceTetraBelongsTo(cubit-numO, numL) )
461
      {
462
      case 0: return mQuats[0];                         // unit quat
463
      case 1: return new Static4D(0,-SQ2/2,0,SQ2/2);    //  90 along Y
464
      case 2: return mQuats[1];                         // 180 along Y
465
      case 3: return new Static4D(0,+SQ2/2,0,SQ2/2);    //  90 along
466
      case 4: return new Static4D(0,     0,1,    0);    // 180 along Z
467
      case 5: return new Static4D(SQ2/2, 0,SQ2/2,0);    //
468
      case 6: return new Static4D(     1,0,0,    0);    // 180 along X
469
      case 7: return new Static4D(-SQ2/2,0,SQ2/2,0);    //
470
      }
471

    
472
    return null;
473
    }
474

    
475
///////////////////////////////////////////////////////////////////////////////////////////////////
476

    
477
  public int getNumCubitVariants(int[] numLayers)
478
    {
479
    return 2;
480
    }
481

    
482
///////////////////////////////////////////////////////////////////////////////////////////////////
483

    
484
  public int getCubitVariant(int cubit, int[] numLayers)
485
    {
486
    return cubit<getNumOctahedrons(numLayers[0]) ? 0 : 1;
487
    }
488

    
489
///////////////////////////////////////////////////////////////////////////////////////////////////
490

    
491
  public int getVariantFaceColor(int variant, int face, int[] numLayers)
492
    {
493
    return 0;
494
    }
495

    
496
///////////////////////////////////////////////////////////////////////////////////////////////////
497

    
498
  public int getCubitFaceColor(int cubit, int face, int[] numLayers)
499
    {
500
    int numL = numLayers[0];
501
    int numO = getNumOctahedrons(numL);
502

    
503
    if( cubit<numO )
504
      {
505
      int axis = 0;
506
      int layer= 1;
507

    
508
      switch(face)
509
        {
510
        case 0: axis = 2; layer =             1; break;
511
        case 1: axis = 0; layer = (1<<(numL-1)); break;
512
        case 2: axis = 3; layer =             1; break;
513
        case 3: axis = 1; layer = (1<<(numL-1)); break;
514
        case 4: axis = 3; layer = (1<<(numL-1)); break;
515
        case 5: axis = 1; layer =             1; break;
516
        case 6: axis = 2; layer = (1<<(numL-1)); break;
517
        case 7: axis = 0; layer =             1; break;
518
        }
519

    
520
      return CUBITS[cubit].getRotRow(axis) == layer ? face : -1;
521
      }
522
    else
523
      {
524
      return face>0 ? -1 : retFaceTetraBelongsTo(cubit-numO, numL);
525
      }
526
    }
527

    
528
///////////////////////////////////////////////////////////////////////////////////////////////////
529

    
530
  public ObjectSticker retSticker(int sticker)
531
    {
532
    if( mStickers==null )
533
      {
534
      float[][] STICKERS = new float[][] { { -0.4330127f, -0.25f, 0.4330127f, -0.25f, 0.0f, 0.5f } };
535
      float radius = 0.06f;
536
      float stroke = 0.07f;
537
      float[] radii = new float[] {radius,radius,radius};
538

    
539
      if( ObjectControl.isInIconMode() )
540
        {
541
        int[] numLayers = getNumLayers();
542

    
543
        switch(numLayers[0])
544
          {
545
          case 2: stroke*=1.4f; break;
546
          case 3: stroke*=2.0f; break;
547
          case 4: stroke*=2.1f; break;
548
          default:stroke*=2.2f; break;
549
          }
550
        }
551

    
552
      mStickers     = new ObjectSticker[STICKERS.length];
553
      mStickers[0]  = new ObjectSticker(STICKERS[0],null,radii,stroke);
554
      }
555

    
556
    return mStickers[sticker];
557
    }
558

    
559
///////////////////////////////////////////////////////////////////////////////////////////////////
560
// PUBLIC API
561

    
562
  public Static3D[] getRotationAxis()
563
    {
564
    return ROT_AXIS;
565
    }
566

    
567
///////////////////////////////////////////////////////////////////////////////////////////////////
568

    
569
  public int[] getBasicAngle()
570
    {
571
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
572
    return mBasicAngle;
573
    }
574

    
575
///////////////////////////////////////////////////////////////////////////////////////////////////
576

    
577
  public ObjectType intGetObjectType(int[] numLayers)
578
    {
579
    switch(numLayers[0])
580
      {
581
      case 2: return ObjectType.DIAM_2;
582
      case 3: return ObjectType.DIAM_3;
583
      case 4: return ObjectType.DIAM_4;
584
      }
585

    
586
    return ObjectType.DIAM_2;
587
    }
588

    
589
///////////////////////////////////////////////////////////////////////////////////////////////////
590

    
591
  public String getObjectName()
592
    {
593
    switch(getNumLayers()[0])
594
      {
595
      case 2: return "Skewb Diamond";
596
      case 3: return "Face Turning Octahedron";
597
      case 4: return "Master Face Turning Octahedron";
598
      }
599

    
600
    return "Skewb Diamond";
601
    }
602

    
603
///////////////////////////////////////////////////////////////////////////////////////////////////
604

    
605
  public String getInventor()
606
    {
607
    switch(getNumLayers()[0])
608
      {
609
      case 2: return "Uwe Meffert";
610
      case 3: return "David Pitcher";
611
      case 4: return "Timur Evbatyrov";
612
      }
613

    
614
    return "Uwe Meffert";
615
    }
616

    
617
///////////////////////////////////////////////////////////////////////////////////////////////////
618

    
619
  public int getYearOfInvention()
620
    {
621
    switch(getNumLayers()[0])
622
      {
623
      case 2: return 1984;
624
      case 3: return 2003;
625
      case 4: return 2011;
626
      }
627
    return 1984;
628
    }
629

    
630
///////////////////////////////////////////////////////////////////////////////////////////////////
631

    
632
  public int getComplexity()
633
    {
634
    switch(getNumLayers()[0])
635
      {
636
      case 2: return 4;
637
      case 3: return 6;
638
      case 4: return 8;
639
      }
640

    
641
    return 0;
642
    }
643
}
(7-7/25)