Project

General

Profile

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

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

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.helpers.ScrambleState;
27
import org.distorted.library.main.DistortedEffects;
28
import org.distorted.library.main.DistortedTexture;
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
public class TwistyPyraminx extends TwistyObject
39
{
40
  static final float SCREEN_RATIO = 0.88f;
41

    
42
  static final Static3D[] ROT_AXIS = new Static3D[]
43
         {
44
           new Static3D(     0,-SQ3/3,-SQ6/3),
45
           new Static3D(     0,-SQ3/3,+SQ6/3),
46
           new Static3D(+SQ6/3,+SQ3/3,     0),
47
           new Static3D(-SQ6/3,+SQ3/3,     0),
48
         };
49

    
50
  private static final int[] BASIC_ANGLE = new int[] { 3,3,3,3 };
51

    
52
  private static final int[] FACE_COLORS = new int[]
53
         {
54
           COLOR_GREEN , COLOR_YELLOW,
55
           COLOR_BLUE  , COLOR_RED
56
         };
57

    
58
  // computed with res/raw/compute_quats.c
59
  private static final Static4D[] QUATS = new Static4D[]
60
         {
61
           new Static4D(  0.0f,   0.0f,   0.0f,  1.0f),
62
           new Static4D(  0.0f,   1.0f,   0.0f,  0.0f),
63
           new Static4D( SQ2/2,   0.5f,   0.0f,  0.5f),
64
           new Static4D(-SQ2/2,   0.5f,   0.0f,  0.5f),
65
           new Static4D(  0.0f,  -0.5f, -SQ2/2,  0.5f),
66
           new Static4D(  0.0f,  -0.5f,  SQ2/2,  0.5f),
67
           new Static4D( SQ2/2,   0.5f,   0.0f, -0.5f),
68
           new Static4D(-SQ2/2,   0.5f,   0.0f, -0.5f),
69
           new Static4D(  0.0f,  -0.5f, -SQ2/2, -0.5f),
70
           new Static4D(  0.0f,  -0.5f,  SQ2/2, -0.5f),
71
           new Static4D( SQ2/2,   0.0f,  SQ2/2,  0.0f),
72
           new Static4D(-SQ2/2,   0.0f,  SQ2/2,  0.0f)
73
         };
74

    
75
  private static final double[][] VERTICES_TETRA = new double[][]
76
          {
77
             {-0.5, SQ2/4, 0.0},
78
             { 0.5, SQ2/4, 0.0},
79
             { 0.0,-SQ2/4, 0.5},
80
             { 0.0,-SQ2/4,-0.5}
81
          };
82

    
83
  private static final int[][] VERT_INDEXES_TETRA = new int[][]
84
          {
85
             {2,1,0},   // counterclockwise!
86
             {3,0,1},
87
             {3,2,0},
88
             {2,3,1}
89
          };
90

    
91
  private static final double[][] VERTICES_OCTA = new double[][]
92
          {
93
             { 0.5,   0.0, 0.5},
94
             { 0.5,   0.0,-0.5},
95
             {-0.5,   0.0,-0.5},
96
             {-0.5,   0.0, 0.5},
97
             { 0.0, SQ2/2, 0.0},
98
             { 0.0,-SQ2/2, 0.0}
99
          };
100

    
101
  private static final int[][] VERT_INDEXES_OCTA = new int[][]
102
          {
103
             {3,0,4},   // counterclockwise!
104
             {0,1,4},
105
             {1,2,4},
106
             {2,3,4},
107
             {5,0,3},
108
             {5,1,0},
109
             {5,2,1},
110
             {5,3,2}
111
          };
112

    
113
  private static final float[][] STICKERS = new float[][]
114
          {
115
             { -0.4330127f, -0.25f, 0.4330127f, -0.25f, 0.0f, 0.5f }
116
          };
117

    
118
  private static final ObjectSticker[] mStickers;
119

    
120
  static
121
    {
122
    mStickers = new ObjectSticker[STICKERS.length];
123
    final float stroke = 0.08f;
124
    final float radius = 0.06f;
125
    final float[] radii= {radius,radius,radius};
126
    mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke);
127
    }
128

    
129
  private int mCurrState;
130
  private int mIndexExcluded;
131
  private ScrambleState[] mStates;
132
  private int[][] mScrambleTable;
133
  private int[] mNumOccurences;
134

    
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

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

    
142
    initializeScrambleStates(size);
143
    }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146

    
147
  private int[][] generateState(int start, int end)
148
    {
149
    int len = end-start+1;
150
    int[] tmp = new int[6*len];
151

    
152
    for(int i=0; i<len; i++)
153
      {
154
      tmp[6*i  ] = start;
155
      tmp[6*i+1] = -1;
156
      tmp[6*i+2] = start;
157
      tmp[6*i+3] = start;
158
      tmp[6*i+4] = +1;
159
      tmp[6*i+5] = start;
160

    
161
      start++;
162
      }
163

    
164
    return new int[][] {tmp,tmp,tmp,tmp};
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  private void initializeScrambleStates(int numLayers)
170
    {
171
    mStates = new ScrambleState[numLayers];
172

    
173
    for(int i=0; i<numLayers-1; i++)
174
      {
175
      mStates[i] = new ScrambleState( generateState(0,numLayers-1-i) );
176
      }
177

    
178
    mStates[numLayers-1] = new ScrambleState( generateState(1,numLayers-2) );
179
    }
180

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

    
183
  int[] getSolvedQuats(int cubit, int numLayers)
184
    {
185
    int status = retCubitSolvedStatus(cubit,numLayers);
186
    return status<0 ? null : buildSolvedQuats(MovementPyraminx.FACE_AXIS[status],QUATS);
187
    }
188

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

    
191
  private void addTetrahedralLattice(int size, int index, float[][] pos)
192
    {
193
    final float DX = 1.0f;
194
    final float DY = SQ2/2;
195
    final float DZ = 1.0f;
196

    
197
    float startX = 0.0f;
198
    float startY =-DY*(size-1)/2;
199
    float startZ = DZ*(size-1)/2;
200

    
201
    for(int layer=0; layer<size; layer++)
202
      {
203
      float currX = startX;
204
      float currY = startY;
205

    
206
      for(int x=0; x<layer+1; x++)
207
        {
208
        float currZ = startZ;
209

    
210
        for(int z=0; z<size-layer; z++)
211
          {
212
          pos[index] = new float[] {currX,currY,currZ};
213
          index++;
214
          currZ -= DZ;
215
          }
216

    
217
        currX += DX;
218
        }
219

    
220
      startX-=DX/2;
221
      startY+=DY;
222
      startZ-=DZ/2;
223
      }
224
    }
225

    
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227
// there are (n^3-n)/6 octahedrons and ((n+1)^3 - (n+1))/6 tetrahedrons
228

    
229
  float[][] getCubitPositions(int size)
230
    {
231
    int numOcta = (size-1)*size*(size+1)/6;
232
    int numTetra= size*(size+1)*(size+2)/6;
233
    float[][] ret = new float[numOcta+numTetra][];
234

    
235
    addTetrahedralLattice(size-1,      0,ret);
236
    addTetrahedralLattice(size  ,numOcta,ret);
237

    
238
    return ret;
239
    }
240

    
241
///////////////////////////////////////////////////////////////////////////////////////////////////
242

    
243
  Static4D[] getQuats()
244
    {
245
    return QUATS;
246
    }
247

    
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249

    
250
  int getNumFaces()
251
    {
252
    return FACE_COLORS.length;
253
    }
254

    
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256

    
257
  int getSolvedFunctionIndex()
258
    {
259
    return 0;
260
    }
261

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

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

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

    
271
  float[][] getCuts(int size)
272
    {
273
    float[][] cuts = new float[4][size-1];
274

    
275
    for(int i=0; i<size-1; i++)
276
      {
277
      float cut = (1.0f-0.25f*size+i)*(SQ6/3);
278
      cuts[0][i] = cut;
279
      cuts[1][i] = cut;
280
      cuts[2][i] = cut;
281
      cuts[3][i] = cut;
282
      }
283

    
284
    return cuts;
285
    }
286

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

    
289
  int getNumCubitFaces()
290
    {
291
    return 8;
292
    }
293

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

    
296
  float getScreenRatio()
297
    {
298
    return SCREEN_RATIO;
299
    }
300

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

    
303
  boolean shouldResetTextureMaps()
304
    {
305
    return false;
306
    }
307

    
308
///////////////////////////////////////////////////////////////////////////////////////////////////
309

    
310
  private int getNumOctahedrons(int numLayers)
311
    {
312
    return (numLayers-1)*numLayers*(numLayers+1)/6;
313
    }
314

    
315
///////////////////////////////////////////////////////////////////////////////////////////////////
316

    
317
  private int faceColor(int cubit, int axis)
318
    {
319
    return CUBITS[cubit].mRotationRow[axis] == 1 ? axis : NUM_FACES;
320
    }
321

    
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323

    
324
  int getFaceColor(int cubit, int cubitface, int size)
325
    {
326
    if( cubit< (size-1)*size*(size+1)/6 )
327
      {
328
      switch( cubitface )
329
        {
330
        case 0: return faceColor(cubit,0);
331
        case 2: return faceColor(cubit,1);
332
        case 5: return faceColor(cubit,3);
333
        case 7: return faceColor(cubit,2);
334
        default:return NUM_FACES;
335
        }
336
      }
337
    else
338
      {
339
      return cubitface<NUM_FACES ? faceColor(cubit,cubitface) : NUM_FACES;
340
      }
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

    
345
  ObjectShape getObjectShape(int cubit, int numLayers)
346
    {
347
    int variant = getCubitVariant(cubit,numLayers);
348

    
349
    if( variant==0 )
350
      {
351
      int N = numLayers==3? 6 : 5;
352
      int E = numLayers==3? 2 : 1;
353
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
354
      int[] bandIndices   = new int[] { 0,0,0,0,0,0,0,0 };
355
      float[][] corners   = new float[][] { {0.04f,0.20f} };
356
      int[] cornerIndices = new int[] { 0,0,0,0,0,0 };
357
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
358
      int[] centerIndices = new int[] { 0,0,0,0,0,0 };
359
      return new ObjectShape(VERTICES_OCTA,VERT_INDEXES_OCTA,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
360
      }
361
    else
362
      {
363
      int N = numLayers==3? 6 : 5;
364
      int E = numLayers==3? 2 : 1;
365
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
366
      int[] bandIndices   = new int[] { 0,0,0,0 };
367
      float[][] corners   = new float[][] { {0.06f,0.15f} };
368
      int[] cornerIndices = new int[] { 0,0,0,0 };
369
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
370
      int[] centerIndices = new int[] { 0,0,0,0 };
371
      return new ObjectShape(VERTICES_TETRA,VERT_INDEXES_TETRA,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
372
      }
373
    }
374

    
375
///////////////////////////////////////////////////////////////////////////////////////////////////
376

    
377
  Static4D getQuat(int cubit, int numLayers)
378
    {
379
    return QUATS[0];
380
    }
381

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383

    
384
  int getNumCubitVariants(int numLayers)
385
    {
386
    return 2;
387
    }
388

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
  int getCubitVariant(int cubit, int numLayers)
392
    {
393
    return cubit<getNumOctahedrons(numLayers) ? 0:1;
394
    }
395

    
396
///////////////////////////////////////////////////////////////////////////////////////////////////
397

    
398
  int getColor(int face)
399
    {
400
    return FACE_COLORS[face];
401
    }
402

    
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404

    
405
  ObjectSticker retSticker(int face)
406
    {
407
    return mStickers[face/NUM_FACES];
408
    }
409

    
410
///////////////////////////////////////////////////////////////////////////////////////////////////
411
// SQ6/3 = height of the tetrahedron
412

    
413
  float returnMultiplier()
414
    {
415
    return getNumLayers()/(SQ6/3);
416
    }
417

    
418
///////////////////////////////////////////////////////////////////////////////////////////////////
419

    
420
  private void initializeScrambling()
421
    {
422
    int numLayers = getNumLayers();
423

    
424
    if( mScrambleTable ==null )
425
      {
426
      mScrambleTable = new int[NUM_AXIS][numLayers];
427
      }
428
    if( mNumOccurences ==null )
429
      {
430
      int max=0;
431

    
432
      for (ScrambleState mState : mStates)
433
        {
434
        int tmp = mState.getTotal(-1);
435
        if (max < tmp) max = tmp;
436
        }
437

    
438
      mNumOccurences = new int[max];
439
      }
440

    
441
    for(int i=0; i<NUM_AXIS; i++)
442
      for(int j=0; j<numLayers; j++) mScrambleTable[i][j] = 0;
443
    }
444

    
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446
// PUBLIC API
447

    
448
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int totalScrambles)
449
    {
450
    if( curr==0 )
451
      {
452
      mCurrState     = 0;
453
      mIndexExcluded =-1;
454
      initializeScrambling();
455
      }
456

    
457
    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
458

    
459
    scramble[curr][0] = info[0];
460
    scramble[curr][1] = info[1];
461
    scramble[curr][2] = info[2];
462

    
463
    mCurrState     = info[3];
464
    mIndexExcluded = info[0];
465
    }
466

    
467
///////////////////////////////////////////////////////////////////////////////////////////////////
468

    
469
  public Static3D[] getRotationAxis()
470
    {
471
    return ROT_AXIS;
472
    }
473

    
474
///////////////////////////////////////////////////////////////////////////////////////////////////
475

    
476
  public int[] getBasicAngle()
477
    {
478
    return BASIC_ANGLE;
479
    }
480

    
481
///////////////////////////////////////////////////////////////////////////////////////////////////
482

    
483
  public int getObjectName(int numLayers)
484
    {
485
    switch(numLayers)
486
      {
487
      case 3: return R.string.pyra3;
488
      case 4: return R.string.pyra4;
489
      case 5: return R.string.pyra5;
490
      }
491
    return R.string.pyra3;
492
    }
493

    
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495

    
496
  public int getInventor(int numLayers)
497
    {
498
    switch(numLayers)
499
      {
500
      case 3: return R.string.pyra3_inventor;
501
      case 4: return R.string.pyra4_inventor;
502
      case 5: return R.string.pyra5_inventor;
503
      }
504
    return R.string.pyra3_inventor;
505
    }
506

    
507
///////////////////////////////////////////////////////////////////////////////////////////////////
508

    
509
  public int getComplexity(int numLayers)
510
    {
511
    switch(numLayers)
512
      {
513
      case 3: return 4;
514
      case 4: return 6;
515
      case 5: return 8;
516
      }
517
    return 4;
518
    }
519
}
(34-34/41)