Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyPyraminx.java @ 967c1d17

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 static org.distorted.objects.Movement.TYPE_NOT_SPLIT;
23

    
24
import android.content.res.Resources;
25

    
26
import org.distorted.helpers.ObjectShape;
27
import org.distorted.helpers.ObjectSticker;
28
import org.distorted.helpers.ScrambleState;
29
import org.distorted.library.main.DistortedEffects;
30
import org.distorted.library.main.DistortedTexture;
31
import org.distorted.library.mesh.MeshSquare;
32
import org.distorted.library.type.Static3D;
33
import org.distorted.library.type.Static4D;
34
import org.distorted.main.R;
35

    
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37

    
38
public class TwistyPyraminx extends Twisty4
39
{
40
  static final Static3D[] ROT_AXIS = new Static3D[]
41
         {
42
           new Static3D(     0,-SQ3/3,-SQ6/3),
43
           new Static3D(     0,-SQ3/3,+SQ6/3),
44
           new Static3D(+SQ6/3,+SQ3/3,     0),
45
           new Static3D(-SQ6/3,+SQ3/3,     0),
46
         };
47

    
48
  private static final int[] NUM_ENABLED = {3,3,3,3};
49

    
50
  private static final int[][][] ENABLED = new int[][][]
51
      {
52
          {{1,2,3}},{{0,2,3}},{{0,1,3}},{{0,1,2}}
53
      };
54

    
55
  private ScrambleState[] mStates;
56
  private int[] mBasicAngle;
57
  private Static4D[] mQuats;
58
  private float[][] mCuts;
59
  private boolean[][] mLayerRotatable;
60
  private ObjectSticker[] mStickers;
61
  private Movement mMovement;
62

    
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64

    
65
  TwistyPyraminx(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
66
                 DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
67
    {
68
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.PYRA, res, scrWidth);
69
    }
70

    
71
///////////////////////////////////////////////////////////////////////////////////////////////////
72

    
73
  ScrambleState[] getScrambleStates()
74
    {
75
    if( mStates==null )
76
      {
77
      int numLayers = getNumLayers();
78
      initializeScrambleStates(numLayers);
79
      }
80

    
81
    return mStates;
82
    }
83

    
84
///////////////////////////////////////////////////////////////////////////////////////////////////
85

    
86
  private void initializeQuats()
87
    {
88
    mQuats = new Static4D[]
89
         {
90
         new Static4D(  0.0f,   0.0f,   0.0f,  1.0f),
91
         new Static4D(  0.0f,   1.0f,   0.0f,  0.0f),
92
         new Static4D( SQ2/2,   0.5f,   0.0f,  0.5f),
93
         new Static4D(-SQ2/2,   0.5f,   0.0f,  0.5f),
94
         new Static4D(  0.0f,  -0.5f, -SQ2/2,  0.5f),
95
         new Static4D(  0.0f,  -0.5f,  SQ2/2,  0.5f),
96
         new Static4D( SQ2/2,   0.5f,   0.0f, -0.5f),
97
         new Static4D(-SQ2/2,   0.5f,   0.0f, -0.5f),
98
         new Static4D(  0.0f,  -0.5f, -SQ2/2, -0.5f),
99
         new Static4D(  0.0f,  -0.5f,  SQ2/2, -0.5f),
100
         new Static4D( SQ2/2,   0.0f,  SQ2/2,  0.0f),
101
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,  0.0f)
102
         };
103
    }
104

    
105
///////////////////////////////////////////////////////////////////////////////////////////////////
106

    
107
  private int[][] generateState(int start, int end)
108
    {
109
    int len = end-start+1;
110
    int[] tmp = new int[6*len];
111

    
112
    for(int i=0; i<len; i++)
113
      {
114
      tmp[6*i  ] = start;
115
      tmp[6*i+1] = -1;
116
      tmp[6*i+2] = start;
117
      tmp[6*i+3] = start;
118
      tmp[6*i+4] = +1;
119
      tmp[6*i+5] = start;
120

    
121
      start++;
122
      }
123

    
124
    return new int[][] {tmp,tmp,tmp,tmp};
125
    }
126

    
127
///////////////////////////////////////////////////////////////////////////////////////////////////
128

    
129
  private void initializeScrambleStates(int numLayers)
130
    {
131
    mStates = new ScrambleState[numLayers];
132

    
133
    for(int i=0; i<numLayers-1; i++)
134
      {
135
      mStates[i] = new ScrambleState( generateState(0,numLayers-1-i) );
136
      }
137

    
138
    mStates[numLayers-1] = new ScrambleState( generateState(1,numLayers-2) );
139
    }
140

    
141
///////////////////////////////////////////////////////////////////////////////////////////////////
142

    
143
  int[] getSolvedQuats(int cubit, int numLayers)
144
    {
145
    if( mQuats==null ) initializeQuats();
146
    int status = retCubitSolvedStatus(cubit,numLayers);
147
    return status<0 ? null : buildSolvedQuats(Movement4.FACE_AXIS[status],mQuats);
148
    }
149

    
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

    
152
  private void addTetrahedralLattice(int size, int index, float[][] pos)
153
    {
154
    final float DX = 1.0f;
155
    final float DY = SQ2/2;
156
    final float DZ = 1.0f;
157

    
158
    float startX = 0.0f;
159
    float startY =-DY*(size-1)/2;
160
    float startZ = DZ*(size-1)/2;
161

    
162
    for(int layer=0; layer<size; layer++)
163
      {
164
      float currX = startX;
165
      float currY = startY;
166

    
167
      for(int x=0; x<layer+1; x++)
168
        {
169
        float currZ = startZ;
170

    
171
        for(int z=0; z<size-layer; z++)
172
          {
173
          pos[index] = new float[] {currX,currY,currZ};
174
          index++;
175
          currZ -= DZ;
176
          }
177

    
178
        currX += DX;
179
        }
180

    
181
      startX-=DX/2;
182
      startY+=DY;
183
      startZ-=DZ/2;
184
      }
185
    }
186

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188
// there are (n^3-n)/6 octahedrons and ((n+1)^3 - (n+1))/6 tetrahedrons
189

    
190
  float[][] getCubitPositions(int size)
191
    {
192
    int numOcta = (size-1)*size*(size+1)/6;
193
    int numTetra= size*(size+1)*(size+2)/6;
194
    float[][] ret = new float[numOcta+numTetra][];
195

    
196
    addTetrahedralLattice(size-1,      0,ret);
197
    addTetrahedralLattice(size  ,numOcta,ret);
198

    
199
    return ret;
200
    }
201

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
  Static4D[] getQuats()
205
    {
206
    if( mQuats==null ) initializeQuats();
207
    return mQuats;
208
    }
209

    
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211

    
212
  int getSolvedFunctionIndex()
213
    {
214
    return 0;
215
    }
216

    
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218

    
219
  int getNumStickerTypes(int numLayers)
220
    {
221
    return 1;
222
    }
223

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

    
226
  float[][] getCuts(int numLayers)
227
    {
228
    if( mCuts==null )
229
      {
230
      mCuts = new float[4][numLayers-1];
231

    
232
      for(int i=0; i<numLayers-1; i++)
233
        {
234
        float cut = (1.0f+i-numLayers/4.0f)*(SQ6/3);
235
        mCuts[0][i] = cut;
236
        mCuts[1][i] = cut;
237
        mCuts[2][i] = cut;
238
        mCuts[3][i] = cut;
239
        }
240
      }
241

    
242
    return mCuts;
243
    }
244

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

    
247
  private void getLayerRotatable(int numLayers)
248
    {
249
    if( mLayerRotatable==null )
250
      {
251
      int numAxis = ROT_AXIS.length;
252
      boolean[] tmp = new boolean[numLayers];
253
      for(int i=0; i<numLayers; i++) tmp[i] = true;
254
      mLayerRotatable = new boolean[numAxis][];
255
      for(int i=0; i<numAxis; i++) mLayerRotatable[i] = tmp;
256
      }
257
    }
258

    
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260

    
261
  int getNumCubitFaces()
262
    {
263
    return 8;
264
    }
265

    
266
///////////////////////////////////////////////////////////////////////////////////////////////////
267

    
268
  private int getNumOctahedrons(int numLayers)
269
    {
270
    return (numLayers-1)*numLayers*(numLayers+1)/6;
271
    }
272

    
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274

    
275
  private int faceColor(int cubit, int axis)
276
    {
277
    return CUBITS[cubit].mRotationRow[axis] == 1 ? axis : NUM_TEXTURES;
278
    }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

    
282
  int getFaceColor(int cubit, int cubitface, int size)
283
    {
284
    if( cubit< (size-1)*size*(size+1)/6 )
285
      {
286
      switch( cubitface )
287
        {
288
        case 0: return faceColor(cubit,0);
289
        case 2: return faceColor(cubit,1);
290
        case 5: return faceColor(cubit,3);
291
        case 7: return faceColor(cubit,2);
292
        default:return NUM_TEXTURES;
293
        }
294
      }
295
    else
296
      {
297
      return cubitface<NUM_TEXTURES ? faceColor(cubit,cubitface) : NUM_TEXTURES;
298
      }
299
    }
300

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

    
303
  ObjectShape getObjectShape(int cubit, int numLayers)
304
    {
305
    int variant = getCubitVariant(cubit,numLayers);
306

    
307
    if( variant==0 )
308
      {
309
      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} };
310
      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} };
311
      int N = numLayers==3? 6 : 5;
312
      int E = numLayers==3? 2 : 1;
313
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
314
      int[] bandIndices   = new int[] { 0,0,0,0,0,0,0,0 };
315
      float[][] corners   = new float[][] { {0.04f,0.20f} };
316
      int[] cornerIndices = new int[] { 0,0,0,0,0,0 };
317
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
318
      int[] centerIndices = new int[] { 0,0,0,0,0,0 };
319
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
320
      }
321
    else
322
      {
323
      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} };
324
      int[][] vert_indices = new int[][] { {2,1,0},{3,0,1},{3,2,0},{2,3,1} };
325
      int N = numLayers==3? 6 : 5;
326
      int E = numLayers==3? 2 : 1;
327
      float[][] bands     = new float[][] { {0.05f,35,0.5f,0.8f,N,E,E} };
328
      int[] bandIndices   = new int[] { 0,0,0,0 };
329
      float[][] corners   = new float[][] { {0.06f,0.15f} };
330
      int[] cornerIndices = new int[] { 0,0,0,0 };
331
      float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
332
      int[] centerIndices = new int[] { 0,0,0,0 };
333
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
334
      }
335
    }
336

    
337
///////////////////////////////////////////////////////////////////////////////////////////////////
338

    
339
  Static4D getQuat(int cubit, int numLayers)
340
    {
341
    if( mQuats==null ) initializeQuats();
342
    return mQuats[0];
343
    }
344

    
345
///////////////////////////////////////////////////////////////////////////////////////////////////
346

    
347
  int getNumCubitVariants(int numLayers)
348
    {
349
    return 2;
350
    }
351

    
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353

    
354
  int getCubitVariant(int cubit, int numLayers)
355
    {
356
    return cubit<getNumOctahedrons(numLayers) ? 0:1;
357
    }
358

    
359
///////////////////////////////////////////////////////////////////////////////////////////////////
360

    
361
  ObjectSticker retSticker(int face)
362
    {
363
    if( mStickers==null )
364
      {
365
      float[][] STICKERS = new float[][] { { -0.4330127f, -0.25f, 0.4330127f, -0.25f, 0.0f, 0.5f } };
366
      final float stroke = 0.08f;
367
      final float radius = 0.06f;
368
      final float[] radii= {radius,radius,radius};
369
      mStickers = new ObjectSticker[STICKERS.length];
370
      mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke);
371
      }
372

    
373
    return mStickers[face/NUM_FACE_COLORS];
374
    }
375

    
376
///////////////////////////////////////////////////////////////////////////////////////////////////
377
// public API
378

    
379
  public Static3D[] getRotationAxis()
380
    {
381
    return ROT_AXIS;
382
    }
383

    
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385

    
386
  public Movement getMovement()
387
    {
388
    if( mMovement==null )
389
      {
390
      int numLayers = getNumLayers();
391
      if( mCuts==null ) getCuts(numLayers);
392
      getLayerRotatable(numLayers);
393
      mMovement = new Movement4(ROT_AXIS,mCuts,mLayerRotatable,numLayers,TYPE_NOT_SPLIT,NUM_ENABLED,ENABLED);
394
      }
395
    return mMovement;
396
    }
397

    
398
///////////////////////////////////////////////////////////////////////////////////////////////////
399

    
400
  public int[] getBasicAngle()
401
    {
402
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
403
    return mBasicAngle;
404
    }
405

    
406
///////////////////////////////////////////////////////////////////////////////////////////////////
407

    
408
  public int getObjectName(int numLayers)
409
    {
410
    switch(numLayers)
411
      {
412
      case 3: return R.string.pyra3;
413
      case 4: return R.string.pyra4;
414
      case 5: return R.string.pyra5;
415
      }
416
    return R.string.pyra3;
417
    }
418

    
419
///////////////////////////////////////////////////////////////////////////////////////////////////
420

    
421
  public int getInventor(int numLayers)
422
    {
423
    switch(numLayers)
424
      {
425
      case 3: return R.string.pyra3_inventor;
426
      case 4: return R.string.pyra4_inventor;
427
      case 5: return R.string.pyra5_inventor;
428
      }
429
    return R.string.pyra3_inventor;
430
    }
431

    
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433

    
434
  public int getComplexity(int numLayers)
435
    {
436
    switch(numLayers)
437
      {
438
      case 3: return 4;
439
      case 4: return 6;
440
      case 5: return 8;
441
      }
442
    return 4;
443
    }
444
}
(31-31/38)