Project

General

Profile

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

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

1 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4 fdec60a3 Leszek Koltunski
// This file is part of Magic Cube.                                                              //
5 0c52af30 Leszek Koltunski
//                                                                                               //
6 fdec60a3 Leszek Koltunski
// Magic Cube is free software: you can redistribute it and/or modify                            //
7 0c52af30 Leszek Koltunski
// 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 fdec60a3 Leszek Koltunski
// Magic Cube is distributed in the hope that it will be useful,                                 //
12 0c52af30 Leszek Koltunski
// 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 fdec60a3 Leszek Koltunski
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20 1f9772f3 Leszek Koltunski
package org.distorted.objects;
21 0c52af30 Leszek Koltunski
22 ccf9fec5 Leszek Koltunski
import android.content.res.Resources;
23 0c52af30 Leszek Koltunski
24 749ef882 Leszek Koltunski
import org.distorted.helpers.FactoryCubit;
25 f10a88a8 Leszek Koltunski
import org.distorted.helpers.ObjectShape;
26 9c06394a Leszek Koltunski
import org.distorted.helpers.ObjectSticker;
27 f10a88a8 Leszek Koltunski
import org.distorted.library.effect.MatrixEffectQuaternion;
28 0c52af30 Leszek Koltunski
import org.distorted.library.main.DistortedEffects;
29
import org.distorted.library.main.DistortedTexture;
30 b32444ee Leszek Koltunski
import org.distorted.library.mesh.MeshBase;
31 efa8aa48 Leszek Koltunski
import org.distorted.library.mesh.MeshSquare;
32 0c52af30 Leszek Koltunski
import org.distorted.library.type.Static3D;
33
import org.distorted.library.type.Static4D;
34 6fd4a72c Leszek Koltunski
import org.distorted.main.R;
35 0c52af30 Leszek Koltunski
36 7c969a6d Leszek Koltunski
import java.util.Random;
37
38 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
39
40 9c2f0c91 Leszek Koltunski
class TwistyCube extends TwistyObject
41 0c52af30 Leszek Koltunski
{
42 e844c116 Leszek Koltunski
  // the three rotation axis of a RubikCube. Must be normalized.
43 ad38d800 Leszek Koltunski
  static final Static3D[] ROT_AXIS = new Static3D[]
44 efef689c Leszek Koltunski
         {
45
           new Static3D(1,0,0),
46
           new Static3D(0,1,0),
47
           new Static3D(0,0,1)
48
         };
49
50 925ed78f Leszek Koltunski
  private static final int[] BASIC_ANGLE = new int[] { 4,4,4 };
51
52 37a25788 Leszek Koltunski
  private static final int[] FACE_COLORS = new int[]
53 efef689c Leszek Koltunski
         {
54 ece1b58d Leszek Koltunski
           COLOR_YELLOW, COLOR_WHITE,
55
           COLOR_BLUE  , COLOR_GREEN,
56 323b217c Leszek Koltunski
           COLOR_RED   , COLOR_ORANGE
57 efef689c Leszek Koltunski
         };
58
59 10585385 Leszek Koltunski
  // All legal rotation quats of a RubikCube of any size.
60 efef689c Leszek Koltunski
  // Here's how to compute this:
61
  // 1) compute how many rotations there are (RubikCube of any size = 24)
62
  // 2) take the AXIS, angles of rotation (90 in RubikCube's case) compute the basic quaternions
63
  // (i.e. rotations of 1 basic angle along each of the axis) and from there start semi-randomly
64
  // multiplying them and eventually you'll find all (24) legal rotations.
65 9f4c44fe Leszek Koltunski
  // Example program in C, res/raw/compute_quats.c , is included.
66 10585385 Leszek Koltunski
  private static final Static4D[] QUATS = new Static4D[]
67 efef689c Leszek Koltunski
         {
68 10585385 Leszek Koltunski
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
69
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
70
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
71
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
72
73
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
74
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
75
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
76
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
77
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
78
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
79
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
80
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
81
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
82
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
83
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
84
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
85
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
         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
93
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
94 efef689c Leszek Koltunski
         };
95 411c6285 Leszek Koltunski
96 b1f2ccf5 Leszek Koltunski
  private static final double[][] VERTICES = new double[][]
97
          {
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
              {-0.5,-0.5, 0.5 },
105
              {-0.5,-0.5,-0.5 },
106
          };
107
108
  private static final int[][] VERT_INDEXES = new int[][]
109
          {
110
              {2,3,1,0},   // counterclockwise!
111
              {7,6,4,5},
112
              {4,0,1,5},
113
              {7,3,2,6},
114
              {6,2,0,4},
115
              {3,7,5,1}
116
          };
117
118
  private static final float[][] STICKERS = new float[][]
119
          {
120
              { -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f }
121
          };
122
123 9c06394a Leszek Koltunski
  private static final ObjectSticker[] mStickers;
124
125
  static
126
    {
127
    final float radius = 0.10f;
128
    final float stroke = 0.08f;
129
    final float[] radii = {radius,radius,radius,radius};
130
    mStickers = new ObjectSticker[STICKERS.length];
131
    mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke );
132
    }
133
134 411c6285 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
135
136 9c2f0c91 Leszek Koltunski
  TwistyCube(int size, Static4D quat, DistortedTexture texture,
137
             MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
138 411c6285 Leszek Koltunski
    {
139 db875721 Leszek Koltunski
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.CUBE, res, scrWidth);
140 411c6285 Leszek Koltunski
    }
141
142 f10a88a8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
143
144
  private Static4D getQuat(int cubit, int numLayers)
145
    {
146
    return QUATS[0];
147
    }
148
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150
151
  private int getNumCubitVariants(int numLayers)
152
    {
153
    return 1;
154
    }
155
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157
158
  int getCubitVariant(int cubit, int numLayers)
159
    {
160
    return 0;
161
    }
162
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164
165
  ObjectShape getObjectShape(int cubit, int numLayers)
166
    {
167
    int extraI, extraV, num;
168
    float height;
169
170
    switch(numLayers)
171
      {
172
      case 2 : num = 6; extraI = 2; extraV = 2; height = 0.045f; break;
173
      case 3 : num = 5; extraI = 2; extraV = 2; height = 0.045f; break;
174
      case 4 : num = 5; extraI = 1; extraV = 1; height = 0.045f; break;
175
      default: num = 5; extraI = 0; extraV = 0; height = 0.045f; break;
176
      }
177
178
    float[][] bands     = new float[][] { {height,35,0.5f,0.7f,num,extraI,extraV} };
179
    int[] bandIndices   = new int[] { 0,0,0,0,0,0};
180
    float[][] corners   = new float[][] { {0.036f,0.12f} };
181
    int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
182
    float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
183
    int[] centerIndices = new int[] { 0,0,0,0,0,0,0,0 };
184
185
    return new ObjectShape(VERTICES,VERT_INDEXES,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
186
    }
187
188 ac940e24 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
189
190 a64e07d0 Leszek Koltunski
  MeshBase createCubitMesh(int cubit, int numLayers)
191 ac940e24 Leszek Koltunski
    {
192 f10a88a8 Leszek Koltunski
    int variant = getCubitVariant(cubit,numLayers);
193
194 ac940e24 Leszek Koltunski
    if( mMeshes==null )
195
      {
196 b1f2ccf5 Leszek Koltunski
      FactoryCubit factory = FactoryCubit.getInstance();
197
      factory.clear();
198 f10a88a8 Leszek Koltunski
      mMeshes = new MeshBase[getNumCubitVariants(numLayers)];
199 ac940e24 Leszek Koltunski
      }
200
201 f10a88a8 Leszek Koltunski
    if( mMeshes[variant]==null )
202 ac940e24 Leszek Koltunski
      {
203 f10a88a8 Leszek Koltunski
      ObjectShape shape = getObjectShape(cubit,numLayers);
204 b1f2ccf5 Leszek Koltunski
      FactoryCubit factory = FactoryCubit.getInstance();
205 f10a88a8 Leszek Koltunski
      factory.createNewFaceTransform(shape);
206
      mMeshes[variant] = factory.createRoundedSolid(shape);
207 ac940e24 Leszek Koltunski
      }
208
209 f10a88a8 Leszek Koltunski
    MeshBase mesh = mMeshes[variant].copy(true);
210
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit,numLayers), new Static3D(0,0,0) );
211
    mesh.apply(quat,0xffffffff,0);
212
213
    return mesh;
214 ac940e24 Leszek Koltunski
    }
215
216 7289fd6c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
217
218 9c06394a Leszek Koltunski
  int getColor(int face)
219 7289fd6c Leszek Koltunski
    {
220 9c06394a Leszek Koltunski
    return FACE_COLORS[face];
221
    }
222
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224 7289fd6c Leszek Koltunski
225 9c06394a Leszek Koltunski
  ObjectSticker retSticker(int face)
226
    {
227
    return mStickers[face/NUM_FACES];
228 7289fd6c Leszek Koltunski
    }
229
230 411c6285 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
231
232 b1f2ccf5 Leszek Koltunski
  float[][] getCubitPositions(int numLayers)
233 a10ada2a Leszek Koltunski
    {
234 b1f2ccf5 Leszek Koltunski
    int numCubits = numLayers>1 ? 6*numLayers*numLayers - 12*numLayers + 8 : 1;
235 e6cf7283 Leszek Koltunski
    float[][] tmp = new float[numCubits][];
236 beb325a0 Leszek Koltunski
237 b1f2ccf5 Leszek Koltunski
    float diff = 0.5f*(numLayers-1);
238 a10ada2a Leszek Koltunski
    int currentPosition = 0;
239 beb325a0 Leszek Koltunski
240 b1f2ccf5 Leszek Koltunski
    for(int x = 0; x<numLayers; x++)
241
      for(int y = 0; y<numLayers; y++)
242
        for(int z = 0; z<numLayers; z++)
243
          if( x==0 || x==numLayers-1 || y==0 || y==numLayers-1 || z==0 || z==numLayers-1 )
244 beb325a0 Leszek Koltunski
            {
245 e6cf7283 Leszek Koltunski
            tmp[currentPosition++] = new float[] {x-diff,y-diff,z-diff};
246 a10ada2a Leszek Koltunski
            }
247 47ba5ddc Leszek Koltunski
248 a10ada2a Leszek Koltunski
    return tmp;
249
    }
250 47ba5ddc Leszek Koltunski
251 beb325a0 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
252
253 10585385 Leszek Koltunski
  Static4D[] getQuats()
254 a10ada2a Leszek Koltunski
    {
255 10585385 Leszek Koltunski
    return QUATS;
256 a10ada2a Leszek Koltunski
    }
257 47ba5ddc Leszek Koltunski
258 eaee1ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
259
260
  boolean shouldResetTextureMaps()
261
    {
262
    return false;
263
    }
264
265 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
266
267 411c6285 Leszek Koltunski
  int getNumFaces()
268 a10ada2a Leszek Koltunski
    {
269 411c6285 Leszek Koltunski
    return FACE_COLORS.length;
270 8f53e513 Leszek Koltunski
    }
271
272 7403cdfa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
273
274 e6734aa9 Leszek Koltunski
  float[][] getCuts(int numLayers)
275 7403cdfa Leszek Koltunski
    {
276 e6734aa9 Leszek Koltunski
    float[][] cuts = new float[3][numLayers-1];
277 a97e02b7 Leszek Koltunski
278 a64e07d0 Leszek Koltunski
    for(int i=0; i<numLayers-1; i++)
279 a97e02b7 Leszek Koltunski
      {
280 e6734aa9 Leszek Koltunski
      float cut = (2-numLayers)*0.5f + i;
281
      cuts[0][i] = cut;
282
      cuts[1][i] = cut;
283
      cuts[2][i] = cut;
284 a97e02b7 Leszek Koltunski
      }
285
286
    return cuts;
287 7403cdfa Leszek Koltunski
    }
288
289 eab9d8f8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
290
291 a64e07d0 Leszek Koltunski
  int getNumStickerTypes(int numLayers)
292 eab9d8f8 Leszek Koltunski
    {
293 b1f2ccf5 Leszek Koltunski
    return STICKERS.length;
294 eab9d8f8 Leszek Koltunski
    }
295
296 8f53e513 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
297
298
  int getNumCubitFaces()
299
    {
300
    return FACE_COLORS.length;
301 411c6285 Leszek Koltunski
    }
302 47ba5ddc Leszek Koltunski
303 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
304
305
  float getScreenRatio()
306
    {
307
    return 0.5f;
308
    }
309
310 f6d06256 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
311
312 f10a88a8 Leszek Koltunski
  int getFaceColor(int cubit, int cubitface, int numLayers)
313 f6d06256 Leszek Koltunski
    {
314 f10a88a8 Leszek Koltunski
    return CUBITS[cubit].mRotationRow[cubitface/2] == (cubitface%2==0 ? (1<<(numLayers-1)):1) ? cubitface : NUM_FACES;
315 f6d06256 Leszek Koltunski
    }
316
317 fb377dae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
318
319
  float returnMultiplier()
320
    {
321 d99f3a48 Leszek Koltunski
    return getNumLayers();
322 fb377dae Leszek Koltunski
    }
323
324 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
325
// PUBLIC API
326
327 12ad3fca Leszek Koltunski
  public Static3D[] getRotationAxis()
328
    {
329 ad38d800 Leszek Koltunski
    return ROT_AXIS;
330 12ad3fca Leszek Koltunski
    }
331
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333
334 925ed78f Leszek Koltunski
  public int[] getBasicAngle()
335 e844c116 Leszek Koltunski
    {
336 925ed78f Leszek Koltunski
    return BASIC_ANGLE;
337 e844c116 Leszek Koltunski
    }
338 39e74052 Leszek Koltunski
339 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
340
341 9f171eba Leszek Koltunski
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
342 7c969a6d Leszek Koltunski
    {
343 9f171eba Leszek Koltunski
    if( curr==0 )
344 5cf34c5f Leszek Koltunski
      {
345 9f171eba Leszek Koltunski
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
346 7c969a6d Leszek Koltunski
      }
347
    else
348
      {
349 8e6dc249 Leszek Koltunski
      int newVector = rnd.nextInt(NUM_AXIS-1);
350 9f171eba Leszek Koltunski
      scramble[curr][0] = (newVector>=scramble[curr-1][0] ? newVector+1 : newVector);
351 8e6dc249 Leszek Koltunski
352
      // All three axis must be present among every four consecutive rotations.
353
      // Otherwise in case of odd-sized cubes we can get four consecutive rotations
354
      // that collapse to a NOP
355
      // (X,midLayer,180)->(Y,midLayer,180)->(X,midLayer,180)->(Y,midLayer,180) = NOP
356
      if( curr>=3 && scramble[curr-1][0]==scramble[curr-3][0] )
357
        {
358
        for( int ax=0; ax<NUM_AXIS; ax++)
359
          {
360
          if( scramble[curr-1][0]!=ax && scramble[curr-2][0]!=ax )
361
            {
362
            scramble[curr][0] = ax;
363
            break;
364
            }
365
          }
366
        }
367 5cf34c5f Leszek Koltunski
      }
368
369 7c969a6d Leszek Koltunski
    float rowFloat = rnd.nextFloat();
370 0203be88 Leszek Koltunski
    int numLayers = getNumLayers();
371 7c969a6d Leszek Koltunski
372 0203be88 Leszek Koltunski
    for(int row=0; row<numLayers; row++)
373 7c969a6d Leszek Koltunski
      {
374 0203be88 Leszek Koltunski
      if( rowFloat*numLayers <= row+1 )
375 bbc6471c Leszek Koltunski
        {
376 9f171eba Leszek Koltunski
        scramble[curr][1] = row;
377 bbc6471c Leszek Koltunski
        break;
378
        }
379 7c969a6d Leszek Koltunski
      }
380
381 5043d5d0 Leszek Koltunski
    switch( rnd.nextInt(4) )
382
      {
383 9f171eba Leszek Koltunski
      case 0: scramble[curr][2] = -2; break;
384
      case 1: scramble[curr][2] = -1; break;
385
      case 2: scramble[curr][2] =  1; break;
386
      case 3: scramble[curr][2] =  2; break;
387 5043d5d0 Leszek Koltunski
      }
388 e46e17fb Leszek Koltunski
    }
389 f0336037 Leszek Koltunski
390 6b6504fe Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
391
392
  public boolean isSolved()
393
    {
394
    int index = CUBITS[0].mQuatIndex;
395
396
    for(int i=1; i<NUM_CUBITS; i++)
397
      {
398 722b2512 Leszek Koltunski
      if( thereIsVisibleDifference(CUBITS[i], index) ) return false;
399 6b6504fe Leszek Koltunski
      }
400
401
    return true;
402
    }
403
404 f0336037 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
405 6fd4a72c Leszek Koltunski
406
  public int getObjectName(int numLayers)
407
    {
408
    switch(numLayers)
409
      {
410
      case 2: return R.string.cube2;
411
      case 3: return R.string.cube3;
412
      case 4: return R.string.cube4;
413
      case 5: return R.string.cube5;
414
      }
415
    return R.string.cube3;
416
    }
417
418
///////////////////////////////////////////////////////////////////////////////////////////////////
419
420
  public int getInventor(int numLayers)
421
    {
422
    switch(numLayers)
423
      {
424
      case 2: return R.string.cube2_inventor;
425
      case 3: return R.string.cube3_inventor;
426
      case 4: return R.string.cube4_inventor;
427
      case 5: return R.string.cube5_inventor;
428
      }
429
    return R.string.cube3_inventor;
430
    }
431
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433
434
  public int getComplexity(int numLayers)
435
    {
436
    switch(numLayers)
437
      {
438
      case 2: return 4;
439
      case 3: return 6;
440
      case 4: return 8;
441
      case 5: return 10;
442
      }
443
    return 6;
444
    }
445 0c52af30 Leszek Koltunski
}