Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyCube.java @ 8db55f55

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
  int[] getSolvedQuats(int cubit, int numLayers)
142
    {
143
    int status = retCubitSolvedStatus(cubit,numLayers);
144
    return status<0 ? null : buildSolvedQuats(MovementCube.FACE_AXIS[status],QUATS);
145
    }
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148

    
149
  ObjectShape getObjectShape(int cubit, int numLayers)
150
    {
151
    int extraI, extraV, num;
152
    float height;
153

    
154
    switch(numLayers)
155
      {
156
      case 2 : num = 6; extraI = 2; extraV = 2; height = 0.045f; break;
157
      case 3 : num = 5; extraI = 2; extraV = 2; height = 0.045f; break;
158
      case 4 : num = 5; extraI = 1; extraV = 1; height = 0.045f; break;
159
      default: num = 5; extraI = 0; extraV = 0; height = 0.045f; break;
160
      }
161

    
162
    float[][] bands     = new float[][] { {height,35,0.5f,0.7f,num,extraI,extraV} };
163
    int[] bandIndices   = new int[] { 0,0,0,0,0,0};
164
    float[][] corners   = new float[][] { {0.036f,0.12f} };
165
    int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
166
    float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
167
    int[] centerIndices = new int[] { 0,0,0,0,0,0,0,0 };
168

    
169
    return new ObjectShape(VERTICES,VERT_INDEXES,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
170
    }
171

    
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173

    
174
  Static4D getQuat(int cubit, int numLayers)
175
    {
176
    return QUATS[0];
177
    }
178

    
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180

    
181
  int getNumCubitVariants(int numLayers)
182
    {
183
    return 1;
184
    }
185

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

    
188
  int getCubitVariant(int cubit, int numLayers)
189
    {
190
    return 0;
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
  int getColor(int face)
196
    {
197
    return FACE_COLORS[face];
198
    }
199

    
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201

    
202
  ObjectSticker retSticker(int face)
203
    {
204
    return mStickers[face/NUM_FACES];
205
    }
206

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

    
209
  float[][] getCubitPositions(int numLayers)
210
    {
211
    int numCubits = numLayers>1 ? 6*numLayers*numLayers - 12*numLayers + 8 : 1;
212
    float[][] tmp = new float[numCubits][];
213

    
214
    float diff = 0.5f*(numLayers-1);
215
    int currentPosition = 0;
216

    
217
    for(int x = 0; x<numLayers; x++)
218
      for(int y = 0; y<numLayers; y++)
219
        for(int z = 0; z<numLayers; z++)
220
          if( x==0 || x==numLayers-1 || y==0 || y==numLayers-1 || z==0 || z==numLayers-1 )
221
            {
222
            tmp[currentPosition++] = new float[] {x-diff,y-diff,z-diff};
223
            }
224

    
225
    return tmp;
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  Static4D[] getQuats()
231
    {
232
    return QUATS;
233
    }
234

    
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236

    
237
  boolean shouldResetTextureMaps()
238
    {
239
    return false;
240
    }
241

    
242
///////////////////////////////////////////////////////////////////////////////////////////////////
243

    
244
  int getNumFaces()
245
    {
246
    return FACE_COLORS.length;
247
    }
248

    
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250

    
251
  float[][] getCuts(int numLayers)
252
    {
253
    float[][] cuts = new float[3][numLayers-1];
254

    
255
    for(int i=0; i<numLayers-1; i++)
256
      {
257
      float cut = (2-numLayers)*0.5f + i;
258
      cuts[0][i] = cut;
259
      cuts[1][i] = cut;
260
      cuts[2][i] = cut;
261
      }
262

    
263
    return cuts;
264
    }
265

    
266
///////////////////////////////////////////////////////////////////////////////////////////////////
267

    
268
  int getSolvedFunctionIndex()
269
    {
270
    return 0;
271
    }
272

    
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274

    
275
  int getNumStickerTypes(int numLayers)
276
    {
277
    return STICKERS.length;
278
    }
279

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

    
282
  int getNumCubitFaces()
283
    {
284
    return FACE_COLORS.length;
285
    }
286

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

    
289
  float getScreenRatio()
290
    {
291
    return 0.5f;
292
    }
293

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

    
296
  int getFaceColor(int cubit, int cubitface, int numLayers)
297
    {
298
    return CUBITS[cubit].mRotationRow[cubitface/2] == (cubitface%2==0 ? (1<<(numLayers-1)):1) ? cubitface : NUM_FACES;
299
    }
300

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

    
303
  float returnMultiplier()
304
    {
305
    return getNumLayers();
306
    }
307

    
308
///////////////////////////////////////////////////////////////////////////////////////////////////
309
// PUBLIC API
310

    
311
  public Static3D[] getRotationAxis()
312
    {
313
    return ROT_AXIS;
314
    }
315

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

    
318
  public int[] getBasicAngle()
319
    {
320
    return BASIC_ANGLE;
321
    }
322

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

    
325
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
326
    {
327
    if( curr==0 )
328
      {
329
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
330
      }
331
    else
332
      {
333
      int newVector = rnd.nextInt(NUM_AXIS-1);
334
      scramble[curr][0] = (newVector>=scramble[curr-1][0] ? newVector+1 : newVector);
335

    
336
      // All three axis must be present among every four consecutive rotations.
337
      // Otherwise in case of odd-sized cubes we can get four consecutive rotations
338
      // that collapse to a NOP
339
      // (X,midLayer,180)->(Y,midLayer,180)->(X,midLayer,180)->(Y,midLayer,180) = NOP
340
      if( curr>=3 && scramble[curr-1][0]==scramble[curr-3][0] )
341
        {
342
        for( int ax=0; ax<NUM_AXIS; ax++)
343
          {
344
          if( scramble[curr-1][0]!=ax && scramble[curr-2][0]!=ax )
345
            {
346
            scramble[curr][0] = ax;
347
            break;
348
            }
349
          }
350
        }
351
      }
352

    
353
    float rowFloat = rnd.nextFloat();
354
    int numLayers = getNumLayers();
355

    
356
    for(int row=0; row<numLayers; row++)
357
      {
358
      if( rowFloat*numLayers <= row+1 )
359
        {
360
        scramble[curr][1] = row;
361
        break;
362
        }
363
      }
364

    
365
    switch( rnd.nextInt(4) )
366
      {
367
      case 0: scramble[curr][2] = -2; break;
368
      case 1: scramble[curr][2] = -1; break;
369
      case 2: scramble[curr][2] =  1; break;
370
      case 3: scramble[curr][2] =  2; break;
371
      }
372
    }
373

    
374
///////////////////////////////////////////////////////////////////////////////////////////////////
375

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

    
388
///////////////////////////////////////////////////////////////////////////////////////////////////
389

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

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

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