Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyPyraminx.java @ abe288a3

1 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 1f9772f3 Leszek Koltunski
package org.distorted.objects;
21 e844c116 Leszek Koltunski
22 ccf9fec5 Leszek Koltunski
import android.content.res.Resources;
23 e844c116 Leszek Koltunski
24 045d8cbd Leszek Koltunski
import org.distorted.helpers.ObjectShape;
25 9c06394a Leszek Koltunski
import org.distorted.helpers.ObjectSticker;
26 e844c116 Leszek Koltunski
import org.distorted.library.main.DistortedEffects;
27
import org.distorted.library.main.DistortedTexture;
28 efa8aa48 Leszek Koltunski
import org.distorted.library.mesh.MeshSquare;
29 e844c116 Leszek Koltunski
import org.distorted.library.type.Static3D;
30
import org.distorted.library.type.Static4D;
31 6fd4a72c Leszek Koltunski
import org.distorted.main.R;
32 e844c116 Leszek Koltunski
33 7c969a6d Leszek Koltunski
import java.util.Random;
34
35 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
36
37 9c2f0c91 Leszek Koltunski
public class TwistyPyraminx extends TwistyObject
38 e844c116 Leszek Koltunski
{
39 f074c272 Leszek Koltunski
  static final float SCREEN_RATIO = 0.88f;
40
41 ad38d800 Leszek Koltunski
  static final Static3D[] ROT_AXIS = new Static3D[]
42 e844c116 Leszek Koltunski
         {
43 ac940e24 Leszek Koltunski
           new Static3D(     0,-SQ3/3,-SQ6/3),
44
           new Static3D(     0,-SQ3/3,+SQ6/3),
45
           new Static3D(+SQ6/3,+SQ3/3,     0),
46
           new Static3D(-SQ6/3,+SQ3/3,     0),
47 ad38d800 Leszek Koltunski
         };
48
49 925ed78f Leszek Koltunski
  private static final int[] BASIC_ANGLE = new int[] { 3,3,3,3 };
50
51 e844c116 Leszek Koltunski
  private static final int[] FACE_COLORS = new int[]
52
         {
53 ece1b58d Leszek Koltunski
           COLOR_GREEN , COLOR_YELLOW,
54
           COLOR_BLUE  , COLOR_RED
55 e844c116 Leszek Koltunski
         };
56
57 9f4c44fe Leszek Koltunski
  // computed with res/raw/compute_quats.c
58 10585385 Leszek Koltunski
  private static final Static4D[] QUATS = new Static4D[]
59 e844c116 Leszek Koltunski
         {
60 10585385 Leszek Koltunski
           new Static4D(  0.0f,   0.0f,   0.0f,  1.0f),
61 ac940e24 Leszek Koltunski
           new Static4D(  0.0f,   1.0f,   0.0f,  0.0f),
62
           new Static4D( SQ2/2,   0.5f,   0.0f,  0.5f),
63
           new Static4D(-SQ2/2,   0.5f,   0.0f,  0.5f),
64
           new Static4D(  0.0f,  -0.5f, -SQ2/2,  0.5f),
65
           new Static4D(  0.0f,  -0.5f,  SQ2/2,  0.5f),
66
           new Static4D( SQ2/2,   0.5f,   0.0f, -0.5f),
67
           new Static4D(-SQ2/2,   0.5f,   0.0f, -0.5f),
68
           new Static4D(  0.0f,  -0.5f, -SQ2/2, -0.5f),
69
           new Static4D(  0.0f,  -0.5f,  SQ2/2, -0.5f),
70
           new Static4D( SQ2/2,   0.0f,  SQ2/2,  0.0f),
71
           new Static4D(-SQ2/2,   0.0f,  SQ2/2,  0.0f)
72 e844c116 Leszek Koltunski
         };
73
74 31cd7256 Leszek Koltunski
  private static final double[][] VERTICES_TETRA = new double[][]
75 b1f2ccf5 Leszek Koltunski
          {
76
             {-0.5, SQ2/4, 0.0},
77
             { 0.5, SQ2/4, 0.0},
78
             { 0.0,-SQ2/4, 0.5},
79
             { 0.0,-SQ2/4,-0.5}
80
          };
81
82 31cd7256 Leszek Koltunski
  private static final int[][] VERT_INDEXES_TETRA = new int[][]
83 b1f2ccf5 Leszek Koltunski
          {
84
             {2,1,0},   // counterclockwise!
85 31cd7256 Leszek Koltunski
             {3,0,1},
86 b1f2ccf5 Leszek Koltunski
             {3,2,0},
87 31cd7256 Leszek Koltunski
             {2,3,1}
88 b1f2ccf5 Leszek Koltunski
          };
89
90 31cd7256 Leszek Koltunski
  private static final double[][] VERTICES_OCTA = new double[][]
91 b1f2ccf5 Leszek Koltunski
          {
92
             { 0.5,   0.0, 0.5},
93
             { 0.5,   0.0,-0.5},
94
             {-0.5,   0.0,-0.5},
95
             {-0.5,   0.0, 0.5},
96
             { 0.0, SQ2/2, 0.0},
97
             { 0.0,-SQ2/2, 0.0}
98
          };
99
100 31cd7256 Leszek Koltunski
  private static final int[][] VERT_INDEXES_OCTA = new int[][]
101 b1f2ccf5 Leszek Koltunski
          {
102
             {3,0,4},   // counterclockwise!
103
             {0,1,4},
104
             {1,2,4},
105
             {2,3,4},
106
             {5,0,3},
107
             {5,1,0},
108
             {5,2,1},
109
             {5,3,2}
110
          };
111
112 31cd7256 Leszek Koltunski
  private static final float[][] STICKERS = new float[][]
113
          {
114
             { -0.4330127f, -0.25f, 0.4330127f, -0.25f, 0.0f, 0.5f }
115
          };
116
117 0203be88 Leszek Koltunski
  private static float[] mRowChances;
118 49f67f9b Leszek Koltunski
119 9c06394a Leszek Koltunski
  private static final ObjectSticker[] mStickers;
120
121
  static
122
    {
123
    mStickers = new ObjectSticker[STICKERS.length];
124
    final float stroke = 0.08f;
125
    final float radius = 0.06f;
126
    final float[] radii= {radius,radius,radius};
127
    mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke);
128
    }
129
130 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
131
132 ac940e24 Leszek Koltunski
  TwistyPyraminx(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
133
                 DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
134 e844c116 Leszek Koltunski
    {
135 db875721 Leszek Koltunski
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.PYRA, res, scrWidth);
136 e844c116 Leszek Koltunski
    }
137
138 0203be88 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
139
140
  private float[] getRowChances(int numLayers)
141
    {
142
    int total = numLayers*(numLayers+1)/2;
143
    float running=0.0f;
144
    float[] chances = new float[numLayers];
145
146
    for(int i=0; i<numLayers; i++)
147
      {
148
      running += (numLayers-i);
149
      chances[i] = running / total;
150
      }
151
152
    return chances;
153
    }
154
155 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
156
157 e6cf7283 Leszek Koltunski
  private void addTetrahedralLattice(int size, int index, float[][] pos)
158 49f67f9b Leszek Koltunski
    {
159 ac940e24 Leszek Koltunski
    final float DX = 1.0f;
160
    final float DY = SQ2/2;
161
    final float DZ = 1.0f;
162 49f67f9b Leszek Koltunski
163 ac940e24 Leszek Koltunski
    float startX = 0.0f;
164
    float startY =-DY*(size-1)/2;
165
    float startZ = DZ*(size-1)/2;
166 769409d2 Leszek Koltunski
167 ac940e24 Leszek Koltunski
    for(int layer=0; layer<size; layer++)
168 49f67f9b Leszek Koltunski
      {
169 ac940e24 Leszek Koltunski
      float currX = startX;
170
      float currY = startY;
171
172
      for(int x=0; x<layer+1; x++)
173
        {
174
        float currZ = startZ;
175
176
        for(int z=0; z<size-layer; z++)
177
          {
178 e6cf7283 Leszek Koltunski
          pos[index] = new float[] {currX,currY,currZ};
179 ac940e24 Leszek Koltunski
          index++;
180
          currZ -= DZ;
181
          }
182
183
        currX += DX;
184
        }
185
186
      startX-=DX/2;
187
      startY+=DY;
188
      startZ-=DZ/2;
189 49f67f9b Leszek Koltunski
      }
190
    }
191
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193 ac940e24 Leszek Koltunski
// there are (n^3-n)/6 octahedrons and ((n+1)^3 - (n+1))/6 tetrahedrons
194 49f67f9b Leszek Koltunski
195 e6cf7283 Leszek Koltunski
  float[][] getCubitPositions(int size)
196 e844c116 Leszek Koltunski
    {
197 ac940e24 Leszek Koltunski
    int numOcta = (size-1)*size*(size+1)/6;
198
    int numTetra= size*(size+1)*(size+2)/6;
199 e6cf7283 Leszek Koltunski
    float[][] ret = new float[numOcta+numTetra][];
200 49f67f9b Leszek Koltunski
201 ac940e24 Leszek Koltunski
    addTetrahedralLattice(size-1,      0,ret);
202
    addTetrahedralLattice(size  ,numOcta,ret);
203 49f67f9b Leszek Koltunski
204 ac940e24 Leszek Koltunski
    return ret;
205 e844c116 Leszek Koltunski
    }
206
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208
209 10585385 Leszek Koltunski
  Static4D[] getQuats()
210 e844c116 Leszek Koltunski
    {
211 10585385 Leszek Koltunski
    return QUATS;
212 e844c116 Leszek Koltunski
    }
213
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215
216
  int getNumFaces()
217
    {
218
    return FACE_COLORS.length;
219
    }
220
221 eab9d8f8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
222
223 a64e07d0 Leszek Koltunski
  int getNumStickerTypes(int numLayers)
224 eab9d8f8 Leszek Koltunski
    {
225 31cd7256 Leszek Koltunski
    return STICKERS.length;
226 eab9d8f8 Leszek Koltunski
    }
227
228 7403cdfa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
229
230 e6734aa9 Leszek Koltunski
  float[][] getCuts(int size)
231 7403cdfa Leszek Koltunski
    {
232 e6734aa9 Leszek Koltunski
    float[][] cuts = new float[4][size-1];
233 a97e02b7 Leszek Koltunski
234
    for(int i=0; i<size-1; i++)
235
      {
236 e6734aa9 Leszek Koltunski
      float cut = (1.0f-0.25f*size+i)*(SQ6/3);
237
      cuts[0][i] = cut;
238
      cuts[1][i] = cut;
239
      cuts[2][i] = cut;
240
      cuts[3][i] = cut;
241 a97e02b7 Leszek Koltunski
      }
242
243
    return cuts;
244 7403cdfa Leszek Koltunski
    }
245
246 8f53e513 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
247
248
  int getNumCubitFaces()
249
    {
250 ac940e24 Leszek Koltunski
    return 8;
251 8f53e513 Leszek Koltunski
    }
252
253 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
254
255
  float getScreenRatio()
256
    {
257 f074c272 Leszek Koltunski
    return SCREEN_RATIO;
258 f0fa83ae Leszek Koltunski
    }
259
260 eaee1ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
261
262
  boolean shouldResetTextureMaps()
263
    {
264
    return false;
265
    }
266
267 31cd7256 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
268
269
  private int getNumOctahedrons(int numLayers)
270
    {
271
    return (numLayers-1)*numLayers*(numLayers+1)/6;
272
    }
273
274 f6d06256 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
275
276 ac940e24 Leszek Koltunski
  private int faceColor(int cubit, int axis)
277 f6d06256 Leszek Koltunski
    {
278 f0450fcc Leszek Koltunski
    return CUBITS[cubit].mRotationRow[axis] == 1 ? axis : NUM_FACES;
279 f6d06256 Leszek Koltunski
    }
280
281 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
282
283 ac940e24 Leszek Koltunski
  int getFaceColor(int cubit, int cubitface, int size)
284 e844c116 Leszek Koltunski
    {
285 ac940e24 Leszek Koltunski
    if( cubit< (size-1)*size*(size+1)/6 )
286 40ab026e Leszek Koltunski
      {
287 ac940e24 Leszek Koltunski
      switch( cubitface )
288
        {
289
        case 0: return faceColor(cubit,0);
290
        case 2: return faceColor(cubit,1);
291
        case 5: return faceColor(cubit,3);
292
        case 7: return faceColor(cubit,2);
293
        default:return NUM_FACES;
294
        }
295 40ab026e Leszek Koltunski
      }
296 ac940e24 Leszek Koltunski
    else
297 89a11f7b Leszek Koltunski
      {
298 ac940e24 Leszek Koltunski
      return cubitface<NUM_FACES ? faceColor(cubit,cubitface) : NUM_FACES;
299 89a11f7b Leszek Koltunski
      }
300 e844c116 Leszek Koltunski
    }
301
302 045d8cbd Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
303
304
  ObjectShape getObjectShape(int cubit, int numLayers)
305
    {
306
    int variant = getCubitVariant(cubit,numLayers);
307
308
    if( variant==0 )
309
      {
310
      int N = numLayers==3? 6 : 5;
311
      int E = numLayers==3? 2 : 1;
312
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
313
      int[] bandIndices   = new int[] { 0,0,0,0,0,0,0,0 };
314
      float[][] corners   = new float[][] { {0.04f,0.20f} };
315
      int[] cornerIndices = new int[] { 0,0,0,0,0,0 };
316
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
317
      int[] centerIndices = new int[] { 0,0,0,0,0,0 };
318
      return new ObjectShape(VERTICES_OCTA,VERT_INDEXES_OCTA,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
319
      }
320
    else
321
      {
322
      int N = numLayers==3? 6 : 5;
323
      int E = numLayers==3? 2 : 1;
324
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
325
      int[] bandIndices   = new int[] { 0,0,0,0 };
326
      float[][] corners   = new float[][] { {0.06f,0.15f} };
327
      int[] cornerIndices = new int[] { 0,0,0,0 };
328
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
329
      int[] centerIndices = new int[] { 0,0,0,0 };
330
      return new ObjectShape(VERTICES_TETRA,VERT_INDEXES_TETRA,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
331
      }
332
    }
333
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335
336 3e605536 Leszek Koltunski
  Static4D getQuat(int cubit, int numLayers)
337 045d8cbd Leszek Koltunski
    {
338
    return QUATS[0];
339
    }
340
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342
343 3e605536 Leszek Koltunski
  int getNumCubitVariants(int numLayers)
344 045d8cbd Leszek Koltunski
    {
345
    return 2;
346
    }
347
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349
350
  int getCubitVariant(int cubit, int numLayers)
351
    {
352
    return cubit<getNumOctahedrons(numLayers) ? 0:1;
353
    }
354
355 7289fd6c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
356
357 9c06394a Leszek Koltunski
  int getColor(int face)
358 7289fd6c Leszek Koltunski
    {
359 9c06394a Leszek Koltunski
    return FACE_COLORS[face];
360
    }
361
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363 76c2bd07 Leszek Koltunski
364 9c06394a Leszek Koltunski
  ObjectSticker retSticker(int face)
365
    {
366
    return mStickers[face/NUM_FACES];
367 7289fd6c Leszek Koltunski
    }
368
369 fb377dae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
370 7403cdfa Leszek Koltunski
// SQ6/3 = height of the tetrahedron
371 fb377dae Leszek Koltunski
372
  float returnMultiplier()
373
    {
374 d99f3a48 Leszek Koltunski
    return getNumLayers()/(SQ6/3);
375 fb377dae Leszek Koltunski
    }
376
377 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
378
// PUBLIC API
379
380 12ad3fca Leszek Koltunski
  public Static3D[] getRotationAxis()
381
    {
382 ad38d800 Leszek Koltunski
    return ROT_AXIS;
383 12ad3fca Leszek Koltunski
    }
384
385
///////////////////////////////////////////////////////////////////////////////////////////////////
386
387 925ed78f Leszek Koltunski
  public int[] getBasicAngle()
388 e844c116 Leszek Koltunski
    {
389 925ed78f Leszek Koltunski
    return BASIC_ANGLE;
390 e844c116 Leszek Koltunski
    }
391 39e74052 Leszek Koltunski
392 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
393
394 9f171eba Leszek Koltunski
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
395 7c969a6d Leszek Koltunski
    {
396 0203be88 Leszek Koltunski
    int numLayers = getNumLayers();
397
398
    if( mRowChances==null ) mRowChances = getRowChances(numLayers);
399
400 9f171eba Leszek Koltunski
    if( curr==0 )
401 5cf34c5f Leszek Koltunski
      {
402 9f171eba Leszek Koltunski
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
403 7c969a6d Leszek Koltunski
      }
404
    else
405
      {
406 3ca97293 Leszek Koltunski
      int newVector = rnd.nextInt(NUM_AXIS-1);
407 9f171eba Leszek Koltunski
      scramble[curr][0] = (newVector>=scramble[curr-1][0] ? newVector+1 : newVector);
408 3ca97293 Leszek Koltunski
409
      // Correct the situation when we first rotate the largest layer, then a tip (which doesn't
410
      // intersect anything besides the largest layer!) and then we try to rotate again along
411
      // the same axis like 2 rotations before - which carries the risk we rotate the largest
412
      // layer back to its spot again and the three moves end up being only a single tip rotation.
413
      if( curr>=2 && scramble[curr-1][1]==(numLayers-1) && scramble[curr][0]==scramble[curr-2][0] )
414
        {
415
        for(int ax=0; ax<NUM_AXIS; ax++)
416
          {
417
          if( scramble[curr-1][0]!=ax && scramble[curr-2][0]!=ax )
418
            {
419
            scramble[curr][0]=ax;
420
            break;
421
            }
422
          }
423
        }
424 5cf34c5f Leszek Koltunski
      }
425 e46e17fb Leszek Koltunski
426 7c969a6d Leszek Koltunski
    float rowFloat = rnd.nextFloat();
427 e46e17fb Leszek Koltunski
428 0203be88 Leszek Koltunski
    for(int row=0; row<numLayers; row++)
429 7c969a6d Leszek Koltunski
      {
430 bbc6471c Leszek Koltunski
      if( rowFloat<=mRowChances[row] )
431
        {
432 9f171eba Leszek Koltunski
        scramble[curr][1] = row;
433 bbc6471c Leszek Koltunski
        break;
434
        }
435 7c969a6d Leszek Koltunski
      }
436
437 5043d5d0 Leszek Koltunski
    switch( rnd.nextInt(2) )
438
      {
439 9f171eba Leszek Koltunski
      case 0: scramble[curr][2] = -1; break;
440
      case 1: scramble[curr][2] =  1; break;
441 5043d5d0 Leszek Koltunski
      }
442 e46e17fb Leszek Koltunski
    }
443 f0336037 Leszek Koltunski
444 6b6504fe Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
445
446
  public boolean isSolved()
447
    {
448
    int index = CUBITS[0].mQuatIndex;
449
450
    for(int i=1; i<NUM_CUBITS; i++)
451
      {
452 722b2512 Leszek Koltunski
      if( thereIsVisibleDifference(CUBITS[i], index) ) return false;
453 6b6504fe Leszek Koltunski
      }
454
455
    return true;
456
    }
457
458 6fd4a72c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
459
460
  public int getObjectName(int numLayers)
461
    {
462
    switch(numLayers)
463
      {
464
      case 3: return R.string.pyra3;
465
      case 4: return R.string.pyra4;
466
      case 5: return R.string.pyra5;
467
      }
468
    return R.string.pyra3;
469
    }
470
471
///////////////////////////////////////////////////////////////////////////////////////////////////
472
473
  public int getInventor(int numLayers)
474
    {
475
    switch(numLayers)
476
      {
477
      case 3: return R.string.pyra3_inventor;
478
      case 4: return R.string.pyra4_inventor;
479
      case 5: return R.string.pyra5_inventor;
480
      }
481
    return R.string.pyra3_inventor;
482
    }
483
484
///////////////////////////////////////////////////////////////////////////////////////////////////
485
486
  public int getComplexity(int numLayers)
487
    {
488
    switch(numLayers)
489
      {
490
      case 3: return 4;
491
      case 4: return 6;
492
      case 5: return 8;
493
      }
494
    return 4;
495
    }
496 e844c116 Leszek Koltunski
}