Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyRedi.java @ a480ee80

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
  boolean shouldResetTextureMaps()
248
    {
249
    return false;
250
    }
251

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

    
254
  int getNumStickerTypes(int numLayers)
255
    {
256
    return STICKERS.length;
257
    }
258

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

    
261
  float[][] getCuts(int size)
262
    {
263
    float C = +SQ3/3 +0.05f;
264
    float[] cut = new float[] {-C,+C};
265
    return new float[][] { cut,cut,cut,cut };
266
    }
267

    
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269

    
270
  int getNumCubitFaces()
271
    {
272
    return FACES_PER_CUBIT;
273
    }
274

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

    
277
  float[][] getCubitPositions(int size)
278
    {
279
    return CENTERS;
280
    }
281

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

    
284
  ObjectShape getObjectShape(int cubit, int numLayers)
285
    {
286
    int variant = getCubitVariant(cubit,numLayers);
287

    
288
    if( variant==0 )
289
      {
290
      float[][] bands     = new float[][] { {0.06f,35,0.5f,0.7f,5,2,2}, {0.01f,35,0.2f,0.4f,5,2,2} };
291
      int[] bandIndices   = new int[] { 0,0,0,1,1,1,1,1,1 };
292
      float[][] corners   = new float[][] { {0.06f,0.12f} };
293
      int[] cornerIndices = new int[]  { -1,0,-1,0,0,0,-1,-1 };
294
      float[][] centers   = new float[][] { { 0.0f, 0.0f, 0.0f} };
295
      int[] centerIndices = new int[] { -1,0,-1,0,0,0,-1,-1 };
296
      return new ObjectShape(VERTICES_CORNER,VERT_INDEXES_CORNER,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
297
      }
298
    else
299
      {
300
      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} };
301
      int[] bandIndices   = new int[] { 0,0,1,1,2,2 };
302
      float[][] corners   = new float[][] { {0.06f,0.20f} };
303
      int[] cornerIndices = new int[] { 0,0,-1,-1,-1,-1,-1,-1 };
304
      float[][] centers   = new float[][] { { 0.0f,-0.75f,-0.75f} };
305
      int[] centerIndices = new int[] { 0,0,-1,-1,-1,-1,-1,-1 };
306
      return new ObjectShape(VERTICES_EDGE,VERT_INDEXES_EDGE,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
307
      }
308
    }
309

    
310
///////////////////////////////////////////////////////////////////////////////////////////////////
311

    
312
  Static4D getQuat(int cubit, int numLayers)
313
    {
314
    switch(cubit)
315
      {
316
      case  0: return QUATS[0];                          //  unit quat
317
      case  1: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
318
      case  2: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
319
      case  3: return QUATS[1];                          // 180 along X
320
      case  4: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
321
      case  5: return QUATS[2];                          // 180 along Y
322
      case  6: return QUATS[3];                          // 180 along Z
323
      case  7: return new Static4D(SQ2/2,0,-SQ2/2,0);    // 180 along (SQ2/2,0,-SQ2/2)
324

    
325
      case  8: return QUATS[0];
326
      case  9: return QUATS[5];
327
      case 10: return QUATS[3];
328
      case 11: return QUATS[11];
329
      case 12: return QUATS[4];
330
      case 13: return QUATS[7];
331
      case 14: return QUATS[9];
332
      case 15: return QUATS[10];
333
      case 16: return QUATS[2];
334
      case 17: return QUATS[8];
335
      case 18: return QUATS[1];
336
      case 19: return QUATS[6];
337
      }
338

    
339
    return null;
340
    }
341

    
342
///////////////////////////////////////////////////////////////////////////////////////////////////
343

    
344
  int getNumCubitVariants(int numLayers)
345
    {
346
    return 2;
347
    }
348

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

    
351
  int getCubitVariant(int cubit, int numLayers)
352
    {
353
    return cubit<8 ? 0:1;
354
    }
355

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

    
358
  int getFaceColor(int cubit, int cubitface, int size)
359
    {
360
    return cubitface<3 ? mFaceMap[cubit][cubitface] : STICKERS.length*FACE_COLORS.length;
361
    }
362

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

    
365
  int getColor(int face)
366
    {
367
    return FACE_COLORS[face];
368
    }
369

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

    
372
  ObjectSticker retSticker(int face)
373
    {
374
    return mStickers[face/NUM_FACES];
375
    }
376

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

    
379
  float returnMultiplier()
380
    {
381
    return 2.0f;
382
    }
383

    
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385
// PUBLIC API
386

    
387
  public Static3D[] getRotationAxis()
388
    {
389
    return ROT_AXIS;
390
    }
391

    
392
///////////////////////////////////////////////////////////////////////////////////////////////////
393

    
394
  public int[] getBasicAngle()
395
    {
396
    return BASIC_ANGLE;
397
    }
398

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

    
401
  private void initializeScrambleTable(int[] first)
402
    {
403
    if( mScrambleTable ==null ) mScrambleTable = new int[NUM_AXIS][2];
404
    if( mPossibleAxis  ==null ) mPossibleAxis  = new int[NUM_AXIS-1];
405
    if( mPossibleLayers==null ) mPossibleLayers= new int[NUM_AXIS-1];
406
    if( mNumOccurences ==null ) mNumOccurences = new int[NUM_AXIS-1];
407

    
408
    for(int i=0; i<NUM_AXIS; i++)
409
      for(int j=0; j<2; j++)
410
        {
411
        mScrambleTable[i][j] = 0;
412
        }
413

    
414
    mScrambleTable[first[0]][first[1]/2] = 1;
415
    }
416

    
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418

    
419
  private boolean areOpposite(int oldAxis, int newAxis, int oldRow, int nom)
420
    {
421
    return (oldAxis+newAxis==3)^(oldRow<nom);
422
    }
423

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

    
426
  private int retNewRotationIndex(Random rnd, int nom, int[] oldRot)
427
    {
428
    int index=0, max=0;
429

    
430
    for(int ax=0; ax<NUM_AXIS; ax++)
431
      {
432
      if( ax!=oldRot[0] )
433
        {
434
        mPossibleAxis[index] = ax;
435
        mPossibleLayers[index] = areOpposite(oldRot[0],ax,oldRot[1],nom) ? 0:1;
436
        int tmp = mScrambleTable[mPossibleAxis[index]][mPossibleLayers[index]];
437
        if( tmp>max ) max=tmp;
438
        index++;
439
        }
440
      }
441

    
442
    for(int ax=0; ax<NUM_AXIS-1; ax++)
443
      {
444
      int value = mScrambleTable[mPossibleAxis[ax]][mPossibleLayers[ax]];
445
      mNumOccurences[ax] = max - value + (ax==0 ? 0 : mNumOccurences[ax-1]);
446
      }
447

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

    
450
    for(int ax=0; ax<NUM_AXIS-1; ax++)
451
      {
452
      if( random <= mNumOccurences[ax] )
453
        {
454
        index=ax;
455
        break;
456
        }
457
      }
458

    
459
    mScrambleTable[mPossibleAxis[index]][mPossibleLayers[index]]++;
460

    
461
    return index;
462
    }
463

    
464
///////////////////////////////////////////////////////////////////////////////////////////////////
465
// PUBLIC API
466

    
467
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
468
    {
469
    if( curr==0 )
470
      {
471
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
472
      scramble[curr][1] = rnd.nextFloat()<=0.5f ? 0:2;
473
      initializeScrambleTable(scramble[curr]);
474
      }
475
    else
476
      {
477
      int index = retNewRotationIndex(rnd,1,scramble[curr-1]);
478
      scramble[curr][0] = mPossibleAxis[index];
479
      scramble[curr][1] = 2*mPossibleLayers[index];
480
      }
481

    
482
    switch( rnd.nextInt(2) )
483
      {
484
      case 0: scramble[curr][2] = -1; break;
485
      case 1: scramble[curr][2] =  1; break;
486
      }
487
    }
488

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

    
491
  public int getObjectName(int numLayers)
492
    {
493
    return R.string.redi2;
494
    }
495

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

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

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

    
505
  public int getComplexity(int numLayers)
506
    {
507
    return 4;
508
    }
509
}
(35-35/41)