Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyCube.java @ e1dc3366

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 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.helpers.ScrambleState;
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
import org.distorted.main.R;
33

    
34
import java.util.Random;
35

    
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37

    
38
class TwistyCube extends TwistyObject
39
{
40
  // the three rotation axis of a RubikCube. Must be normalized.
41
  static final Static3D[] ROT_AXIS = new Static3D[]
42
         {
43
           new Static3D(1,0,0),
44
           new Static3D(0,1,0),
45
           new Static3D(0,0,1)
46
         };
47

    
48
  private static final int[] BASIC_ANGLE = new int[] { 4,4,4 };
49

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

    
57
  // All legal rotation quats of a RubikCube of any size.
58
  // Here's how to compute this:
59
  // 1) compute how many rotations there are (RubikCube of any size = 24)
60
  // 2) take the AXIS, angles of rotation (90 in RubikCube's case) compute the basic quaternions
61
  // (i.e. rotations of 1 basic angle along each of the axis) and from there start semi-randomly
62
  // multiplying them and eventually you'll find all (24) legal rotations.
63
  // Example program in C, res/raw/compute_quats.c , is included.
64
  private static final Static4D[] QUATS = new Static4D[]
65
         {
66
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
67
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
68
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
69
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
70

    
71
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
72
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
73
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
74
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
75
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
76
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
77
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
78
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
79
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
80
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
81
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
82
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
83

    
84
         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
85
         new Static4D(  0.5f,   0.5f,  -0.5f,   0.5f),
86
         new Static4D(  0.5f,   0.5f,  -0.5f,  -0.5f),
87
         new Static4D(  0.5f,  -0.5f,   0.5f,  -0.5f),
88
         new Static4D( -0.5f,  -0.5f,  -0.5f,   0.5f),
89
         new Static4D( -0.5f,   0.5f,  -0.5f,  -0.5f),
90
         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
91
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
92
         };
93

    
94
  private static final double[][] VERTICES = new double[][]
95
          {
96
              { 0.5, 0.5, 0.5 },
97
              { 0.5, 0.5,-0.5 },
98
              { 0.5,-0.5, 0.5 },
99
              { 0.5,-0.5,-0.5 },
100
              {-0.5, 0.5, 0.5 },
101
              {-0.5, 0.5,-0.5 },
102
              {-0.5,-0.5, 0.5 },
103
              {-0.5,-0.5,-0.5 },
104
          };
105

    
106
  private static final int[][] VERT_INDEXES = new int[][]
107
          {
108
              {2,3,1,0},   // counterclockwise!
109
              {7,6,4,5},
110
              {4,0,1,5},
111
              {7,3,2,6},
112
              {6,2,0,4},
113
              {3,7,5,1}
114
          };
115

    
116
  private static final float[][] STICKERS = new float[][]
117
          {
118
              { -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f }
119
          };
120

    
121
  private static final ObjectSticker[] mStickers;
122

    
123
  static
124
    {
125
    final float radius = 0.10f;
126
    final float stroke = 0.08f;
127
    final float[] radii = {radius,radius,radius,radius};
128
    mStickers = new ObjectSticker[STICKERS.length];
129
    mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke );
130
    }
131

    
132
  private int mCurrState;
133
  private int mIndexExcluded;
134
  private final ScrambleState[] mStates;
135
  private int[][] mScrambleTable;
136
  private int[] mNumOccurences;
137

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

    
140
  TwistyCube(int size, Static4D quat, DistortedTexture texture,
141
             MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
142
    {
143
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.CUBE, res, scrWidth);
144

    
145
    int[][] m = new int[16][];
146
    for(int i=1; i<16; i++) m[i] = createEdges(size,i);
147

    
148
    mStates = new ScrambleState[]  // built so that all 3 axes must be present in every 4 consecutive moves
149
      {
150
      new ScrambleState( new int[][] { m[ 1], m[ 2], m[ 3] } ),  // 0
151
      new ScrambleState( new int[][] {  null, m[ 4], m[ 5] } ),  // x
152
      new ScrambleState( new int[][] { m[ 6],  null, m[ 7] } ),  // y
153
      new ScrambleState( new int[][] { m[ 8], m[ 8],  null } ),  // z
154
      new ScrambleState( new int[][] { m[10],  null, m[ 7] } ),  // xy
155
      new ScrambleState( new int[][] { m[11], m[ 9],  null } ),  // xz
156
      new ScrambleState( new int[][] {  null, m[12], m[ 5] } ),  // yx
157
      new ScrambleState( new int[][] { m[ 8], m[13],  null } ),  // yz
158
      new ScrambleState( new int[][] {  null, m[ 4], m[14] } ),  // zx
159
      new ScrambleState( new int[][] { m[ 6],  null, m[15] } ),  // zy
160
      new ScrambleState( new int[][] {  null,  null, m[ 5] } ),  // xyx
161
      new ScrambleState( new int[][] {  null, m[ 4],  null } ),  // xzx
162
      new ScrambleState( new int[][] {  null,  null, m[ 7] } ),  // yxy
163
      new ScrambleState( new int[][] { m[ 6],  null,  null } ),  // yzy
164
      new ScrambleState( new int[][] {  null, m[ 9],  null } ),  // zxz
165
      new ScrambleState( new int[][] { m[ 8],  null,  null } ),  // zyz
166
      };
167
    }
168

    
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170

    
171
  private int[] createEdges(int size, int vertex)
172
    {
173
    int[] ret = new int[9*size];
174

    
175
    for(int l=0; l<size; l++)
176
      {
177
      ret[9*l  ] = l;
178
      ret[9*l+1] =-1;
179
      ret[9*l+2] = vertex;
180
      ret[9*l+3] = l;
181
      ret[9*l+4] = 1;
182
      ret[9*l+5] = vertex;
183
      ret[9*l+6] = l;
184
      ret[9*l+7] = 2;
185
      ret[9*l+8] = vertex;
186
      }
187

    
188
    return ret;
189
    }
190

    
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192

    
193
  int[] getSolvedQuats(int cubit, int numLayers)
194
    {
195
    int status = retCubitSolvedStatus(cubit,numLayers);
196
    return status<0 ? null : buildSolvedQuats(MovementCube.FACE_AXIS[status],QUATS);
197
    }
198

    
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

    
201
  ObjectShape getObjectShape(int cubit, int numLayers)
202
    {
203
    int extraI, extraV, num;
204
    float height;
205

    
206
    switch(numLayers)
207
      {
208
      case 2 : num = 6; extraI = 2; extraV = 2; height = 0.045f; break;
209
      case 3 : num = 5; extraI = 2; extraV = 2; height = 0.045f; break;
210
      case 4 : num = 5; extraI = 1; extraV = 1; height = 0.045f; break;
211
      default: num = 5; extraI = 0; extraV = 0; height = 0.045f; break;
212
      }
213

    
214
    float[][] bands     = new float[][] { {height,35,0.5f,0.7f,num,extraI,extraV} };
215
    int[] bandIndices   = new int[] { 0,0,0,0,0,0};
216
    float[][] corners   = new float[][] { {0.036f,0.12f} };
217
    int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
218
    float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
219
    int[] centerIndices = new int[] { 0,0,0,0,0,0,0,0 };
220

    
221
    return new ObjectShape(VERTICES,VERT_INDEXES,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
222
    }
223

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

    
226
  Static4D getQuat(int cubit, int numLayers)
227
    {
228
    return QUATS[0];
229
    }
230

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

    
233
  int getNumCubitVariants(int numLayers)
234
    {
235
    return 1;
236
    }
237

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

    
240
  int getCubitVariant(int cubit, int numLayers)
241
    {
242
    return 0;
243
    }
244

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

    
247
  int getColor(int face)
248
    {
249
    return FACE_COLORS[face];
250
    }
251

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

    
254
  ObjectSticker retSticker(int face)
255
    {
256
    return mStickers[face/NUM_FACES];
257
    }
258

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

    
261
  float[][] getCubitPositions(int numLayers)
262
    {
263
    int numCubits = numLayers>1 ? 6*numLayers*numLayers - 12*numLayers + 8 : 1;
264
    float[][] tmp = new float[numCubits][];
265

    
266
    float diff = 0.5f*(numLayers-1);
267
    int currentPosition = 0;
268

    
269
    for(int x = 0; x<numLayers; x++)
270
      for(int y = 0; y<numLayers; y++)
271
        for(int z = 0; z<numLayers; z++)
272
          if( x==0 || x==numLayers-1 || y==0 || y==numLayers-1 || z==0 || z==numLayers-1 )
273
            {
274
            tmp[currentPosition++] = new float[] {x-diff,y-diff,z-diff};
275
            }
276

    
277
    return tmp;
278
    }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

    
282
  Static4D[] getQuats()
283
    {
284
    return QUATS;
285
    }
286

    
287
///////////////////////////////////////////////////////////////////////////////////////////////////
288

    
289
  boolean shouldResetTextureMaps()
290
    {
291
    return false;
292
    }
293

    
294
///////////////////////////////////////////////////////////////////////////////////////////////////
295

    
296
  int getNumFaces()
297
    {
298
    return FACE_COLORS.length;
299
    }
300

    
301
///////////////////////////////////////////////////////////////////////////////////////////////////
302

    
303
  float[][] getCuts(int numLayers)
304
    {
305
    float[][] cuts = new float[3][numLayers-1];
306

    
307
    for(int i=0; i<numLayers-1; i++)
308
      {
309
      float cut = (2-numLayers)*0.5f + i;
310
      cuts[0][i] = cut;
311
      cuts[1][i] = cut;
312
      cuts[2][i] = cut;
313
      }
314

    
315
    return cuts;
316
    }
317

    
318
///////////////////////////////////////////////////////////////////////////////////////////////////
319

    
320
  int getSolvedFunctionIndex()
321
    {
322
    return 0;
323
    }
324

    
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326

    
327
  int getNumStickerTypes(int numLayers)
328
    {
329
    return STICKERS.length;
330
    }
331

    
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333

    
334
  int getNumCubitFaces()
335
    {
336
    return FACE_COLORS.length;
337
    }
338

    
339
///////////////////////////////////////////////////////////////////////////////////////////////////
340

    
341
  float getScreenRatio()
342
    {
343
    return 0.5f;
344
    }
345

    
346
///////////////////////////////////////////////////////////////////////////////////////////////////
347

    
348
  int getFaceColor(int cubit, int cubitface, int numLayers)
349
    {
350
    return CUBITS[cubit].mRotationRow[cubitface/2] == (cubitface%2==0 ? (1<<(numLayers-1)):1) ? cubitface : NUM_FACES;
351
    }
352

    
353
///////////////////////////////////////////////////////////////////////////////////////////////////
354

    
355
  float returnMultiplier()
356
    {
357
    return getNumLayers();
358
    }
359

    
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361
// PUBLIC API
362

    
363
  public Static3D[] getRotationAxis()
364
    {
365
    return ROT_AXIS;
366
    }
367

    
368
///////////////////////////////////////////////////////////////////////////////////////////////////
369

    
370
  public int[] getBasicAngle()
371
    {
372
    return BASIC_ANGLE;
373
    }
374

    
375
///////////////////////////////////////////////////////////////////////////////////////////////////
376

    
377
  private void initializeScrambling()
378
    {
379
    int numLayers = getNumLayers();
380

    
381
    if( mScrambleTable ==null )
382
      {
383
      mScrambleTable = new int[NUM_AXIS][numLayers];
384
      }
385
    if( mNumOccurences ==null )
386
      {
387
      int max=0;
388

    
389
      for (ScrambleState mState : mStates)
390
        {
391
        int tmp = mState.getTotal(-1);
392
        if (max < tmp) max = tmp;
393
        }
394

    
395
      mNumOccurences = new int[max];
396
      }
397

    
398
    for(int i=0; i<NUM_AXIS; i++)
399
      for(int j=0; j<numLayers; j++) mScrambleTable[i][j] = 0;
400
    }
401

    
402
///////////////////////////////////////////////////////////////////////////////////////////////////
403

    
404
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int totalScrambles)
405
    {
406
    if( curr==0 )
407
      {
408
      mCurrState     = 0;
409
      mIndexExcluded =-1;
410
      initializeScrambling();
411
      }
412

    
413
    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
414

    
415
    scramble[curr][0] = info[0];
416
    scramble[curr][1] = info[1];
417
    scramble[curr][2] = info[2];
418

    
419
    mCurrState     = info[3];
420
    mIndexExcluded = info[0];
421
    }
422

    
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424

    
425
  public int getObjectName(int numLayers)
426
    {
427
    switch(numLayers)
428
      {
429
      case 2: return R.string.cube2;
430
      case 3: return R.string.cube3;
431
      case 4: return R.string.cube4;
432
      case 5: return R.string.cube5;
433
      }
434
    return R.string.cube3;
435
    }
436

    
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438

    
439
  public int getInventor(int numLayers)
440
    {
441
    switch(numLayers)
442
      {
443
      case 2: return R.string.cube2_inventor;
444
      case 3: return R.string.cube3_inventor;
445
      case 4: return R.string.cube4_inventor;
446
      case 5: return R.string.cube5_inventor;
447
      }
448
    return R.string.cube3_inventor;
449
    }
450

    
451
///////////////////////////////////////////////////////////////////////////////////////////////////
452

    
453
  public int getComplexity(int numLayers)
454
    {
455
    switch(numLayers)
456
      {
457
      case 2: return 4;
458
      case 3: return 6;
459
      case 4: return 8;
460
      case 5: return 10;
461
      }
462
    return 6;
463
    }
464
}
(22-22/41)