Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyCube.java @ 6cf89a3e

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

    
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

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

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

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

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

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

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

    
186
    return ret;
187
    }
188

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

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

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

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

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

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

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

    
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223

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

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

    
231
  int getNumCubitVariants(int numLayers)
232
    {
233
    return 1;
234
    }
235

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

    
238
  int getCubitVariant(int cubit, int numLayers)
239
    {
240
    return 0;
241
    }
242

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

    
245
  int getColor(int face)
246
    {
247
    return FACE_COLORS[face];
248
    }
249

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

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

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

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

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

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

    
275
    return tmp;
276
    }
277

    
278
///////////////////////////////////////////////////////////////////////////////////////////////////
279

    
280
  Static4D[] getQuats()
281
    {
282
    return QUATS;
283
    }
284

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286

    
287
  boolean shouldResetTextureMaps()
288
    {
289
    return false;
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

    
294
  int getNumFaces()
295
    {
296
    return FACE_COLORS.length;
297
    }
298

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

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

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

    
313
    return cuts;
314
    }
315

    
316
///////////////////////////////////////////////////////////////////////////////////////////////////
317

    
318
  int getSolvedFunctionIndex()
319
    {
320
    return 0;
321
    }
322

    
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324

    
325
  int getNumStickerTypes(int numLayers)
326
    {
327
    return STICKERS.length;
328
    }
329

    
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331

    
332
  int getNumCubitFaces()
333
    {
334
    return FACE_COLORS.length;
335
    }
336

    
337
///////////////////////////////////////////////////////////////////////////////////////////////////
338

    
339
  float getScreenRatio()
340
    {
341
    return 0.5f;
342
    }
343

    
344
///////////////////////////////////////////////////////////////////////////////////////////////////
345

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

    
351
///////////////////////////////////////////////////////////////////////////////////////////////////
352

    
353
  float returnMultiplier()
354
    {
355
    return getNumLayers();
356
    }
357

    
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359
// PUBLIC API
360

    
361
  public Static3D[] getRotationAxis()
362
    {
363
    return ROT_AXIS;
364
    }
365

    
366
///////////////////////////////////////////////////////////////////////////////////////////////////
367

    
368
  public int[] getBasicAngle()
369
    {
370
    return BASIC_ANGLE;
371
    }
372

    
373
///////////////////////////////////////////////////////////////////////////////////////////////////
374

    
375
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int totalScrambles)
376
    {
377
    if( curr==0 )
378
      {
379
      mCurrState     = 0;
380
      mIndexExcluded =-1;
381
      }
382

    
383
    int total = mStates[mCurrState].getTotal(mIndexExcluded);
384
    int random= rnd.nextInt(total);
385
    int[] info= mStates[mCurrState].getInfo(random,mIndexExcluded);
386

    
387
    scramble[curr][0] = info[0];
388
    scramble[curr][1] = info[1];
389
    scramble[curr][2] = info[2];
390

    
391
    mCurrState     = info[3];
392
    mIndexExcluded = info[0];
393
    }
394

    
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396

    
397
  public int getObjectName(int numLayers)
398
    {
399
    switch(numLayers)
400
      {
401
      case 2: return R.string.cube2;
402
      case 3: return R.string.cube3;
403
      case 4: return R.string.cube4;
404
      case 5: return R.string.cube5;
405
      }
406
    return R.string.cube3;
407
    }
408

    
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410

    
411
  public int getInventor(int numLayers)
412
    {
413
    switch(numLayers)
414
      {
415
      case 2: return R.string.cube2_inventor;
416
      case 3: return R.string.cube3_inventor;
417
      case 4: return R.string.cube4_inventor;
418
      case 5: return R.string.cube5_inventor;
419
      }
420
    return R.string.cube3_inventor;
421
    }
422

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

    
425
  public int getComplexity(int numLayers)
426
    {
427
    switch(numLayers)
428
      {
429
      case 2: return 4;
430
      case 3: return 6;
431
      case 4: return 8;
432
      case 5: return 10;
433
      }
434
    return 6;
435
    }
436
}
(22-22/41)