Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyCube.java @ 47d98cd5

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 9c06394a Leszek Koltunski
import org.distorted.helpers.ObjectSticker;
26 0c52af30 Leszek Koltunski
import org.distorted.library.main.DistortedEffects;
27
import org.distorted.library.main.DistortedTexture;
28 b32444ee Leszek Koltunski
import org.distorted.library.mesh.MeshBase;
29 efa8aa48 Leszek Koltunski
import org.distorted.library.mesh.MeshSquare;
30 0c52af30 Leszek Koltunski
import org.distorted.library.type.Static3D;
31
import org.distorted.library.type.Static4D;
32 6fd4a72c Leszek Koltunski
import org.distorted.main.R;
33 0c52af30 Leszek Koltunski
34 7c969a6d Leszek Koltunski
import java.util.Random;
35
36 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
37
38 9c2f0c91 Leszek Koltunski
class TwistyCube extends TwistyObject
39 0c52af30 Leszek Koltunski
{
40 e844c116 Leszek Koltunski
  // the three rotation axis of a RubikCube. Must be normalized.
41 ad38d800 Leszek Koltunski
  static final Static3D[] ROT_AXIS = new Static3D[]
42 efef689c Leszek Koltunski
         {
43
           new Static3D(1,0,0),
44
           new Static3D(0,1,0),
45
           new Static3D(0,0,1)
46
         };
47
48 925ed78f Leszek Koltunski
  private static final int[] BASIC_ANGLE = new int[] { 4,4,4 };
49
50 37a25788 Leszek Koltunski
  private static final int[] FACE_COLORS = new int[]
51 efef689c Leszek Koltunski
         {
52 ece1b58d Leszek Koltunski
           COLOR_YELLOW, COLOR_WHITE,
53
           COLOR_BLUE  , COLOR_GREEN,
54 323b217c Leszek Koltunski
           COLOR_RED   , COLOR_ORANGE
55 efef689c Leszek Koltunski
         };
56
57 10585385 Leszek Koltunski
  // All legal rotation quats of a RubikCube of any size.
58 efef689c Leszek Koltunski
  // 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 9f4c44fe Leszek Koltunski
  // Example program in C, res/raw/compute_quats.c , is included.
64 10585385 Leszek Koltunski
  private static final Static4D[] QUATS = new Static4D[]
65 efef689c Leszek Koltunski
         {
66 10585385 Leszek Koltunski
         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 efef689c Leszek Koltunski
         };
93 411c6285 Leszek Koltunski
94 b1f2ccf5 Leszek Koltunski
  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 9c06394a Leszek Koltunski
  private static final ObjectSticker[] mStickers;
122
123 fbca0033 Leszek Koltunski
  private static MeshBase[] mMeshes;
124 40ab026e Leszek Koltunski
125 9c06394a Leszek Koltunski
  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 ac940e24 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
143
144 a64e07d0 Leszek Koltunski
  MeshBase createCubitMesh(int cubit, int numLayers)
145 ac940e24 Leszek Koltunski
    {
146
    if( mMeshes==null )
147
      {
148 b1f2ccf5 Leszek Koltunski
      FactoryCubit factory = FactoryCubit.getInstance();
149
      factory.clear();
150 ac940e24 Leszek Koltunski
      mMeshes = new MeshBase[ObjectList.CUBE.getNumVariants()];
151
      }
152
153
    int ordinal= ObjectList.CUBE.ordinal();
154 d99f3a48 Leszek Koltunski
    int index  = ObjectList.getSizeIndex(ordinal,getNumLayers());
155 ac940e24 Leszek Koltunski
156
    if( mMeshes[index]==null )
157
      {
158 b1f2ccf5 Leszek Koltunski
      int extraI, extraV, num;
159 67b2d57b Leszek Koltunski
      float height;
160 b1f2ccf5 Leszek Koltunski
161
      switch(numLayers)
162
        {
163 67b2d57b Leszek Koltunski
        case 2 : num = 6; extraI = 2; extraV = 2; height = 0.045f; break;
164
        case 3 : num = 5; extraI = 2; extraV = 2; height = 0.045f; break;
165
        case 4 : num = 5; extraI = 1; extraV = 1; height = 0.045f; break;
166
        default: num = 5; extraI = 0; extraV = 0; height = 0.045f; break;
167 b1f2ccf5 Leszek Koltunski
        }
168
169 67b2d57b Leszek Koltunski
      float[][] bands     = new float[][] { {height,35,0.5f,0.7f,num,extraI,extraV} };
170 b1f2ccf5 Leszek Koltunski
      int[] bandIndexes   = new int[] { 0,0,0,0,0,0};
171
      float[][] corners   = new float[][] { {0.036f,0.12f} };
172
      int[] cornerIndexes = new int[] { 0,0,0,0,0,0,0,0 };
173 b3c9061a Leszek Koltunski
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
174
      int[] centerIndexes = new int[] { 0,0,0,0,0,0,0,0 };
175 b1f2ccf5 Leszek Koltunski
176
      FactoryCubit factory = FactoryCubit.getInstance();
177
178
      factory.createNewFaceTransform(VERTICES,VERT_INDEXES);
179
      mMeshes[index] = factory.createRoundedSolid(VERTICES, VERT_INDEXES,
180
                                                  bands, bandIndexes,
181
                                                  corners, cornerIndexes,
182 b3c9061a Leszek Koltunski
                                                  centers, centerIndexes,
183 47d98cd5 Leszek Koltunski
                                                  getNumCubitFaces(), null );
184 ac940e24 Leszek Koltunski
      }
185
186
    return mMeshes[index].copy(true);
187
    }
188
189 7289fd6c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
190
191 9c06394a Leszek Koltunski
  int getColor(int face)
192 7289fd6c Leszek Koltunski
    {
193 9c06394a Leszek Koltunski
    return FACE_COLORS[face];
194
    }
195
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197 7289fd6c Leszek Koltunski
198 9c06394a Leszek Koltunski
  ObjectSticker retSticker(int face)
199
    {
200
    return mStickers[face/NUM_FACES];
201 7289fd6c Leszek Koltunski
    }
202
203 411c6285 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
204
205 b1f2ccf5 Leszek Koltunski
  float[][] getCubitPositions(int numLayers)
206 a10ada2a Leszek Koltunski
    {
207 b1f2ccf5 Leszek Koltunski
    int numCubits = numLayers>1 ? 6*numLayers*numLayers - 12*numLayers + 8 : 1;
208 e6cf7283 Leszek Koltunski
    float[][] tmp = new float[numCubits][];
209 beb325a0 Leszek Koltunski
210 b1f2ccf5 Leszek Koltunski
    float diff = 0.5f*(numLayers-1);
211 a10ada2a Leszek Koltunski
    int currentPosition = 0;
212 beb325a0 Leszek Koltunski
213 b1f2ccf5 Leszek Koltunski
    for(int x = 0; x<numLayers; x++)
214
      for(int y = 0; y<numLayers; y++)
215
        for(int z = 0; z<numLayers; z++)
216
          if( x==0 || x==numLayers-1 || y==0 || y==numLayers-1 || z==0 || z==numLayers-1 )
217 beb325a0 Leszek Koltunski
            {
218 e6cf7283 Leszek Koltunski
            tmp[currentPosition++] = new float[] {x-diff,y-diff,z-diff};
219 a10ada2a Leszek Koltunski
            }
220 47ba5ddc Leszek Koltunski
221 a10ada2a Leszek Koltunski
    return tmp;
222
    }
223 47ba5ddc Leszek Koltunski
224 beb325a0 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
225
226 10585385 Leszek Koltunski
  Static4D[] getQuats()
227 a10ada2a Leszek Koltunski
    {
228 10585385 Leszek Koltunski
    return QUATS;
229 a10ada2a Leszek Koltunski
    }
230 47ba5ddc Leszek Koltunski
231 eaee1ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
232
233
  boolean shouldResetTextureMaps()
234
    {
235
    return false;
236
    }
237
238 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
239
240 411c6285 Leszek Koltunski
  int getNumFaces()
241 a10ada2a Leszek Koltunski
    {
242 411c6285 Leszek Koltunski
    return FACE_COLORS.length;
243 8f53e513 Leszek Koltunski
    }
244
245 7403cdfa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
246
247 e6734aa9 Leszek Koltunski
  float[][] getCuts(int numLayers)
248 7403cdfa Leszek Koltunski
    {
249 e6734aa9 Leszek Koltunski
    float[][] cuts = new float[3][numLayers-1];
250 a97e02b7 Leszek Koltunski
251 a64e07d0 Leszek Koltunski
    for(int i=0; i<numLayers-1; i++)
252 a97e02b7 Leszek Koltunski
      {
253 e6734aa9 Leszek Koltunski
      float cut = (2-numLayers)*0.5f + i;
254
      cuts[0][i] = cut;
255
      cuts[1][i] = cut;
256
      cuts[2][i] = cut;
257 a97e02b7 Leszek Koltunski
      }
258
259
    return cuts;
260 7403cdfa Leszek Koltunski
    }
261
262 eab9d8f8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
263
264 a64e07d0 Leszek Koltunski
  int getNumStickerTypes(int numLayers)
265 eab9d8f8 Leszek Koltunski
    {
266 b1f2ccf5 Leszek Koltunski
    return STICKERS.length;
267 eab9d8f8 Leszek Koltunski
    }
268
269 8f53e513 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
270
271
  int getNumCubitFaces()
272
    {
273
    return FACE_COLORS.length;
274 411c6285 Leszek Koltunski
    }
275 47ba5ddc Leszek Koltunski
276 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
277
278
  float getScreenRatio()
279
    {
280
    return 0.5f;
281
    }
282
283 f6d06256 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
284
285
  int getFaceColor(int cubit, int cubitface, int size)
286
    {
287 2ef489e2 Leszek Koltunski
    return CUBITS[cubit].mRotationRow[cubitface/2] == (cubitface%2==0 ? (1<<(size-1)):1) ? cubitface : NUM_FACES;
288 f6d06256 Leszek Koltunski
    }
289
290 fb377dae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
291
292
  float returnMultiplier()
293
    {
294 d99f3a48 Leszek Koltunski
    return getNumLayers();
295 fb377dae Leszek Koltunski
    }
296
297 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
298
// PUBLIC API
299
300 12ad3fca Leszek Koltunski
  public Static3D[] getRotationAxis()
301
    {
302 ad38d800 Leszek Koltunski
    return ROT_AXIS;
303 12ad3fca Leszek Koltunski
    }
304
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306
307 925ed78f Leszek Koltunski
  public int[] getBasicAngle()
308 e844c116 Leszek Koltunski
    {
309 925ed78f Leszek Koltunski
    return BASIC_ANGLE;
310 e844c116 Leszek Koltunski
    }
311 39e74052 Leszek Koltunski
312 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
313
314 9f171eba Leszek Koltunski
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
315 7c969a6d Leszek Koltunski
    {
316 9f171eba Leszek Koltunski
    if( curr==0 )
317 5cf34c5f Leszek Koltunski
      {
318 9f171eba Leszek Koltunski
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
319 7c969a6d Leszek Koltunski
      }
320
    else
321
      {
322 8e6dc249 Leszek Koltunski
      int newVector = rnd.nextInt(NUM_AXIS-1);
323 9f171eba Leszek Koltunski
      scramble[curr][0] = (newVector>=scramble[curr-1][0] ? newVector+1 : newVector);
324 8e6dc249 Leszek Koltunski
325
      // All three axis must be present among every four consecutive rotations.
326
      // Otherwise in case of odd-sized cubes we can get four consecutive rotations
327
      // that collapse to a NOP
328
      // (X,midLayer,180)->(Y,midLayer,180)->(X,midLayer,180)->(Y,midLayer,180) = NOP
329
      if( curr>=3 && scramble[curr-1][0]==scramble[curr-3][0] )
330
        {
331
        for( int ax=0; ax<NUM_AXIS; ax++)
332
          {
333
          if( scramble[curr-1][0]!=ax && scramble[curr-2][0]!=ax )
334
            {
335
            scramble[curr][0] = ax;
336
            break;
337
            }
338
          }
339
        }
340 5cf34c5f Leszek Koltunski
      }
341
342 7c969a6d Leszek Koltunski
    float rowFloat = rnd.nextFloat();
343 0203be88 Leszek Koltunski
    int numLayers = getNumLayers();
344 7c969a6d Leszek Koltunski
345 0203be88 Leszek Koltunski
    for(int row=0; row<numLayers; row++)
346 7c969a6d Leszek Koltunski
      {
347 0203be88 Leszek Koltunski
      if( rowFloat*numLayers <= row+1 )
348 bbc6471c Leszek Koltunski
        {
349 9f171eba Leszek Koltunski
        scramble[curr][1] = row;
350 bbc6471c Leszek Koltunski
        break;
351
        }
352 7c969a6d Leszek Koltunski
      }
353
354 5043d5d0 Leszek Koltunski
    switch( rnd.nextInt(4) )
355
      {
356 9f171eba Leszek Koltunski
      case 0: scramble[curr][2] = -2; break;
357
      case 1: scramble[curr][2] = -1; break;
358
      case 2: scramble[curr][2] =  1; break;
359
      case 3: scramble[curr][2] =  2; break;
360 5043d5d0 Leszek Koltunski
      }
361 e46e17fb Leszek Koltunski
    }
362 f0336037 Leszek Koltunski
363 6b6504fe Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
364
365
  public boolean isSolved()
366
    {
367
    int index = CUBITS[0].mQuatIndex;
368
369
    for(int i=1; i<NUM_CUBITS; i++)
370
      {
371 722b2512 Leszek Koltunski
      if( thereIsVisibleDifference(CUBITS[i], index) ) return false;
372 6b6504fe Leszek Koltunski
      }
373
374
    return true;
375
    }
376
377 f0336037 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
378 6fd4a72c Leszek Koltunski
379
  public int getObjectName(int numLayers)
380
    {
381
    switch(numLayers)
382
      {
383
      case 2: return R.string.cube2;
384
      case 3: return R.string.cube3;
385
      case 4: return R.string.cube4;
386
      case 5: return R.string.cube5;
387
      }
388
    return R.string.cube3;
389
    }
390
391
///////////////////////////////////////////////////////////////////////////////////////////////////
392
393
  public int getInventor(int numLayers)
394
    {
395
    switch(numLayers)
396
      {
397
      case 2: return R.string.cube2_inventor;
398
      case 3: return R.string.cube3_inventor;
399
      case 4: return R.string.cube4_inventor;
400
      case 5: return R.string.cube5_inventor;
401
      }
402
    return R.string.cube3_inventor;
403
    }
404
405
///////////////////////////////////////////////////////////////////////////////////////////////////
406
407
  public int getComplexity(int numLayers)
408
    {
409
    switch(numLayers)
410
      {
411
      case 2: return 4;
412
      case 3: return 6;
413
      case 4: return 8;
414
      case 5: return 10;
415
      }
416
    return 6;
417
    }
418 0c52af30 Leszek Koltunski
}