Project

General

Profile

Download (15.9 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyPyraminx.java @ e7daa161

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.objectlib.objects;
21

    
22
import static org.distorted.objectlib.main.Movement.TYPE_NOT_SPLIT;
23

    
24
import android.content.res.Resources;
25

    
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

    
32
import org.distorted.objectlib.R;
33
import org.distorted.objectlib.main.Movement;
34
import org.distorted.objectlib.main.Movement4;
35
import org.distorted.objectlib.main.ObjectControl;
36
import org.distorted.objectlib.main.ObjectType;
37
import org.distorted.objectlib.helpers.ObjectShape;
38
import org.distorted.objectlib.helpers.ObjectSticker;
39
import org.distorted.objectlib.helpers.ScrambleState;
40
import org.distorted.objectlib.main.Twisty4;
41

    
42
///////////////////////////////////////////////////////////////////////////////////////////////////
43

    
44
public class TwistyPyraminx extends Twisty4
45
{
46
  static final Static3D[] ROT_AXIS = new Static3D[]
47
         {
48
           new Static3D(     0,-SQ3/3,-SQ6/3),
49
           new Static3D(     0,-SQ3/3,+SQ6/3),
50
           new Static3D(+SQ6/3,+SQ3/3,     0),
51
           new Static3D(-SQ6/3,+SQ3/3,     0),
52
         };
53

    
54
  private static final int[][][] ENABLED = new int[][][]
55
      {
56
          {{1,2,3}},{{0,2,3}},{{0,1,3}},{{0,1,2}}
57
      };
58

    
59
  private ScrambleState[] mStates;
60
  private int[] mBasicAngle;
61
  private Static4D[] mQuats;
62
  private float[][] mCuts;
63
  private boolean[][] mLayerRotatable;
64
  private ObjectSticker[] mStickers;
65
  private Movement mMovement;
66

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

    
69
  public TwistyPyraminx(int[] numL, Static4D quat, Static3D move, DistortedTexture texture,
70
                        MeshSquare mesh, DistortedEffects effects, Resources res, int surfaceW, int surfaceH)
71
    {
72
    super(numL, numL[0], quat, move, texture, mesh, effects, res, surfaceW, surfaceH);
73
    }
74

    
75
///////////////////////////////////////////////////////////////////////////////////////////////////
76

    
77
  protected ScrambleState[] getScrambleStates()
78
    {
79
    if( mStates==null )
80
      {
81
      int[] numLayers = getNumLayers();
82
      initializeScrambleStates(numLayers[0]);
83
      }
84

    
85
    return mStates;
86
    }
87

    
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89

    
90
  protected int getResource(int[] numLayers)
91
    {
92
    switch(numLayers[0])
93
      {
94
      case 3: return R.raw.pyra3;
95
      case 4: return R.raw.pyra4;
96
      case 5: return R.raw.pyra5;
97
      }
98

    
99
    return 0;
100
    }
101

    
102
///////////////////////////////////////////////////////////////////////////////////////////////////
103

    
104
  private void initializeQuats()
105
    {
106
    mQuats = new Static4D[]
107
         {
108
         new Static4D(  0.0f,   0.0f,   0.0f,  1.0f),
109
         new Static4D(  0.0f,   1.0f,   0.0f,  0.0f),
110
         new Static4D( SQ2/2,   0.5f,   0.0f,  0.5f),
111
         new Static4D(-SQ2/2,   0.5f,   0.0f,  0.5f),
112
         new Static4D(  0.0f,  -0.5f, -SQ2/2,  0.5f),
113
         new Static4D(  0.0f,  -0.5f,  SQ2/2,  0.5f),
114
         new Static4D( SQ2/2,   0.5f,   0.0f, -0.5f),
115
         new Static4D(-SQ2/2,   0.5f,   0.0f, -0.5f),
116
         new Static4D(  0.0f,  -0.5f, -SQ2/2, -0.5f),
117
         new Static4D(  0.0f,  -0.5f,  SQ2/2, -0.5f),
118
         new Static4D( SQ2/2,   0.0f,  SQ2/2,  0.0f),
119
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,  0.0f)
120
         };
121
    }
122

    
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124

    
125
  private int[][] generateState(int start, int end)
126
    {
127
    int len = end-start+1;
128
    int[] tmp = new int[6*len];
129

    
130
    for(int i=0; i<len; i++)
131
      {
132
      tmp[6*i  ] = start;
133
      tmp[6*i+1] = -1;
134
      tmp[6*i+2] = start;
135
      tmp[6*i+3] = start;
136
      tmp[6*i+4] = +1;
137
      tmp[6*i+5] = start;
138

    
139
      start++;
140
      }
141

    
142
    return new int[][] {tmp,tmp,tmp,tmp};
143
    }
144

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

    
147
  private void initializeScrambleStates(int numLayers)
148
    {
149
    mStates = new ScrambleState[numLayers];
150

    
151
    for(int i=0; i<numLayers-1; i++)
152
      {
153
      mStates[i] = new ScrambleState( generateState(0,numLayers-1-i) );
154
      }
155

    
156
    mStates[numLayers-1] = new ScrambleState( generateState(1,numLayers-2) );
157
    }
158

    
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160

    
161
  protected int[] getSolvedQuats(int cubit, int[] numLayers)
162
    {
163
    if( mQuats==null ) initializeQuats();
164
    int status = retCubitSolvedStatus(cubit,numLayers);
165
    return status<0 ? null : buildSolvedQuats(Movement4.FACE_AXIS[status],mQuats);
166
    }
167

    
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169

    
170
  private void addTetrahedralLattice(int size, int index, float[][] pos)
171
    {
172
    final float DX = 1.0f;
173
    final float DY = SQ2/2;
174
    final float DZ = 1.0f;
175

    
176
    float startX = 0.0f;
177
    float startY =-DY*(size-1)/2;
178
    float startZ = DZ*(size-1)/2;
179

    
180
    for(int layer=0; layer<size; layer++)
181
      {
182
      float currX = startX;
183
      float currY = startY;
184

    
185
      for(int x=0; x<layer+1; x++)
186
        {
187
        float currZ = startZ;
188

    
189
        for(int z=0; z<size-layer; z++)
190
          {
191
          pos[index] = new float[] {currX,currY,currZ};
192
          index++;
193
          currZ -= DZ;
194
          }
195

    
196
        currX += DX;
197
        }
198

    
199
      startX-=DX/2;
200
      startY+=DY;
201
      startZ-=DZ/2;
202
      }
203
    }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206
// there are (n^3-n)/6 octahedrons and ((n+1)^3 - (n+1))/6 tetrahedrons
207

    
208
  protected float[][] getCubitPositions(int[] numLayers)
209
    {
210
    int numL = numLayers[0];
211
    int numOcta = (numL-1)*numL*(numL+1)/6;
212
    int numTetra= numL*(numL+1)*(numL+2)/6;
213
    float[][] ret = new float[numOcta+numTetra][];
214

    
215
    addTetrahedralLattice(numL-1,      0,ret);
216
    addTetrahedralLattice(numL  ,numOcta,ret);
217

    
218
    return ret;
219
    }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

    
223
  protected Static4D[] getQuats()
224
    {
225
    if( mQuats==null ) initializeQuats();
226
    return mQuats;
227
    }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230

    
231
  protected int getSolvedFunctionIndex()
232
    {
233
    return 0;
234
    }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237

    
238
  protected int getNumStickerTypes(int[] numLayers)
239
    {
240
    return 1;
241
    }
242

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244

    
245
  protected float[][] getCuts(int[] numLayers)
246
    {
247
    if( mCuts==null )
248
      {
249
      int numL = numLayers[0];
250
      mCuts = new float[4][numL-1];
251

    
252
      for(int i=0; i<numL-1; i++)
253
        {
254
        float cut = (1.0f+i-numL/4.0f)*(SQ6/3);
255
        mCuts[0][i] = cut;
256
        mCuts[1][i] = cut;
257
        mCuts[2][i] = cut;
258
        mCuts[3][i] = cut;
259
        }
260
      }
261

    
262
    return mCuts;
263
    }
264

    
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266

    
267
  private void getLayerRotatable(int[] numLayers)
268
    {
269
    if( mLayerRotatable==null )
270
      {
271
      int numAxis = ROT_AXIS.length;
272
      mLayerRotatable = new boolean[numAxis][];
273

    
274
      for(int i=0; i<numAxis; i++)
275
        {
276
        mLayerRotatable[i] = new boolean[numLayers[i]];
277
        for(int j=0; j<numLayers[i]; j++) mLayerRotatable[i][j] = true;
278
        }
279
      }
280
    }
281

    
282
///////////////////////////////////////////////////////////////////////////////////////////////////
283

    
284
  protected int getNumCubitFaces()
285
    {
286
    return 8;
287
    }
288

    
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290

    
291
  private int getNumOctahedrons(int numLayers)
292
    {
293
    return (numLayers-1)*numLayers*(numLayers+1)/6;
294
    }
295

    
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297

    
298
  private int faceColor(int cubit, int axis)
299
    {
300
    return CUBITS[cubit].getRotRow(axis) == 1 ? axis : NUM_TEXTURES;
301
    }
302

    
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304

    
305
  protected int getFaceColor(int cubit, int cubitface, int[] numLayers)
306
    {
307
    int numL = numLayers[0];
308

    
309
    if( cubit< (numL-1)*numL*(numL+1)/6 )
310
      {
311
      switch( cubitface )
312
        {
313
        case 0: return faceColor(cubit,0);
314
        case 2: return faceColor(cubit,1);
315
        case 5: return faceColor(cubit,3);
316
        case 7: return faceColor(cubit,2);
317
        default:return NUM_TEXTURES;
318
        }
319
      }
320
    else
321
      {
322
      return cubitface<NUM_TEXTURES ? faceColor(cubit,cubitface) : NUM_TEXTURES;
323
      }
324
    }
325

    
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327

    
328
  protected ObjectShape getObjectShape(int cubit, int[] numLayers)
329
    {
330
    int numL = numLayers[0];
331
    int variant = getCubitVariant(cubit,numLayers);
332

    
333
    if( variant==0 )
334
      {
335
      double[][] vertices = new double[][] { { 0.5,0.0,0.5},{ 0.5,0.0,-0.5},{-0.5,0.0,-0.5},{-0.5,0.0,0.5},{ 0.0,SQ2/2,0.0},{ 0.0,-SQ2/2,0.0} };
336
      int[][] vert_indices = new int[][] { {3,0,4},{0,1,4},{1,2,4},{2,3,4},{5,0,3},{5,1,0},{5,2,1},{5,3,2} };
337
      int N = numL==3? 6 : 5;
338
      int E = numL==3? 2 : 1;
339
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
340
      int[] bandIndices   = new int[] { 0,0,0,0,0,0,0,0 };
341
      float[][] corners   = new float[][] { {0.04f,0.20f} };
342
      int[] cornerIndices = new int[] { 0,0,0,0,0,0 };
343
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
344
      int[] centerIndices = new int[] { 0,0,0,0,0,0 };
345
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
346
      }
347
    else
348
      {
349
      double[][] vertices = new double[][] { {-0.5, SQ2/4, 0.0},{ 0.5, SQ2/4, 0.0},{ 0.0,-SQ2/4, 0.5},{ 0.0,-SQ2/4,-0.5} };
350
      int[][] vert_indices = new int[][] { {2,1,0},{3,0,1},{3,2,0},{2,3,1} };
351
      int N = numL==3? 6 : 5;
352
      int E = numL==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 };
355
      float[][] corners   = new float[][] { {0.06f,0.15f} };
356
      int[] cornerIndices = new int[] { 0,0,0,0 };
357
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
358
      int[] centerIndices = new int[] { 0,0,0,0 };
359
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
360
      }
361
    }
362

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

    
365
  protected Static4D getQuat(int cubit, int[] numLayers)
366
    {
367
    if( mQuats==null ) initializeQuats();
368
    return mQuats[0];
369
    }
370

    
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

    
373
  protected int getNumCubitVariants(int[] numLayers)
374
    {
375
    return 2;
376
    }
377

    
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

    
380
  protected int getCubitVariant(int cubit, int[] numLayers)
381
    {
382
    return cubit<getNumOctahedrons(numLayers[0]) ? 0:1;
383
    }
384

    
385
///////////////////////////////////////////////////////////////////////////////////////////////////
386

    
387
  protected ObjectSticker retSticker(int face)
388
    {
389
    if( mStickers==null )
390
      {
391
      float[][] STICKERS = new float[][] { { -0.4330127f, -0.25f, 0.4330127f, -0.25f, 0.0f, 0.5f } };
392
      final float radius = 0.06f;
393
      final float[] radii= {radius,radius,radius};
394
      mStickers = new ObjectSticker[STICKERS.length];
395

    
396
      float stroke = 0.08f;
397

    
398
      if( ObjectControl.isInIconMode() )
399
        {
400
        int[] numLayers = getNumLayers();
401

    
402
        switch(numLayers[0])
403
          {
404
          case 2: stroke*=1.0f; break;
405
          case 3: stroke*=1.4f; break;
406
          case 4: stroke*=1.7f; break;
407
          default:stroke*=1.9f; break;
408
          }
409
        }
410

    
411
      mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke);
412
      }
413

    
414
    return mStickers[face/NUM_FACE_COLORS];
415
    }
416

    
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418
// public API
419

    
420
  public Static3D[] getRotationAxis()
421
    {
422
    return ROT_AXIS;
423
    }
424

    
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426

    
427
  public Movement getMovement()
428
    {
429
    if( mMovement==null )
430
      {
431
      int[] numLayers = getNumLayers();
432
      if( mCuts==null ) getCuts(numLayers);
433
      getLayerRotatable(numLayers);
434
      mMovement = new Movement4(ROT_AXIS,mCuts,mLayerRotatable,numLayers[0],TYPE_NOT_SPLIT,ENABLED);
435
      }
436
    return mMovement;
437
    }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440

    
441
  public int[] getBasicAngle()
442
    {
443
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
444
    return mBasicAngle;
445
    }
446

    
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448

    
449
  public ObjectType intGetObjectType(int[] numLayers)
450
    {
451
    switch(numLayers[0])
452
      {
453
      case 3: return ObjectType.PYRA_3;
454
      case 4: return ObjectType.PYRA_4;
455
      case 5: return ObjectType.PYRA_5;
456
      }
457

    
458
    return ObjectType.PYRA_3;
459
    }
460

    
461
///////////////////////////////////////////////////////////////////////////////////////////////////
462

    
463
  public int getObjectName(int[] numLayers)
464
    {
465
    switch(numLayers[0])
466
      {
467
      case 3: return R.string.pyra3;
468
      case 4: return R.string.pyra4;
469
      case 5: return R.string.pyra5;
470
      }
471
    return R.string.pyra3;
472
    }
473

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

    
476
  public int getInventor(int[] numLayers)
477
    {
478
    switch(numLayers[0])
479
      {
480
      case 3: return R.string.pyra3_inventor;
481
      case 4: return R.string.pyra4_inventor;
482
      case 5: return R.string.pyra5_inventor;
483
      }
484
    return R.string.pyra3_inventor;
485
    }
486

    
487
///////////////////////////////////////////////////////////////////////////////////////////////////
488

    
489
  public int getComplexity(int[] numLayers)
490
    {
491
    switch(numLayers[0])
492
      {
493
      case 3: return 4;
494
      case 4: return 6;
495
      case 5: return 8;
496
      }
497
    return 4;
498
    }
499
}
(18-18/25)