Project

General

Profile

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

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

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.FactoryCubit;
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.MeshBase;
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
  private static MeshBase[] mMeshes;
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
///////////////////////////////////////////////////////////////////////////////////////////////////
135

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

    
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143

    
144
  MeshBase createCubitMesh(int cubit, int numLayers)
145
    {
146
    if( mMeshes==null )
147
      {
148
      FactoryCubit factory = FactoryCubit.getInstance();
149
      factory.clear();
150
      mMeshes = new MeshBase[ObjectList.CUBE.getNumVariants()];
151
      }
152

    
153
    int ordinal= ObjectList.CUBE.ordinal();
154
    int index  = ObjectList.getSizeIndex(ordinal,getNumLayers());
155

    
156
    if( mMeshes[index]==null )
157
      {
158
      int extraI, extraV, num;
159
      float height;
160

    
161
      switch(numLayers)
162
        {
163
        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
        }
168

    
169
      float[][] bands     = new float[][] { {height,35,0.5f,0.7f,num,extraI,extraV} };
170
      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
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
174
      int[] centerIndexes = new int[] { 0,0,0,0,0,0,0,0 };
175

    
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
                                                  centers, centerIndexes,
183
                                                  getNumCubitFaces(), null );
184
      }
185

    
186
    return mMeshes[index].copy(true);
187
    }
188

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

    
191
  int getColor(int face)
192
    {
193
    return FACE_COLORS[face];
194
    }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

    
198
  ObjectSticker retSticker(int face)
199
    {
200
    return mStickers[face/NUM_FACES];
201
    }
202

    
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204

    
205
  float[][] getCubitPositions(int numLayers)
206
    {
207
    int numCubits = numLayers>1 ? 6*numLayers*numLayers - 12*numLayers + 8 : 1;
208
    float[][] tmp = new float[numCubits][];
209

    
210
    float diff = 0.5f*(numLayers-1);
211
    int currentPosition = 0;
212

    
213
    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
            {
218
            tmp[currentPosition++] = new float[] {x-diff,y-diff,z-diff};
219
            }
220

    
221
    return tmp;
222
    }
223

    
224
///////////////////////////////////////////////////////////////////////////////////////////////////
225

    
226
  Static4D[] getQuats()
227
    {
228
    return QUATS;
229
    }
230

    
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232

    
233
  boolean shouldResetTextureMaps()
234
    {
235
    return false;
236
    }
237

    
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239

    
240
  int getNumFaces()
241
    {
242
    return FACE_COLORS.length;
243
    }
244

    
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246

    
247
  float[][] getCuts(int numLayers)
248
    {
249
    float[][] cuts = new float[3][numLayers-1];
250

    
251
    for(int i=0; i<numLayers-1; i++)
252
      {
253
      float cut = (2-numLayers)*0.5f + i;
254
      cuts[0][i] = cut;
255
      cuts[1][i] = cut;
256
      cuts[2][i] = cut;
257
      }
258

    
259
    return cuts;
260
    }
261

    
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263

    
264
  int getNumStickerTypes(int numLayers)
265
    {
266
    return STICKERS.length;
267
    }
268

    
269
///////////////////////////////////////////////////////////////////////////////////////////////////
270

    
271
  int getNumCubitFaces()
272
    {
273
    return FACE_COLORS.length;
274
    }
275

    
276
///////////////////////////////////////////////////////////////////////////////////////////////////
277

    
278
  float getScreenRatio()
279
    {
280
    return 0.5f;
281
    }
282

    
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284

    
285
  int getFaceColor(int cubit, int cubitface, int size)
286
    {
287
    return CUBITS[cubit].mRotationRow[cubitface/2] == (cubitface%2==0 ? (1<<(size-1)):1) ? cubitface : NUM_FACES;
288
    }
289

    
290
///////////////////////////////////////////////////////////////////////////////////////////////////
291

    
292
  float returnMultiplier()
293
    {
294
    return getNumLayers();
295
    }
296

    
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298
// PUBLIC API
299

    
300
  public Static3D[] getRotationAxis()
301
    {
302
    return ROT_AXIS;
303
    }
304

    
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306

    
307
  public int[] getBasicAngle()
308
    {
309
    return BASIC_ANGLE;
310
    }
311

    
312
///////////////////////////////////////////////////////////////////////////////////////////////////
313

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

    
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
      }
341

    
342
    float rowFloat = rnd.nextFloat();
343
    int numLayers = getNumLayers();
344

    
345
    for(int row=0; row<numLayers; row++)
346
      {
347
      if( rowFloat*numLayers <= row+1 )
348
        {
349
        scramble[curr][1] = row;
350
        break;
351
        }
352
      }
353

    
354
    switch( rnd.nextInt(4) )
355
      {
356
      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
      }
361
    }
362

    
363
///////////////////////////////////////////////////////////////////////////////////////////////////
364

    
365
  public boolean isSolved()
366
    {
367
    int index = CUBITS[0].mQuatIndex;
368

    
369
    for(int i=1; i<NUM_CUBITS; i++)
370
      {
371
      if( thereIsVisibleDifference(CUBITS[i], index) ) return false;
372
      }
373

    
374
    return true;
375
    }
376

    
377
///////////////////////////////////////////////////////////////////////////////////////////////////
378

    
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
}
(22-22/41)