Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyCube.java @ 3e605536

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

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

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

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

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

    
83
         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
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
         };
92

    
93
  private static final double[][] VERTICES = new double[][]
94
          {
95
              { 0.5, 0.5, 0.5 },
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
          };
104

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

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

    
120
  private static final ObjectSticker[] mStickers;
121

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

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

    
133
  TwistyCube(int size, Static4D quat, DistortedTexture texture,
134
             MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
135
    {
136
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.CUBE, res, scrWidth);
137
    }
138

    
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140

    
141
  ObjectShape getObjectShape(int cubit, int numLayers)
142
    {
143
    int extraI, extraV, num;
144
    float height;
145

    
146
    switch(numLayers)
147
      {
148
      case 2 : num = 6; extraI = 2; extraV = 2; height = 0.045f; break;
149
      case 3 : num = 5; extraI = 2; extraV = 2; height = 0.045f; break;
150
      case 4 : num = 5; extraI = 1; extraV = 1; height = 0.045f; break;
151
      default: num = 5; extraI = 0; extraV = 0; height = 0.045f; break;
152
      }
153

    
154
    float[][] bands     = new float[][] { {height,35,0.5f,0.7f,num,extraI,extraV} };
155
    int[] bandIndices   = new int[] { 0,0,0,0,0,0};
156
    float[][] corners   = new float[][] { {0.036f,0.12f} };
157
    int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
158
    float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
159
    int[] centerIndices = new int[] { 0,0,0,0,0,0,0,0 };
160

    
161
    return new ObjectShape(VERTICES,VERT_INDEXES,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
162
    }
163

    
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165

    
166
  Static4D getQuat(int cubit, int numLayers)
167
    {
168
    return QUATS[0];
169
    }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172

    
173
  int getNumCubitVariants(int numLayers)
174
    {
175
    return 1;
176
    }
177

    
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

    
180
  int getCubitVariant(int cubit, int numLayers)
181
    {
182
    return 0;
183
    }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186

    
187
  int getColor(int face)
188
    {
189
    return FACE_COLORS[face];
190
    }
191

    
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

    
194
  ObjectSticker retSticker(int face)
195
    {
196
    return mStickers[face/NUM_FACES];
197
    }
198

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

    
201
  float[][] getCubitPositions(int numLayers)
202
    {
203
    int numCubits = numLayers>1 ? 6*numLayers*numLayers - 12*numLayers + 8 : 1;
204
    float[][] tmp = new float[numCubits][];
205

    
206
    float diff = 0.5f*(numLayers-1);
207
    int currentPosition = 0;
208

    
209
    for(int x = 0; x<numLayers; x++)
210
      for(int y = 0; y<numLayers; y++)
211
        for(int z = 0; z<numLayers; z++)
212
          if( x==0 || x==numLayers-1 || y==0 || y==numLayers-1 || z==0 || z==numLayers-1 )
213
            {
214
            tmp[currentPosition++] = new float[] {x-diff,y-diff,z-diff};
215
            }
216

    
217
    return tmp;
218
    }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221

    
222
  Static4D[] getQuats()
223
    {
224
    return QUATS;
225
    }
226

    
227
///////////////////////////////////////////////////////////////////////////////////////////////////
228

    
229
  boolean shouldResetTextureMaps()
230
    {
231
    return false;
232
    }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235

    
236
  int getNumFaces()
237
    {
238
    return FACE_COLORS.length;
239
    }
240

    
241
///////////////////////////////////////////////////////////////////////////////////////////////////
242

    
243
  float[][] getCuts(int numLayers)
244
    {
245
    float[][] cuts = new float[3][numLayers-1];
246

    
247
    for(int i=0; i<numLayers-1; i++)
248
      {
249
      float cut = (2-numLayers)*0.5f + i;
250
      cuts[0][i] = cut;
251
      cuts[1][i] = cut;
252
      cuts[2][i] = cut;
253
      }
254

    
255
    return cuts;
256
    }
257

    
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259

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

    
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266

    
267
  int getNumCubitFaces()
268
    {
269
    return FACE_COLORS.length;
270
    }
271

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273

    
274
  float getScreenRatio()
275
    {
276
    return 0.5f;
277
    }
278

    
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280

    
281
  int getFaceColor(int cubit, int cubitface, int numLayers)
282
    {
283
    return CUBITS[cubit].mRotationRow[cubitface/2] == (cubitface%2==0 ? (1<<(numLayers-1)):1) ? cubitface : NUM_FACES;
284
    }
285

    
286
///////////////////////////////////////////////////////////////////////////////////////////////////
287

    
288
  float returnMultiplier()
289
    {
290
    return getNumLayers();
291
    }
292

    
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294
// PUBLIC API
295

    
296
  public Static3D[] getRotationAxis()
297
    {
298
    return ROT_AXIS;
299
    }
300

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

    
303
  public int[] getBasicAngle()
304
    {
305
    return BASIC_ANGLE;
306
    }
307

    
308
///////////////////////////////////////////////////////////////////////////////////////////////////
309

    
310
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
311
    {
312
    if( curr==0 )
313
      {
314
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
315
      }
316
    else
317
      {
318
      int newVector = rnd.nextInt(NUM_AXIS-1);
319
      scramble[curr][0] = (newVector>=scramble[curr-1][0] ? newVector+1 : newVector);
320

    
321
      // All three axis must be present among every four consecutive rotations.
322
      // Otherwise in case of odd-sized cubes we can get four consecutive rotations
323
      // that collapse to a NOP
324
      // (X,midLayer,180)->(Y,midLayer,180)->(X,midLayer,180)->(Y,midLayer,180) = NOP
325
      if( curr>=3 && scramble[curr-1][0]==scramble[curr-3][0] )
326
        {
327
        for( int ax=0; ax<NUM_AXIS; ax++)
328
          {
329
          if( scramble[curr-1][0]!=ax && scramble[curr-2][0]!=ax )
330
            {
331
            scramble[curr][0] = ax;
332
            break;
333
            }
334
          }
335
        }
336
      }
337

    
338
    float rowFloat = rnd.nextFloat();
339
    int numLayers = getNumLayers();
340

    
341
    for(int row=0; row<numLayers; row++)
342
      {
343
      if( rowFloat*numLayers <= row+1 )
344
        {
345
        scramble[curr][1] = row;
346
        break;
347
        }
348
      }
349

    
350
    switch( rnd.nextInt(4) )
351
      {
352
      case 0: scramble[curr][2] = -2; break;
353
      case 1: scramble[curr][2] = -1; break;
354
      case 2: scramble[curr][2] =  1; break;
355
      case 3: scramble[curr][2] =  2; break;
356
      }
357
    }
358

    
359
///////////////////////////////////////////////////////////////////////////////////////////////////
360

    
361
  public boolean isSolved()
362
    {
363
    int index = CUBITS[0].mQuatIndex;
364

    
365
    for(int i=1; i<NUM_CUBITS; i++)
366
      {
367
      if( thereIsVisibleDifference(CUBITS[i], index) ) return false;
368
      }
369

    
370
    return true;
371
    }
372

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

    
375
  public int getObjectName(int numLayers)
376
    {
377
    switch(numLayers)
378
      {
379
      case 2: return R.string.cube2;
380
      case 3: return R.string.cube3;
381
      case 4: return R.string.cube4;
382
      case 5: return R.string.cube5;
383
      }
384
    return R.string.cube3;
385
    }
386

    
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388

    
389
  public int getInventor(int numLayers)
390
    {
391
    switch(numLayers)
392
      {
393
      case 2: return R.string.cube2_inventor;
394
      case 3: return R.string.cube3_inventor;
395
      case 4: return R.string.cube4_inventor;
396
      case 5: return R.string.cube5_inventor;
397
      }
398
    return R.string.cube3_inventor;
399
    }
400

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

    
403
  public int getComplexity(int numLayers)
404
    {
405
    switch(numLayers)
406
      {
407
      case 2: return 4;
408
      case 3: return 6;
409
      case 4: return 8;
410
      case 5: return 10;
411
      }
412
    return 6;
413
    }
414
}
(22-22/41)