Project

General

Profile

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

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

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.helpers.ObjectFaceShape;
31
import org.distorted.objectlib.touchcontrol.TouchControlOctahedron;
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.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

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

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

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

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

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

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

    
88
    return mStates;
89
    }
90

    
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

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

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

    
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114

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

    
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124

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

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

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

    
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139

    
140
  public float[][] getCuts(int[] numLayers)
141
    {
142
    int numL = numLayers[0];
143
    if( numL<2 ) return null;
144

    
145
    if( mCuts==null )
146
      {
147
      mCuts = new float[4][numL-1];
148
      float cut = (SQ6/6)*(2-numL);
149

    
150
      for(int i=0; i<numL-1; i++)
151
        {
152
        mCuts[0][i] = cut;
153
        mCuts[1][i] = cut;
154
        mCuts[2][i] = cut;
155
        mCuts[3][i] = cut;
156
        cut += SQ6/3;
157
        }
158
      }
159

    
160
    return mCuts;
161
    }
162

    
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164

    
165
  public boolean[][] getLayerRotatable(int[] numLayers)
166
    {
167
    int numAxis = ROT_AXIS.length;
168
    boolean[][] layerRotatable = new boolean[numAxis][];
169

    
170
    for(int i=0; i<numAxis; i++)
171
      {
172
      layerRotatable[i] = new boolean[numLayers[i]];
173
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
174
      }
175

    
176
    return layerRotatable;
177
    }
178

    
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180

    
181
  public int getTouchControlType()
182
    {
183
    return TC_OCTAHEDRON;
184
    }
185

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

    
188
  public int getTouchControlSplit()
189
    {
190
    return TYPE_NOT_SPLIT;
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
  public int[][][] getEnabled()
196
    {
197
    return new int[][][]
198
      {
199
          {{1,2,3}},{{1,2,3}},{{0,2,3}},{{0,2,3}},{{0,1,3}},{{0,1,3}},{{0,1,2}},{{0,1,2}}
200
      };
201
    }
202

    
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204

    
205
  public float[] getDist3D(int[] numLayers)
206
    {
207
    return null;
208
    }
209

    
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211

    
212
  private int getNumOctahedrons(int layers)
213
    {
214
    return layers==1 ? 1 : 4*(layers-1)*(layers-1) + 2;
215
    }
216

    
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218

    
219
  private int getNumTetrahedrons(int layers)
220
    {
221
    return 4*layers*(layers-1);
222
    }
223

    
224
///////////////////////////////////////////////////////////////////////////////////////////////////
225

    
226
  private int createOctaPositions(float[][] centers, int index, int layers, float height)
227
    {
228
    float x = (layers-1)*0.5f;
229
    float z = (layers+1)*0.5f;
230

    
231
    for(int i=0; i<layers; i++, index++)
232
      {
233
      z -= 1;
234
      centers[index][0] = x;
235
      centers[index][1] = height;
236
      centers[index][2] = z;
237
      }
238

    
239
    for(int i=0; i<layers-1; i++, index++)
240
      {
241
      x -= 1;
242
      centers[index][0] = x;
243
      centers[index][1] = height;
244
      centers[index][2] = z;
245
      }
246

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

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

    
263
    return index;
264
    }
265

    
266
///////////////////////////////////////////////////////////////////////////////////////////////////
267

    
268
  private int createTetraPositions(float[][] centers, int index, int layers, float height)
269
    {
270
    float x = (layers-1)*0.5f;
271
    float z =  layers*0.5f;
272

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

    
281
    x += 0.5f;
282
    z -= 0.5f;
283

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

    
292
    x -= 0.5f;
293
    z -= 0.5f;
294

    
295
    for(int i=0; i<layers-1; i++, index++)
296
      {
297
      z += 1;
298
      centers[index][0] = x;
299
      centers[index][1] = height;
300
      centers[index][2] = z;
301
      }
302

    
303
    x -= 0.5f;
304
    z += 0.5f;
305

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

    
314
    return index;
315
    }
316

    
317
///////////////////////////////////////////////////////////////////////////////////////////////////
318

    
319
  public float[][] getCubitPositions(int[] numLayers)
320
    {
321
    int layers = numLayers[0];
322
    int numO = getNumOctahedrons(layers);
323
    int numT = getNumTetrahedrons(layers);
324
    int index = 0;
325
    float height = 0.0f;
326

    
327
    float[][] CENTERS = new float[numO+numT][3];
328

    
329
    index = createOctaPositions(CENTERS,index,layers,height);
330

    
331
    for(int i=layers-1; i>0; i--)
332
      {
333
      height += SQ2/2;
334
      index = createOctaPositions(CENTERS,index,i,+height);
335
      index = createOctaPositions(CENTERS,index,i,-height);
336
      }
337

    
338
    height = SQ2/4;
339

    
340
    for(int i=layers; i>1; i--)
341
      {
342
      index = createTetraPositions(CENTERS,index,i,+height);
343
      index = createTetraPositions(CENTERS,index,i,-height);
344
      height += SQ2/2;
345
      }
346

    
347
    return CENTERS;
348
    }
349

    
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351

    
352
  private int retFaceTetraBelongsTo(int tetra, int numLayers)
353
    {
354
    if( mTetraToFaceMap==null ) mTetraToFaceMap = new int[] {1,2,3,0,5,6,7,4};
355

    
356
    for(int i=numLayers-1; i>0; i--)
357
      {
358
      if( tetra < 8*i ) return mTetraToFaceMap[tetra/i];
359
      tetra -= 8*i;
360
      }
361

    
362
    return -1;
363
    }
364

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

    
367
  public ObjectShape getObjectShape(int variant)
368
    {
369
    if( variant==0 )
370
      {
371
      float[][] vertices =
372
          {
373
             { 0.5f,  0.0f, 0.5f},
374
             { 0.5f,  0.0f,-0.5f},
375
             {-0.5f,  0.0f,-0.5f},
376
             {-0.5f,  0.0f, 0.5f},
377
             { 0.0f, SQ2/2, 0.0f},
378
             { 0.0f,-SQ2/2, 0.0f}
379
          };
380

    
381
      int[][] indices =
382
          {
383
             {3,0,4},
384
             {0,1,4},
385
             {1,2,4},
386
             {2,3,4},
387
             {5,0,3},
388
             {5,1,0},
389
             {5,2,1},
390
             {5,3,2}
391
          };
392

    
393
      return new ObjectShape(vertices, indices, 1);
394
      }
395
    else
396
      {
397
      float[][] vertices= { {-0.5f, SQ2/4, 0.0f}, { 0.5f, SQ2/4, 0.0f}, { 0.0f,-SQ2/4, 0.5f}, { 0.0f,-SQ2/4,-0.5f} };
398
      int[][] indices   = { {2,1,0}, {2,3,1}, {3,2,0}, {3,0,1} };
399
      return new ObjectShape(vertices, indices, 1);
400
      }
401
    }
402

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

    
405
  public ObjectFaceShape getObjectFaceShape(int variant)
406
    {
407
    int numL = getNumLayers()[0];
408
    int N = numL>3 ? 5:6;
409
    int E = numL>2 ? (numL>3 ? 0:1) : 2;
410

    
411
    if( variant==0 )
412
      {
413
      float[][] bands     = { {0.05f,35,0.5f,0.8f,N,E,E} };
414
      int[] bandIndices   = { 0,0,0,0,0,0,0,0 };
415
      float[][] corners   = { {0.04f,0.20f} };
416
      int[] cornerIndices = { 0,0,0,0,0,0 };
417
      float[][] centers   = { {0.0f, 0.0f, 0.0f} };
418
      int[] centerIndices = { 0,0,0,0,0,0 };
419
      return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
420
      }
421
    else
422
      {
423
      float[][] bands     = { {0.05f,35,0.5f,0.8f,N,E,E} };
424
      int[] bandIndices   = { 0,0,0,0 };
425
      float[][] corners   = { {0.08f,0.15f} };
426
      int[] cornerIndices = { 0,0,0,0 };
427
      float[][] centers   = { {0.0f, 0.0f, 0.0f} };
428
      int[] centerIndices = { 0,0,0,0 };
429
      return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
430
      }
431
    }
432

    
433
///////////////////////////////////////////////////////////////////////////////////////////////////
434

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

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

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

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

    
456
    return null;
457
    }
458

    
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460

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

    
466
///////////////////////////////////////////////////////////////////////////////////////////////////
467

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

    
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474

    
475
  public int getCubitFaceColor(int cubit, int face, int[] numLayers)
476
    {
477
    int numL = numLayers[0];
478
    int numO = getNumOctahedrons(numL);
479

    
480
    if( cubit<numO )
481
      {
482
      int axis = 0;
483
      int layer= 1;
484

    
485
      switch(face)
486
        {
487
        case 0: axis = 2; layer =             1; break;
488
        case 1: axis = 0; layer = (1<<(numL-1)); break;
489
        case 2: axis = 3; layer =             1; break;
490
        case 3: axis = 1; layer = (1<<(numL-1)); break;
491
        case 4: axis = 3; layer = (1<<(numL-1)); break;
492
        case 5: axis = 1; layer =             1; break;
493
        case 6: axis = 2; layer = (1<<(numL-1)); break;
494
        case 7: axis = 0; layer =             1; break;
495
        }
496

    
497
      return CUBITS[cubit].getRotRow(axis) == layer ? face : -1;
498
      }
499
    else
500
      {
501
      return face>0 ? -1 : retFaceTetraBelongsTo(cubit-numO, numL);
502
      }
503
    }
504

    
505
///////////////////////////////////////////////////////////////////////////////////////////////////
506

    
507
  public float getStickerRadius()
508
    {
509
    return 0.08f;
510
    }
511

    
512
///////////////////////////////////////////////////////////////////////////////////////////////////
513

    
514
  public float getStickerStroke()
515
    {
516
    float stroke = 0.08f;
517

    
518
    if( ObjectControl.isInIconMode() )
519
      {
520
      int[] numLayers = getNumLayers();
521

    
522
      switch(numLayers[0])
523
        {
524
        case 2: stroke*=1.4f; break;
525
        case 3: stroke*=2.0f; break;
526
        case 4: stroke*=2.1f; break;
527
        default:stroke*=2.2f; break;
528
        }
529
      }
530

    
531
    return stroke;
532
    }
533

    
534
///////////////////////////////////////////////////////////////////////////////////////////////////
535

    
536
  public float[][] getStickerAngles()
537
    {
538
    return null;
539
    }
540

    
541
///////////////////////////////////////////////////////////////////////////////////////////////////
542
// PUBLIC API
543

    
544
  public Static3D[] getRotationAxis()
545
    {
546
    return ROT_AXIS;
547
    }
548

    
549
///////////////////////////////////////////////////////////////////////////////////////////////////
550

    
551
  public int[] getBasicAngle()
552
    {
553
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
554
    return mBasicAngle;
555
    }
556

    
557
///////////////////////////////////////////////////////////////////////////////////////////////////
558

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

    
568
    return ObjectType.DIAM_2;
569
    }
570

    
571
///////////////////////////////////////////////////////////////////////////////////////////////////
572

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

    
582
    return "Skewb Diamond";
583
    }
584

    
585
///////////////////////////////////////////////////////////////////////////////////////////////////
586

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

    
596
    return "Uwe Meffert";
597
    }
598

    
599
///////////////////////////////////////////////////////////////////////////////////////////////////
600

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

    
612
///////////////////////////////////////////////////////////////////////////////////////////////////
613

    
614
  public int getComplexity()
615
    {
616
    switch(getNumLayers()[0])
617
      {
618
      case 2: return 1;
619
      case 3: return 2;
620
      case 4: return 3;
621
      }
622

    
623
    return 0;
624
    }
625
}
(7-7/26)