Project

General

Profile

Download (17.1 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / objects / TwistyRedi.java @ 8db55f55

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.objects;
21

    
22
import android.content.res.Resources;
23

    
24
import org.distorted.helpers.ObjectShape;
25
import org.distorted.helpers.ObjectSticker;
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
import org.distorted.main.R;
32

    
33
import java.util.Random;
34

    
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36

    
37
public class TwistyRedi extends TwistyObject
38
{
39
  private static final int FACES_PER_CUBIT =9;
40

    
41
  // the four rotation axis of a RubikRedi. Must be normalized.
42
  static final Static3D[] ROT_AXIS = new Static3D[]
43
         {
44
           new Static3D(+SQ3/3,+SQ3/3,+SQ3/3),
45
           new Static3D(+SQ3/3,+SQ3/3,-SQ3/3),
46
           new Static3D(+SQ3/3,-SQ3/3,+SQ3/3),
47
           new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)
48
         };
49

    
50
  private static final int[] BASIC_ANGLE = new int[] { 3,3,3,3 };
51

    
52
  private static final int[] FACE_COLORS = new int[]
53
         {
54
           COLOR_YELLOW, COLOR_WHITE,
55
           COLOR_BLUE  , COLOR_GREEN,
56
           COLOR_RED   , COLOR_ORANGE
57
         };
58

    
59
  // All legal rotation quats of a RubikRedi
60
  private static final Static4D[] QUATS = new Static4D[]
61
         {
62
           new Static4D(  0.0f,  0.0f,  0.0f,  1.0f ),
63
           new Static4D(  1.0f,  0.0f,  0.0f,  0.0f ),
64
           new Static4D(  0.0f,  1.0f,  0.0f,  0.0f ),
65
           new Static4D(  0.0f,  0.0f,  1.0f,  0.0f ),
66

    
67
           new Static4D(  0.5f,  0.5f,  0.5f,  0.5f ),
68
           new Static4D(  0.5f,  0.5f,  0.5f, -0.5f ),
69
           new Static4D(  0.5f,  0.5f, -0.5f,  0.5f ),
70
           new Static4D(  0.5f,  0.5f, -0.5f, -0.5f ),
71
           new Static4D(  0.5f, -0.5f,  0.5f,  0.5f ),
72
           new Static4D(  0.5f, -0.5f,  0.5f, -0.5f ),
73
           new Static4D(  0.5f, -0.5f, -0.5f,  0.5f ),
74
           new Static4D(  0.5f, -0.5f, -0.5f, -0.5f )
75
         };
76

    
77
  private static final float DIST_CORNER = 1.0f;
78
  private static final float DIST_EDGE   = 1.5f;
79

    
80
  // centers of the 8 corners + 12 edges ( i.e. of the all 20 cubits)
81
  private static final float[][] CENTERS = new float[][]
82
         {
83
             { DIST_CORNER, DIST_CORNER, DIST_CORNER },
84
             { DIST_CORNER, DIST_CORNER,-DIST_CORNER },
85
             { DIST_CORNER,-DIST_CORNER, DIST_CORNER },
86
             { DIST_CORNER,-DIST_CORNER,-DIST_CORNER },
87
             {-DIST_CORNER, DIST_CORNER, DIST_CORNER },
88
             {-DIST_CORNER, DIST_CORNER,-DIST_CORNER },
89
             {-DIST_CORNER,-DIST_CORNER, DIST_CORNER },
90
             {-DIST_CORNER,-DIST_CORNER,-DIST_CORNER },
91

    
92
             {      0.0f, DIST_EDGE, DIST_EDGE },
93
             { DIST_EDGE,      0.0f, DIST_EDGE },
94
             {      0.0f,-DIST_EDGE, DIST_EDGE },
95
             {-DIST_EDGE,      0.0f, DIST_EDGE },
96
             { DIST_EDGE, DIST_EDGE,      0.0f },
97
             { DIST_EDGE,-DIST_EDGE,      0.0f },
98
             {-DIST_EDGE,-DIST_EDGE,      0.0f },
99
             {-DIST_EDGE, DIST_EDGE,      0.0f },
100
             {      0.0f, DIST_EDGE,-DIST_EDGE },
101
             { DIST_EDGE,      0.0f,-DIST_EDGE },
102
             {      0.0f,-DIST_EDGE,-DIST_EDGE },
103
             {-DIST_EDGE,      0.0f,-DIST_EDGE }
104
         };
105

    
106
  // Colors of the faces of cubits.
107
  // YELLOW 0 WHITE 1 BLUE 2 GREEN 3 RED 4  ORANGE 5
108
  // YELLOW 6 WHITE 7 BLUE 8 GREEN 9 RED 10 ORANGE 11
109
  private static final int[][] mFaceMap = new int[][]
110
         {
111
           {  4, 2, 0 },
112
           {  2, 5, 0 },
113
           {  3, 4, 0 },
114
           {  5, 3, 0 },
115
           {  1, 2, 4 },
116
           {  5, 2, 1 },
117
           {  4, 3, 1 },
118
           {  1, 3, 5 },
119

    
120
           { 10, 8,12 },
121
           {  6,10,12 },
122
           { 10, 9,12 },
123
           {  7,10,12 },
124
           {  8, 6,12 },
125
           {  9, 6,12 },
126
           {  9, 7,12 },
127
           {  8, 7,12 },
128
           { 11, 8,12 },
129
           {  6,11,12 },
130
           { 11, 9,12 },
131
           {  7,11,12 },
132
         };
133

    
134
  private static final double[][] VERTICES_CORNER = new double[][]
135
          {
136
             { 0.0f, 0.0f, 0.0f },
137
             {-0.5f, 0.5f, 0.5f },
138
             {-0.5f,-0.5f, 0.5f },
139
             { 0.5f, 0.5f, 0.5f },
140
             { 0.5f,-0.5f, 0.5f },
141
             { 0.5f, 0.5f,-0.5f },
142
             { 0.5f,-0.5f,-0.5f },
143
             {-0.5f, 0.5f,-0.5f },
144
          };
145

    
146
  private static final int[][] VERT_INDEXES_CORNER = new int[][]
147
          {
148
             { 2,4,3,1 },
149
             { 1,3,5,7 },
150
             { 4,6,5,3 },
151

    
152
             { 2,4,0 },
153
             { 5,7,0 },
154
             { 4,6,0 },
155
             { 7,1,0 },
156
             { 1,2,0 },
157
             { 6,5,0 }
158
          };
159

    
160
  private static final double[][] VERTICES_EDGE = new double[][]
161
          {
162
             {-0.5f, 0.0f, 0.0f},
163
             { 0.5f, 0.0f, 0.0f},
164
             {-0.5f,-1.0f, 0.0f},
165
             { 0.5f,-1.0f, 0.0f},
166
             { 0.0f,-1.5f, 0.0f},
167
             {-0.5f, 0.0f,-1.0f},
168
             { 0.5f, 0.0f,-1.0f},
169
             { 0.0f, 0.0f,-1.5f},
170
          };
171

    
172
  private static final int[][] VERT_INDEXES_EDGE = new int[][]
173
          {
174
             { 0,2,4,3,1 },
175
             { 0,1,6,7,5 },
176
             { 1,3,6 },
177
             { 0,2,5 },
178
             { 4,7,6,3 },
179
             { 4,7,5,2 }
180
          };
181

    
182
  private static final float[][] STICKERS = new float[][]
183
          {
184
             { -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f },
185
             { -0.3125f, 0.4375f, -0.3125f, -0.1875f, 0.0f, -0.5f, 0.3125f, -0.1875f, 0.3125f, 0.4375f }
186
          };
187

    
188
  private static int[][] mScrambleTable;
189
  private static int[] mPossibleAxis, mPossibleLayers;
190
  private static int[] mNumOccurences;
191

    
192
  private static final ObjectSticker[] mStickers;
193

    
194
  static
195
    {
196
    mStickers = new ObjectSticker[STICKERS.length];
197
    final float R0 = 0.09f;
198
    final float R1 = 0.06f;
199
    final float[][] radii = { {R0,R0,R0,R0},{R1,R1,R1,R1,R1} };
200
    final float[] strokes = { 0.09f,0.06f };
201

    
202
    for(int s=0; s<STICKERS.length; s++)
203
      {
204
      mStickers[s] = new ObjectSticker(STICKERS[s],null,radii[s],strokes[s]);
205
      }
206
    }
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

    
210
  TwistyRedi(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
211
             DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
212
    {
213
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.REDI, res, scrWidth);
214
    }
215

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

    
218
  int[] getSolvedQuats(int cubit, int numLayers)
219
    {
220
    int status = retCubitSolvedStatus(cubit,numLayers);
221
    return status<0 ? null : buildSolvedQuats(MovementRedi.FACE_AXIS[status],QUATS);
222
    }
223

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

    
226
  float getScreenRatio()
227
    {
228
    return 0.50f;
229
    }
230

    
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

    
233
  Static4D[] getQuats()
234
    {
235
    return QUATS;
236
    }
237

    
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239

    
240
  int getNumFaces()
241
    {
242
    return FACE_COLORS.length;
243
    }
244

    
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246

    
247
  int getSolvedFunctionIndex()
248
    {
249
    return 0;
250
    }
251

    
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253

    
254
  boolean shouldResetTextureMaps()
255
    {
256
    return false;
257
    }
258

    
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260

    
261
  int getNumStickerTypes(int numLayers)
262
    {
263
    return STICKERS.length;
264
    }
265

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

    
268
  float[][] getCuts(int size)
269
    {
270
    float C = +SQ3/3 +0.05f;
271
    float[] cut = new float[] {-C,+C};
272
    return new float[][] { cut,cut,cut,cut };
273
    }
274

    
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276

    
277
  int getNumCubitFaces()
278
    {
279
    return FACES_PER_CUBIT;
280
    }
281

    
282
///////////////////////////////////////////////////////////////////////////////////////////////////
283

    
284
  float[][] getCubitPositions(int size)
285
    {
286
    return CENTERS;
287
    }
288

    
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290

    
291
  ObjectShape getObjectShape(int cubit, int numLayers)
292
    {
293
    int variant = getCubitVariant(cubit,numLayers);
294

    
295
    if( variant==0 )
296
      {
297
      float[][] bands     = new float[][] { {0.06f,35,0.5f,0.7f,5,2,2}, {0.01f,35,0.2f,0.4f,5,2,2} };
298
      int[] bandIndices   = new int[] { 0,0,0,1,1,1,1,1,1 };
299
      float[][] corners   = new float[][] { {0.06f,0.12f} };
300
      int[] cornerIndices = new int[]  { -1,0,-1,0,0,0,-1,-1 };
301
      float[][] centers   = new float[][] { { 0.0f, 0.0f, 0.0f} };
302
      int[] centerIndices = new int[] { -1,0,-1,0,0,0,-1,-1 };
303
      return new ObjectShape(VERTICES_CORNER,VERT_INDEXES_CORNER,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
304
      }
305
    else
306
      {
307
      float[][] bands     = new float[][] { {0.038f,35,0.250f,0.7f,7,2,2}, {0.020f,35,0.125f,0.2f,3,1,2}, {0.020f,35,0.125f,0.2f,3,1,1} };
308
      int[] bandIndices   = new int[] { 0,0,1,1,2,2 };
309
      float[][] corners   = new float[][] { {0.06f,0.20f} };
310
      int[] cornerIndices = new int[] { 0,0,-1,-1,-1,-1,-1,-1 };
311
      float[][] centers   = new float[][] { { 0.0f,-0.75f,-0.75f} };
312
      int[] centerIndices = new int[] { 0,0,-1,-1,-1,-1,-1,-1 };
313
      return new ObjectShape(VERTICES_EDGE,VERT_INDEXES_EDGE,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
314
      }
315
    }
316

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

    
319
  Static4D getQuat(int cubit, int numLayers)
320
    {
321
    switch(cubit)
322
      {
323
      case  0: return QUATS[0];                          //  unit quat
324
      case  1: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
325
      case  2: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
326
      case  3: return QUATS[1];                          // 180 along X
327
      case  4: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
328
      case  5: return QUATS[2];                          // 180 along Y
329
      case  6: return QUATS[3];                          // 180 along Z
330
      case  7: return new Static4D(SQ2/2,0,-SQ2/2,0);    // 180 along (SQ2/2,0,-SQ2/2)
331

    
332
      case  8: return QUATS[0];
333
      case  9: return QUATS[5];
334
      case 10: return QUATS[3];
335
      case 11: return QUATS[11];
336
      case 12: return QUATS[4];
337
      case 13: return QUATS[7];
338
      case 14: return QUATS[9];
339
      case 15: return QUATS[10];
340
      case 16: return QUATS[2];
341
      case 17: return QUATS[8];
342
      case 18: return QUATS[1];
343
      case 19: return QUATS[6];
344
      }
345

    
346
    return null;
347
    }
348

    
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350

    
351
  int getNumCubitVariants(int numLayers)
352
    {
353
    return 2;
354
    }
355

    
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357

    
358
  int getCubitVariant(int cubit, int numLayers)
359
    {
360
    return cubit<8 ? 0:1;
361
    }
362

    
363
///////////////////////////////////////////////////////////////////////////////////////////////////
364

    
365
  int getFaceColor(int cubit, int cubitface, int size)
366
    {
367
    return cubitface<3 ? mFaceMap[cubit][cubitface] : STICKERS.length*FACE_COLORS.length;
368
    }
369

    
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371

    
372
  int getColor(int face)
373
    {
374
    return FACE_COLORS[face];
375
    }
376

    
377
///////////////////////////////////////////////////////////////////////////////////////////////////
378

    
379
  ObjectSticker retSticker(int face)
380
    {
381
    return mStickers[face/NUM_FACES];
382
    }
383

    
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385

    
386
  float returnMultiplier()
387
    {
388
    return 2.0f;
389
    }
390

    
391
///////////////////////////////////////////////////////////////////////////////////////////////////
392
// PUBLIC API
393

    
394
  public Static3D[] getRotationAxis()
395
    {
396
    return ROT_AXIS;
397
    }
398

    
399
///////////////////////////////////////////////////////////////////////////////////////////////////
400

    
401
  public int[] getBasicAngle()
402
    {
403
    return BASIC_ANGLE;
404
    }
405

    
406
///////////////////////////////////////////////////////////////////////////////////////////////////
407

    
408
  private void initializeScrambleTable(int[] first)
409
    {
410
    if( mScrambleTable ==null ) mScrambleTable = new int[NUM_AXIS][2];
411
    if( mPossibleAxis  ==null ) mPossibleAxis  = new int[NUM_AXIS-1];
412
    if( mPossibleLayers==null ) mPossibleLayers= new int[NUM_AXIS-1];
413
    if( mNumOccurences ==null ) mNumOccurences = new int[NUM_AXIS-1];
414

    
415
    for(int i=0; i<NUM_AXIS; i++)
416
      for(int j=0; j<2; j++)
417
        {
418
        mScrambleTable[i][j] = 0;
419
        }
420

    
421
    mScrambleTable[first[0]][first[1]/2] = 1;
422
    }
423

    
424
///////////////////////////////////////////////////////////////////////////////////////////////////
425

    
426
  private boolean areOpposite(int oldAxis, int newAxis, int oldRow, int nom)
427
    {
428
    return (oldAxis+newAxis==3)^(oldRow<nom);
429
    }
430

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

    
433
  private int retNewRotationIndex(Random rnd, int nom, int[] oldRot)
434
    {
435
    int index=0, max=0;
436

    
437
    for(int ax=0; ax<NUM_AXIS; ax++)
438
      {
439
      if( ax!=oldRot[0] )
440
        {
441
        mPossibleAxis[index] = ax;
442
        mPossibleLayers[index] = areOpposite(oldRot[0],ax,oldRot[1],nom) ? 0:1;
443
        int tmp = mScrambleTable[mPossibleAxis[index]][mPossibleLayers[index]];
444
        if( tmp>max ) max=tmp;
445
        index++;
446
        }
447
      }
448

    
449
    for(int ax=0; ax<NUM_AXIS-1; ax++)
450
      {
451
      int value = mScrambleTable[mPossibleAxis[ax]][mPossibleLayers[ax]];
452
      mNumOccurences[ax] = max - value + (ax==0 ? 0 : mNumOccurences[ax-1]);
453
      }
454

    
455
    float random= rnd.nextFloat()*mNumOccurences[NUM_AXIS-2];
456

    
457
    for(int ax=0; ax<NUM_AXIS-1; ax++)
458
      {
459
      if( random <= mNumOccurences[ax] )
460
        {
461
        index=ax;
462
        break;
463
        }
464
      }
465

    
466
    mScrambleTable[mPossibleAxis[index]][mPossibleLayers[index]]++;
467

    
468
    return index;
469
    }
470

    
471
///////////////////////////////////////////////////////////////////////////////////////////////////
472
// PUBLIC API
473

    
474
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
475
    {
476
    if( curr==0 )
477
      {
478
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
479
      scramble[curr][1] = rnd.nextFloat()<=0.5f ? 0:2;
480
      initializeScrambleTable(scramble[curr]);
481
      }
482
    else
483
      {
484
      int index = retNewRotationIndex(rnd,1,scramble[curr-1]);
485
      scramble[curr][0] = mPossibleAxis[index];
486
      scramble[curr][1] = 2*mPossibleLayers[index];
487
      }
488

    
489
    switch( rnd.nextInt(2) )
490
      {
491
      case 0: scramble[curr][2] = -1; break;
492
      case 1: scramble[curr][2] =  1; break;
493
      }
494
    }
495

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

    
498
  public int getObjectName(int numLayers)
499
    {
500
    return R.string.redi2;
501
    }
502

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

    
505
  public int getInventor(int numLayers)
506
    {
507
    return R.string.redi2_inventor;
508
    }
509

    
510
///////////////////////////////////////////////////////////////////////////////////////////////////
511

    
512
  public int getComplexity(int numLayers)
513
    {
514
    return 4;
515
    }
516
}
(35-35/41)