Project

General

Profile

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

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

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.TYPE_NOT_SPLIT;
23

    
24
import android.content.res.Resources;
25

    
26
import org.distorted.library.main.DistortedEffects;
27
import org.distorted.library.main.DistortedTexture;
28
import org.distorted.library.mesh.MeshSquare;
29
import org.distorted.library.type.Static3D;
30
import org.distorted.library.type.Static4D;
31

    
32
import org.distorted.objectlib.R;
33
import org.distorted.objectlib.main.Movement;
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 static final int[][][] ENABLED = new int[][][]
56
      {
57
          {{1,2,3}},{{1,2,3}},{{0,2,3}},{{0,2,3}},{{0,1,3}},{{0,1,3}},{{0,1,2}},{{0,1,2}}
58
      };
59

    
60
  private ScrambleState[] mStates;
61
  private int[] mBasicAngle;
62
  private int[] mFaceMap;
63
  private float[][] mCuts;
64
  private boolean[][] mLayerRotatable;
65
  private Static4D[] mQuats;
66
  private int[] mTetraToFaceMap;
67
  private ObjectSticker[] mStickers;
68
  private Movement mMovement;
69

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

    
72
  public TwistyDiamond(int[] numL, Static4D quat, Static3D move, DistortedTexture texture,
73
                       MeshSquare mesh, DistortedEffects effects, Resources res, int surfaceW, int surfaceH)
74
    {
75
    super(numL, numL[0], quat, move, texture, mesh, effects, res, surfaceW, surfaceH);
76
    }
77

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

    
80
  protected ScrambleState[] getScrambleStates()
81
    {
82
    if( mStates==null )
83
      {
84
      int[] numLayers = getNumLayers();
85
      int numL = numLayers[0];
86
      int[] tmp = new int[3*2*numL];
87

    
88
      for(int i=0; i<2*numL; i++)
89
        {
90
        tmp[3*i  ] = (i<numL) ?  i:i-numL;
91
        tmp[3*i+1] = (i%2==0) ? -1:1;
92
        tmp[3*i+2] = 0;
93
        }
94

    
95
      mStates = new ScrambleState[]
96
        {
97
        new ScrambleState( new int[][] {tmp,tmp,tmp,tmp} )
98
        };
99
      }
100

    
101
    return mStates;
102
    }
103

    
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105

    
106
  protected int getResource(int[] numLayers)
107
    {
108
    switch(numLayers[0])
109
      {
110
      case 2: return R.raw.diam2;
111
      case 3: return R.raw.diam3;
112
      case 4: return R.raw.diam4;
113
      }
114

    
115
    return 0;
116
    }
117

    
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119

    
120
  private void initializeQuats()
121
    {
122
    mQuats = new Static4D[]
123
         {
124
          new Static4D(  0.0f,  0.0f,   0.0f,  1.0f ),
125
          new Static4D(  0.0f,  1.0f,   0.0f,  0.0f ),
126
          new Static4D(+SQ2/2,  0.0f, -SQ2/2,  0.0f ),
127
          new Static4D(-SQ2/2,  0.0f, -SQ2/2,  0.0f ),
128

    
129
          new Static4D(+SQ2/2,  0.5f,   0.0f,  0.5f ),
130
          new Static4D(-SQ2/2,  0.5f,   0.0f,  0.5f ),
131
          new Static4D(  0.0f,  0.5f, +SQ2/2,  0.5f ),
132
          new Static4D(  0.0f,  0.5f, -SQ2/2,  0.5f ),
133
          new Static4D(+SQ2/2,  0.5f,   0.0f, -0.5f ),
134
          new Static4D(-SQ2/2,  0.5f,   0.0f, -0.5f ),
135
          new Static4D(  0.0f,  0.5f, +SQ2/2, -0.5f ),
136
          new Static4D(  0.0f,  0.5f, -SQ2/2, -0.5f )
137
         };
138
    }
139

    
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141

    
142
  protected int[] getSolvedQuats(int cubit, int[] numLayers)
143
    {
144
    if( mQuats==null ) initializeQuats();
145
    if( mFaceMap==null ) mFaceMap = new int[] {4,0,6,2,7,3,5,1};
146
    int status = retCubitSolvedStatus(cubit,numLayers);
147
    return status<0 ? null : buildSolvedQuats(Movement8.FACE_AXIS[mFaceMap[status]],mQuats);
148
    }
149

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

    
152
  protected Static4D[] getQuats()
153
    {
154
    if( mQuats==null ) initializeQuats();
155
    return mQuats;
156
    }
157

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159

    
160
  protected int getSolvedFunctionIndex()
161
    {
162
    return 0;
163
    }
164

    
165
///////////////////////////////////////////////////////////////////////////////////////////////////
166

    
167
  protected int getNumStickerTypes(int[] numLayers)
168
    {
169
    return 1;
170
    }
171

    
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173

    
174
  protected float[][] getCuts(int[] numLayers)
175
    {
176
    int numL = numLayers[0];
177
    if( numL<2 ) return null;
178

    
179
    if( mCuts==null )
180
      {
181
      mCuts = new float[4][numL-1];
182
      float cut = (SQ6/6)*(2-numL);
183

    
184
      for(int i=0; i<numL-1; i++)
185
        {
186
        mCuts[0][i] = cut;
187
        mCuts[1][i] = cut;
188
        mCuts[2][i] = cut;
189
        mCuts[3][i] = cut;
190
        cut += SQ6/3;
191
        }
192
      }
193

    
194
    return mCuts;
195
    }
196

    
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198

    
199
  private void getLayerRotatable(int[] numLayers)
200
    {
201
    if( mLayerRotatable==null )
202
      {
203
      int numAxis = ROT_AXIS.length;
204
      mLayerRotatable = new boolean[numAxis][];
205

    
206
      for(int i=0; i<numAxis; i++)
207
        {
208
        mLayerRotatable[i] = new boolean[numLayers[i]];
209
        for(int j=0; j<numLayers[i]; j++) mLayerRotatable[i][j] = true;
210
        }
211
      }
212
    }
213

    
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215

    
216
  protected int getNumCubitFaces()
217
    {
218
    return 8;
219
    }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

    
223
  private int getNumOctahedrons(int layers)
224
    {
225
    return layers==1 ? 1 : 4*(layers-1)*(layers-1) + 2;
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  private int getNumTetrahedrons(int layers)
231
    {
232
    return 4*layers*(layers-1);
233
    }
234

    
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236

    
237
  private int createOctaPositions(float[][] centers, int index, int layers, float height)
238
    {
239
    float x = (layers-1)*0.5f;
240
    float z = (layers+1)*0.5f;
241

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

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

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

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

    
274
    return index;
275
    }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

    
279
  private int createTetraPositions(float[][] centers, int index, int layers, float height)
280
    {
281
    float x = (layers-1)*0.5f;
282
    float z =  layers*0.5f;
283

    
284
    for(int i=0; i<layers-1; i++, index++)
285
      {
286
      z -= 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
      x -= 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
      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
    return index;
326
    }
327

    
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329

    
330
  protected float[][] getCubitPositions(int[] numLayers)
331
    {
332
    int layers = numLayers[0];
333
    int numO = getNumOctahedrons(layers);
334
    int numT = getNumTetrahedrons(layers);
335
    int index = 0;
336
    float height = 0.0f;
337

    
338
    float[][] CENTERS = new float[numO+numT][3];
339

    
340
    index = createOctaPositions(CENTERS,index,layers,height);
341

    
342
    for(int i=layers-1; i>0; i--)
343
      {
344
      height += SQ2/2;
345
      index = createOctaPositions(CENTERS,index,i,+height);
346
      index = createOctaPositions(CENTERS,index,i,-height);
347
      }
348

    
349
    height = SQ2/4;
350

    
351
    for(int i=layers; i>1; i--)
352
      {
353
      index = createTetraPositions(CENTERS,index,i,+height);
354
      index = createTetraPositions(CENTERS,index,i,-height);
355
      height += SQ2/2;
356
      }
357

    
358
    return CENTERS;
359
    }
360

    
361
///////////////////////////////////////////////////////////////////////////////////////////////////
362

    
363
  private int retFaceTetraBelongsTo(int tetra, int numLayers)
364
    {
365
    if( mTetraToFaceMap==null ) mTetraToFaceMap = new int[] {1,2,3,0,5,6,7,4};
366

    
367
    for(int i=numLayers-1; i>0; i--)
368
      {
369
      if( tetra < 8*i ) return mTetraToFaceMap[tetra/i];
370
      tetra -= 8*i;
371
      }
372

    
373
    return -1;
374
    }
375

    
376
///////////////////////////////////////////////////////////////////////////////////////////////////
377

    
378
  protected ObjectShape getObjectShape(int cubit, int[] numLayers)
379
    {
380
    int variant = getCubitVariant(cubit,numLayers);
381
    int numL = numLayers[0];
382
    int N = numL>3 ? 5:6;
383
    int E = numL>2 ? (numL>3 ? 0:1):2;
384

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

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

    
409
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
410
      int[] bandIndices   = new int[] { 0,0,0,0,0,0,0,0 };
411
      float[][] corners   = new float[][] { {0.04f,0.20f} };
412
      int[] cornerIndices = new int[] { 0,0,0,0,0,0 };
413
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
414
      int[] centerIndices = new int[] { 0,0,0,0,0,0 };
415
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
416
      }
417
    else
418
      {
419
      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} };
420
      int[][] vert_indices = new int[][]  { {2,1,0}, {2,3,1}, {3,2,0}, {3,0,1} };
421
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
422
      int[] bandIndices   = new int[] { 0,0,0,0 };
423
      float[][] corners   = new float[][] { {0.08f,0.15f} };
424
      int[] cornerIndices = new int[] { 0,0,0,0 };
425
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
426
      int[] centerIndices = new int[] { 0,0,0,0 };
427
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
428
      }
429
    }
430

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

    
433
  protected Static4D getQuat(int cubit, int[] numLayers)
434
    {
435
    if( mQuats==null ) initializeQuats();
436

    
437
    int numL = numLayers[0];
438
    int numO = getNumOctahedrons(numL);
439

    
440
    if( cubit<numO ) return mQuats[0];
441

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

    
454
    return null;
455
    }
456

    
457
///////////////////////////////////////////////////////////////////////////////////////////////////
458

    
459
  protected int getNumCubitVariants(int[] numLayers)
460
    {
461
    return 2;
462
    }
463

    
464
///////////////////////////////////////////////////////////////////////////////////////////////////
465

    
466
  protected int getCubitVariant(int cubit, int[] numLayers)
467
    {
468
    return cubit<getNumOctahedrons(numLayers[0]) ? 0 : 1;
469
    }
470

    
471
///////////////////////////////////////////////////////////////////////////////////////////////////
472

    
473
  protected int getFaceColor(int cubit, int cubitface, int[] numLayers)
474
    {
475
    int numL = numLayers[0];
476
    int numO = getNumOctahedrons(numL);
477

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

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

    
495
      return CUBITS[cubit].getRotRow(axis) == layer ? cubitface : NUM_TEXTURES;
496
      }
497
    else
498
      {
499
      return cubitface>0 ? NUM_TEXTURES : retFaceTetraBelongsTo(cubit-numO, numL);
500
      }
501
    }
502

    
503
///////////////////////////////////////////////////////////////////////////////////////////////////
504

    
505
  protected ObjectSticker retSticker(int face)
506
    {
507
    if( mStickers==null )
508
      {
509
      float[][] STICKERS = new float[][] { { -0.4330127f, -0.25f, 0.4330127f, -0.25f, 0.0f, 0.5f } };
510
      float radius = 0.06f;
511
      float stroke = 0.07f;
512
      float[] radii = new float[] {radius,radius,radius};
513

    
514
      if( ObjectControl.isInIconMode() )
515
        {
516
        int[] numLayers = getNumLayers();
517

    
518
        switch(numLayers[0])
519
          {
520
          case 2: stroke*=1.4f; break;
521
          case 3: stroke*=2.0f; break;
522
          case 4: stroke*=2.1f; break;
523
          default:stroke*=2.2f; break;
524
          }
525
        }
526

    
527
      mStickers     = new ObjectSticker[STICKERS.length];
528
      mStickers[0]  = new ObjectSticker(STICKERS[0],null,radii,stroke);
529
      }
530

    
531
    return mStickers[face/NUM_FACE_COLORS];
532
    }
533

    
534
///////////////////////////////////////////////////////////////////////////////////////////////////
535
// PUBLIC API
536

    
537
  public Static3D[] getRotationAxis()
538
    {
539
    return ROT_AXIS;
540
    }
541

    
542
///////////////////////////////////////////////////////////////////////////////////////////////////
543

    
544
  public Movement getMovement()
545
    {
546
    if( mMovement==null )
547
      {
548
      int[] numLayers = getNumLayers();
549
      if( mCuts==null ) getCuts(numLayers);
550
      getLayerRotatable(numLayers);
551
      mMovement = new Movement8(ROT_AXIS,mCuts,mLayerRotatable,numLayers[0],TYPE_NOT_SPLIT,ENABLED);
552
      }
553
    return mMovement;
554
    }
555

    
556
///////////////////////////////////////////////////////////////////////////////////////////////////
557

    
558
  public int[] getBasicAngle()
559
    {
560
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
561
    return mBasicAngle;
562
    }
563

    
564
///////////////////////////////////////////////////////////////////////////////////////////////////
565

    
566
  public ObjectType intGetObjectType(int[] numLayers)
567
    {
568
    switch(numLayers[0])
569
      {
570
      case 2: return ObjectType.DIAM_2;
571
      case 3: return ObjectType.DIAM_3;
572
      case 4: return ObjectType.DIAM_4;
573
      }
574

    
575
    return ObjectType.DIAM_2;
576
    }
577

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

    
580
  public int getObjectName(int[] numLayers)
581
    {
582
    switch(numLayers[0])
583
      {
584
      case 2: return R.string.diam2;
585
      case 3: return R.string.diam3;
586
      case 4: return R.string.diam4;
587
      }
588

    
589
    return 0;
590
    }
591

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

    
594
  public int getInventor(int[] numLayers)
595
    {
596
    switch(numLayers[0])
597
      {
598
      case 2: return R.string.diam2_inventor;
599
      case 3: return R.string.diam3_inventor;
600
      case 4: return R.string.diam4_inventor;
601
      }
602

    
603
    return 0;
604
    }
605

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

    
608
  public int getComplexity(int[] numLayers)
609
    {
610
    switch(numLayers[0])
611
      {
612
      case 2: return 4;
613
      case 3: return 6;
614
      case 4: return 8;
615
      }
616

    
617
    return 0;
618
    }
619
}
(7-7/25)