Project

General

Profile

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

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

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.ObjectType;
36
import org.distorted.objectlib.main.ObjectShape;
37
import org.distorted.objectlib.main.ObjectSticker;
38
import org.distorted.objectlib.main.ScrambleState;
39
import org.distorted.objectlib.main.Twisty4;
40

    
41
///////////////////////////////////////////////////////////////////////////////////////////////////
42

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

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

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

    
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67

    
68
  public TwistyPyraminx(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
69
                        DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
70
    {
71
    super(size, size, quat, texture, mesh, effects, moves, res, scrWidth);
72
    }
73

    
74
///////////////////////////////////////////////////////////////////////////////////////////////////
75

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

    
84
    return mStates;
85
    }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

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

    
98
    return 0;
99
    }
100

    
101
///////////////////////////////////////////////////////////////////////////////////////////////////
102

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

    
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

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

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

    
138
      start++;
139
      }
140

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

    
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145

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

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

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

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159

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

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

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

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

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

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

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

    
195
        currX += DX;
196
        }
197

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

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

    
207
  protected float[][] getCubitPositions(int size)
208
    {
209
    int numOcta = (size-1)*size*(size+1)/6;
210
    int numTetra= size*(size+1)*(size+2)/6;
211
    float[][] ret = new float[numOcta+numTetra][];
212

    
213
    addTetrahedralLattice(size-1,      0,ret);
214
    addTetrahedralLattice(size  ,numOcta,ret);
215

    
216
    return ret;
217
    }
218

    
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220

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

    
227
///////////////////////////////////////////////////////////////////////////////////////////////////
228

    
229
  protected int getSolvedFunctionIndex()
230
    {
231
    return 0;
232
    }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235

    
236
  protected int getNumStickerTypes(int numLayers)
237
    {
238
    return 1;
239
    }
240

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

    
243
  protected float[][] getCuts(int numLayers)
244
    {
245
    if( mCuts==null )
246
      {
247
      mCuts = new float[4][numLayers-1];
248

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

    
259
    return mCuts;
260
    }
261

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

    
264
  private void getLayerRotatable(int numLayers)
265
    {
266
    if( mLayerRotatable==null )
267
      {
268
      int numAxis = ROT_AXIS.length;
269
      boolean[] tmp = new boolean[numLayers];
270
      for(int i=0; i<numLayers; i++) tmp[i] = true;
271
      mLayerRotatable = new boolean[numAxis][];
272
      for(int i=0; i<numAxis; i++) mLayerRotatable[i] = tmp;
273
      }
274
    }
275

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

    
278
  protected int getNumCubitFaces()
279
    {
280
    return 8;
281
    }
282

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

    
285
  private int getNumOctahedrons(int numLayers)
286
    {
287
    return (numLayers-1)*numLayers*(numLayers+1)/6;
288
    }
289

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

    
292
  private int faceColor(int cubit, int axis)
293
    {
294
    return CUBITS[cubit].getRotRow(axis) == 1 ? axis : NUM_TEXTURES;
295
    }
296

    
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298

    
299
  protected int getFaceColor(int cubit, int cubitface, int size)
300
    {
301
    if( cubit< (size-1)*size*(size+1)/6 )
302
      {
303
      switch( cubitface )
304
        {
305
        case 0: return faceColor(cubit,0);
306
        case 2: return faceColor(cubit,1);
307
        case 5: return faceColor(cubit,3);
308
        case 7: return faceColor(cubit,2);
309
        default:return NUM_TEXTURES;
310
        }
311
      }
312
    else
313
      {
314
      return cubitface<NUM_TEXTURES ? faceColor(cubit,cubitface) : NUM_TEXTURES;
315
      }
316
    }
317

    
318
///////////////////////////////////////////////////////////////////////////////////////////////////
319

    
320
  protected ObjectShape getObjectShape(int cubit, int numLayers)
321
    {
322
    int variant = getCubitVariant(cubit,numLayers);
323

    
324
    if( variant==0 )
325
      {
326
      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} };
327
      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} };
328
      int N = numLayers==3? 6 : 5;
329
      int E = numLayers==3? 2 : 1;
330
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
331
      int[] bandIndices   = new int[] { 0,0,0,0,0,0,0,0 };
332
      float[][] corners   = new float[][] { {0.04f,0.20f} };
333
      int[] cornerIndices = new int[] { 0,0,0,0,0,0 };
334
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
335
      int[] centerIndices = new int[] { 0,0,0,0,0,0 };
336
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
337
      }
338
    else
339
      {
340
      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} };
341
      int[][] vert_indices = new int[][] { {2,1,0},{3,0,1},{3,2,0},{2,3,1} };
342
      int N = numLayers==3? 6 : 5;
343
      int E = numLayers==3? 2 : 1;
344
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
345
      int[] bandIndices   = new int[] { 0,0,0,0 };
346
      float[][] corners   = new float[][] { {0.06f,0.15f} };
347
      int[] cornerIndices = new int[] { 0,0,0,0 };
348
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
349
      int[] centerIndices = new int[] { 0,0,0,0 };
350
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
351
      }
352
    }
353

    
354
///////////////////////////////////////////////////////////////////////////////////////////////////
355

    
356
  protected Static4D getQuat(int cubit, int numLayers)
357
    {
358
    if( mQuats==null ) initializeQuats();
359
    return mQuats[0];
360
    }
361

    
362
///////////////////////////////////////////////////////////////////////////////////////////////////
363

    
364
  protected int getNumCubitVariants(int numLayers)
365
    {
366
    return 2;
367
    }
368

    
369
///////////////////////////////////////////////////////////////////////////////////////////////////
370

    
371
  protected int getCubitVariant(int cubit, int numLayers)
372
    {
373
    return cubit<getNumOctahedrons(numLayers) ? 0:1;
374
    }
375

    
376
///////////////////////////////////////////////////////////////////////////////////////////////////
377

    
378
  protected ObjectSticker retSticker(int face)
379
    {
380
    if( mStickers==null )
381
      {
382
      float[][] STICKERS = new float[][] { { -0.4330127f, -0.25f, 0.4330127f, -0.25f, 0.0f, 0.5f } };
383
      final float stroke = 0.08f;
384
      final float radius = 0.06f;
385
      final float[] radii= {radius,radius,radius};
386
      mStickers = new ObjectSticker[STICKERS.length];
387
      mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke);
388
      }
389

    
390
    return mStickers[face/NUM_FACE_COLORS];
391
    }
392

    
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394
// public API
395

    
396
  public Static3D[] getRotationAxis()
397
    {
398
    return ROT_AXIS;
399
    }
400

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

    
403
  public Movement getMovement()
404
    {
405
    if( mMovement==null )
406
      {
407
      int numLayers = getNumLayers();
408
      if( mCuts==null ) getCuts(numLayers);
409
      getLayerRotatable(numLayers);
410
      mMovement = new Movement4(ROT_AXIS,mCuts,mLayerRotatable,numLayers,TYPE_NOT_SPLIT,ENABLED);
411
      }
412
    return mMovement;
413
    }
414

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416

    
417
  public int[] getBasicAngle()
418
    {
419
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
420
    return mBasicAngle;
421
    }
422

    
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424

    
425
  public ObjectType intGetObjectList(int numLayers)
426
    {
427
    switch(numLayers)
428
      {
429
      case 3: return ObjectType.PYRA_3;
430
      case 4: return ObjectType.PYRA_4;
431
      case 5: return ObjectType.PYRA_5;
432
      }
433

    
434
    return ObjectType.PYRA_3;
435
    }
436

    
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438

    
439
  public int getObjectName(int numLayers)
440
    {
441
    switch(numLayers)
442
      {
443
      case 3: return R.string.pyra3;
444
      case 4: return R.string.pyra4;
445
      case 5: return R.string.pyra5;
446
      }
447
    return R.string.pyra3;
448
    }
449

    
450
///////////////////////////////////////////////////////////////////////////////////////////////////
451

    
452
  public int getInventor(int numLayers)
453
    {
454
    switch(numLayers)
455
      {
456
      case 3: return R.string.pyra3_inventor;
457
      case 4: return R.string.pyra4_inventor;
458
      case 5: return R.string.pyra5_inventor;
459
      }
460
    return R.string.pyra3_inventor;
461
    }
462

    
463
///////////////////////////////////////////////////////////////////////////////////////////////////
464

    
465
  public int getComplexity(int numLayers)
466
    {
467
    switch(numLayers)
468
      {
469
      case 3: return 4;
470
      case 4: return 6;
471
      case 5: return 8;
472
      }
473
    return 4;
474
    }
475
}
(18-18/25)