Project

General

Profile

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

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

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.main.DistortedEffects;
28
import org.distorted.library.main.DistortedTexture;
29
import org.distorted.library.mesh.MeshSquare;
30
import org.distorted.library.type.Static3D;
31
import org.distorted.library.type.Static4D;
32

    
33
import org.distorted.objectlib.R;
34
import org.distorted.objectlib.main.Movement8;
35
import org.distorted.objectlib.main.ObjectControl;
36
import org.distorted.objectlib.main.ObjectType;
37
import org.distorted.objectlib.helpers.ObjectShape;
38
import org.distorted.objectlib.helpers.ObjectSticker;
39
import org.distorted.objectlib.helpers.ScrambleState;
40
import org.distorted.objectlib.main.Twisty8;
41

    
42
///////////////////////////////////////////////////////////////////////////////////////////////////
43

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

    
55
  private ScrambleState[] mStates;
56
  private int[] mBasicAngle;
57
  private int[] mFaceMap;
58
  private float[][] mCuts;
59
  private Static4D[] mQuats;
60
  private int[] mTetraToFaceMap;
61
  private ObjectSticker[] mStickers;
62

    
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64

    
65
  public TwistyDiamond(int[] numL, Static4D quat, Static3D move, Resources res)
66
    {
67
    super(numL, numL[0], quat, move, res);
68
    }
69

    
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71

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

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

    
87
      mStates = new ScrambleState[]
88
        {
89
        new ScrambleState( new int[][] {tmp,tmp,tmp,tmp} )
90
        };
91
      }
92

    
93
    return mStates;
94
    }
95

    
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97

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

    
107
    return 0;
108
    }
109

    
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111

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

    
121
          new Static4D(+SQ2/2,  0.5f,   0.0f,  0.5f ),
122
          new Static4D(-SQ2/2,  0.5f,   0.0f,  0.5f ),
123
          new Static4D(  0.0f,  0.5f, +SQ2/2,  0.5f ),
124
          new Static4D(  0.0f,  0.5f, -SQ2/2,  0.5f ),
125
          new Static4D(+SQ2/2,  0.5f,   0.0f, -0.5f ),
126
          new Static4D(-SQ2/2,  0.5f,   0.0f, -0.5f ),
127
          new Static4D(  0.0f,  0.5f, +SQ2/2, -0.5f ),
128
          new Static4D(  0.0f,  0.5f, -SQ2/2, -0.5f )
129
         };
130
    }
131

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

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

    
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143

    
144
  public Static4D[] getQuats()
145
    {
146
    if( mQuats==null ) initializeQuats();
147
    return mQuats;
148
    }
149

    
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

    
152
  public int getSolvedFunctionIndex()
153
    {
154
    return 0;
155
    }
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158

    
159
  public int getNumStickerTypes(int[] numLayers)
160
    {
161
    return 1;
162
    }
163

    
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165

    
166
  public float[][] getCuts(int[] numLayers)
167
    {
168
    int numL = numLayers[0];
169
    if( numL<2 ) return null;
170

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

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

    
186
    return mCuts;
187
    }
188

    
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190

    
191
  public boolean[][] getLayerRotatable(int[] numLayers)
192
    {
193
    int numAxis = ROT_AXIS.length;
194
    boolean[][] layerRotatable = new boolean[numAxis][];
195

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

    
202
    return layerRotatable;
203
    }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

    
207
  public int getMovementType()
208
    {
209
    return MOVEMENT_OCTAHEDRON;
210
    }
211

    
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213

    
214
  public int getMovementSplit()
215
    {
216
    return TYPE_NOT_SPLIT;
217
    }
218

    
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220

    
221
  public int[][][] getEnabled()
222
    {
223
    return new int[][][]
224
      {
225
          {{1,2,3}},{{1,2,3}},{{0,2,3}},{{0,2,3}},{{0,1,3}},{{0,1,3}},{{0,1,2}},{{0,1,2}}
226
      };
227
    }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230

    
231
  public float[] getDist3D(int[] numLayers)
232
    {
233
    return null;
234
    }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237

    
238
  public int getNumCubitFaces()
239
    {
240
    return 8;
241
    }
242

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

    
245
  private int getNumOctahedrons(int layers)
246
    {
247
    return layers==1 ? 1 : 4*(layers-1)*(layers-1) + 2;
248
    }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
  private int getNumTetrahedrons(int layers)
253
    {
254
    return 4*layers*(layers-1);
255
    }
256

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

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

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

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

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

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

    
296
    return index;
297
    }
298

    
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

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

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

    
314
    x += 0.5f;
315
    z -= 0.5f;
316

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

    
325
    x -= 0.5f;
326
    z -= 0.5f;
327

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

    
336
    x -= 0.5f;
337
    z += 0.5f;
338

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

    
347
    return index;
348
    }
349

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

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

    
360
    float[][] CENTERS = new float[numO+numT][3];
361

    
362
    index = createOctaPositions(CENTERS,index,layers,height);
363

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

    
371
    height = SQ2/4;
372

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

    
380
    return CENTERS;
381
    }
382

    
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384

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

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

    
395
    return -1;
396
    }
397

    
398
///////////////////////////////////////////////////////////////////////////////////////////////////
399

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

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

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

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

    
452
///////////////////////////////////////////////////////////////////////////////////////////////////
453

    
454
  public Static4D getQuat(int cubit, int[] numLayers)
455
    {
456
    if( mQuats==null ) initializeQuats();
457

    
458
    int numL = numLayers[0];
459
    int numO = getNumOctahedrons(numL);
460

    
461
    if( cubit<numO ) return mQuats[0];
462

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

    
475
    return null;
476
    }
477

    
478
///////////////////////////////////////////////////////////////////////////////////////////////////
479

    
480
  public int getNumCubitVariants(int[] numLayers)
481
    {
482
    return 2;
483
    }
484

    
485
///////////////////////////////////////////////////////////////////////////////////////////////////
486

    
487
  public int getCubitVariant(int cubit, int[] numLayers)
488
    {
489
    return cubit<getNumOctahedrons(numLayers[0]) ? 0 : 1;
490
    }
491

    
492
///////////////////////////////////////////////////////////////////////////////////////////////////
493

    
494
  public int getVariantFaceColor(int variant, int face, int[] numLayers)
495
    {
496
    return 0;
497
    }
498

    
499
///////////////////////////////////////////////////////////////////////////////////////////////////
500

    
501
  public int getCubitFaceColor(int cubit, int face, int[] numLayers)
502
    {
503
    int numL = numLayers[0];
504
    int numO = getNumOctahedrons(numL);
505

    
506
    if( cubit<numO )
507
      {
508
      int axis = 0;
509
      int layer= 1;
510

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

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

    
531
///////////////////////////////////////////////////////////////////////////////////////////////////
532

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

    
542
      if( ObjectControl.isInIconMode() )
543
        {
544
        int[] numLayers = getNumLayers();
545

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

    
555
      mStickers     = new ObjectSticker[STICKERS.length];
556
      mStickers[0]  = new ObjectSticker(STICKERS[0],null,radii,stroke);
557
      }
558

    
559
    return mStickers[sticker];
560
    }
561

    
562
///////////////////////////////////////////////////////////////////////////////////////////////////
563
// PUBLIC API
564

    
565
  public Static3D[] getRotationAxis()
566
    {
567
    return ROT_AXIS;
568
    }
569

    
570
///////////////////////////////////////////////////////////////////////////////////////////////////
571

    
572
  public int[] getBasicAngle()
573
    {
574
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
575
    return mBasicAngle;
576
    }
577

    
578
///////////////////////////////////////////////////////////////////////////////////////////////////
579

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

    
589
    return ObjectType.DIAM_2;
590
    }
591

    
592
///////////////////////////////////////////////////////////////////////////////////////////////////
593

    
594
  public int getObjectName(int[] numLayers)
595
    {
596
    switch(numLayers[0])
597
      {
598
      case 2: return R.string.diam2;
599
      case 3: return R.string.diam3;
600
      case 4: return R.string.diam4;
601
      }
602

    
603
    return 0;
604
    }
605

    
606
///////////////////////////////////////////////////////////////////////////////////////////////////
607

    
608
  public int getInventor(int[] numLayers)
609
    {
610
    switch(numLayers[0])
611
      {
612
      case 2: return R.string.diam2_inventor;
613
      case 3: return R.string.diam3_inventor;
614
      case 4: return R.string.diam4_inventor;
615
      }
616

    
617
    return 0;
618
    }
619

    
620
///////////////////////////////////////////////////////////////////////////////////////////////////
621

    
622
  public int getYearOfInvention(int[] numLayers)
623
    {
624
    switch(numLayers[0])
625
      {
626
      case 2: return 1984;
627
      case 3: return 2003;
628
      case 4: return 2011;
629
      }
630
    return 1984;
631
    }
632

    
633
///////////////////////////////////////////////////////////////////////////////////////////////////
634

    
635
  public int getComplexity(int[] numLayers)
636
    {
637
    switch(numLayers[0])
638
      {
639
      case 2: return 4;
640
      case 3: return 6;
641
      case 4: return 8;
642
      }
643

    
644
    return 0;
645
    }
646
}
(7-7/25)