Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyPyraminx.java @ 4946b635

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
///////////////////////////////////////////////////////////////////////////////////////////////////
35

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

    
46
  private ScrambleState[] mStates;
47
  private int[] mBasicAngle;
48
  private Static4D[] mQuats;
49
  private float[][] mCuts;
50
  private boolean[][] mLayerRotatable;
51
  private ObjectSticker[] mStickers;
52
  private Movement mMovement;
53

    
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55

    
56
  TwistyPyraminx(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
57
                 DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
58
    {
59
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.PYRA, res, scrWidth);
60
    }
61

    
62
///////////////////////////////////////////////////////////////////////////////////////////////////
63

    
64
  ScrambleState[] getScrambleStates()
65
    {
66
    if( mStates==null )
67
      {
68
      int numLayers = getNumLayers();
69
      initializeScrambleStates(numLayers);
70
      }
71

    
72
    return mStates;
73
    }
74

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

    
77
  private void initializeQuats()
78
    {
79
    mQuats = new Static4D[]
80
         {
81
         new Static4D(  0.0f,   0.0f,   0.0f,  1.0f),
82
         new Static4D(  0.0f,   1.0f,   0.0f,  0.0f),
83
         new Static4D( SQ2/2,   0.5f,   0.0f,  0.5f),
84
         new Static4D(-SQ2/2,   0.5f,   0.0f,  0.5f),
85
         new Static4D(  0.0f,  -0.5f, -SQ2/2,  0.5f),
86
         new Static4D(  0.0f,  -0.5f,  SQ2/2,  0.5f),
87
         new Static4D( SQ2/2,   0.5f,   0.0f, -0.5f),
88
         new Static4D(-SQ2/2,   0.5f,   0.0f, -0.5f),
89
         new Static4D(  0.0f,  -0.5f, -SQ2/2, -0.5f),
90
         new Static4D(  0.0f,  -0.5f,  SQ2/2, -0.5f),
91
         new Static4D( SQ2/2,   0.0f,  SQ2/2,  0.0f),
92
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,  0.0f)
93
         };
94
    }
95

    
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97

    
98
  private int[][] generateState(int start, int end)
99
    {
100
    int len = end-start+1;
101
    int[] tmp = new int[6*len];
102

    
103
    for(int i=0; i<len; i++)
104
      {
105
      tmp[6*i  ] = start;
106
      tmp[6*i+1] = -1;
107
      tmp[6*i+2] = start;
108
      tmp[6*i+3] = start;
109
      tmp[6*i+4] = +1;
110
      tmp[6*i+5] = start;
111

    
112
      start++;
113
      }
114

    
115
    return new int[][] {tmp,tmp,tmp,tmp};
116
    }
117

    
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119

    
120
  private void initializeScrambleStates(int numLayers)
121
    {
122
    mStates = new ScrambleState[numLayers];
123

    
124
    for(int i=0; i<numLayers-1; i++)
125
      {
126
      mStates[i] = new ScrambleState( generateState(0,numLayers-1-i) );
127
      }
128

    
129
    mStates[numLayers-1] = new ScrambleState( generateState(1,numLayers-2) );
130
    }
131

    
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133

    
134
  int[] getSolvedQuats(int cubit, int numLayers)
135
    {
136
    if( mQuats==null ) initializeQuats();
137
    int status = retCubitSolvedStatus(cubit,numLayers);
138
    return status<0 ? null : buildSolvedQuats(MovementPyraminx.FACE_AXIS[status],mQuats);
139
    }
140

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

    
143
  private void addTetrahedralLattice(int size, int index, float[][] pos)
144
    {
145
    final float DX = 1.0f;
146
    final float DY = SQ2/2;
147
    final float DZ = 1.0f;
148

    
149
    float startX = 0.0f;
150
    float startY =-DY*(size-1)/2;
151
    float startZ = DZ*(size-1)/2;
152

    
153
    for(int layer=0; layer<size; layer++)
154
      {
155
      float currX = startX;
156
      float currY = startY;
157

    
158
      for(int x=0; x<layer+1; x++)
159
        {
160
        float currZ = startZ;
161

    
162
        for(int z=0; z<size-layer; z++)
163
          {
164
          pos[index] = new float[] {currX,currY,currZ};
165
          index++;
166
          currZ -= DZ;
167
          }
168

    
169
        currX += DX;
170
        }
171

    
172
      startX-=DX/2;
173
      startY+=DY;
174
      startZ-=DZ/2;
175
      }
176
    }
177

    
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179
// there are (n^3-n)/6 octahedrons and ((n+1)^3 - (n+1))/6 tetrahedrons
180

    
181
  float[][] getCubitPositions(int size)
182
    {
183
    int numOcta = (size-1)*size*(size+1)/6;
184
    int numTetra= size*(size+1)*(size+2)/6;
185
    float[][] ret = new float[numOcta+numTetra][];
186

    
187
    addTetrahedralLattice(size-1,      0,ret);
188
    addTetrahedralLattice(size  ,numOcta,ret);
189

    
190
    return ret;
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
  Static4D[] getQuats()
196
    {
197
    if( mQuats==null ) initializeQuats();
198
    return mQuats;
199
    }
200

    
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202

    
203
  int getSolvedFunctionIndex()
204
    {
205
    return 0;
206
    }
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

    
210
  int getNumStickerTypes(int numLayers)
211
    {
212
    return 1;
213
    }
214

    
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216

    
217
  float[][] getCuts(int numLayers)
218
    {
219
    if( mCuts==null )
220
      {
221
      mCuts = new float[4][numLayers-1];
222

    
223
      for(int i=0; i<numLayers-1; i++)
224
        {
225
        float cut = (1.0f+i-numLayers/4.0f)*(SQ6/3);
226
        mCuts[0][i] = cut;
227
        mCuts[1][i] = cut;
228
        mCuts[2][i] = cut;
229
        mCuts[3][i] = cut;
230
        }
231
      }
232

    
233
    return mCuts;
234
    }
235

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

    
238
  private void getLayerRotatable(int numLayers)
239
    {
240
    if( mLayerRotatable==null )
241
      {
242
      int numAxis = ROT_AXIS.length;
243
      boolean[] tmp = new boolean[numLayers];
244
      for(int i=0; i<numLayers; i++) tmp[i] = true;
245
      mLayerRotatable = new boolean[numAxis][];
246
      for(int i=0; i<numAxis; i++) mLayerRotatable[i] = tmp;
247
      }
248
    }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
  int getNumCubitFaces()
253
    {
254
    return 8;
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

    
259
  private int getNumOctahedrons(int numLayers)
260
    {
261
    return (numLayers-1)*numLayers*(numLayers+1)/6;
262
    }
263

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

    
266
  private int faceColor(int cubit, int axis)
267
    {
268
    return CUBITS[cubit].mRotationRow[axis] == 1 ? axis : NUM_TEXTURES;
269
    }
270

    
271
///////////////////////////////////////////////////////////////////////////////////////////////////
272

    
273
  int getFaceColor(int cubit, int cubitface, int size)
274
    {
275
    if( cubit< (size-1)*size*(size+1)/6 )
276
      {
277
      switch( cubitface )
278
        {
279
        case 0: return faceColor(cubit,0);
280
        case 2: return faceColor(cubit,1);
281
        case 5: return faceColor(cubit,3);
282
        case 7: return faceColor(cubit,2);
283
        default:return NUM_TEXTURES;
284
        }
285
      }
286
    else
287
      {
288
      return cubitface<NUM_TEXTURES ? faceColor(cubit,cubitface) : NUM_TEXTURES;
289
      }
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

    
294
  ObjectShape getObjectShape(int cubit, int numLayers)
295
    {
296
    int variant = getCubitVariant(cubit,numLayers);
297

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

    
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329

    
330
  Static4D getQuat(int cubit, int numLayers)
331
    {
332
    if( mQuats==null ) initializeQuats();
333
    return mQuats[0];
334
    }
335

    
336
///////////////////////////////////////////////////////////////////////////////////////////////////
337

    
338
  int getNumCubitVariants(int numLayers)
339
    {
340
    return 2;
341
    }
342

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

    
345
  int getCubitVariant(int cubit, int numLayers)
346
    {
347
    return cubit<getNumOctahedrons(numLayers) ? 0:1;
348
    }
349

    
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351

    
352
  ObjectSticker retSticker(int face)
353
    {
354
    if( mStickers==null )
355
      {
356
      float[][] STICKERS = new float[][] { { -0.4330127f, -0.25f, 0.4330127f, -0.25f, 0.0f, 0.5f } };
357
      final float stroke = 0.08f;
358
      final float radius = 0.06f;
359
      final float[] radii= {radius,radius,radius};
360
      mStickers = new ObjectSticker[STICKERS.length];
361
      mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke);
362
      }
363

    
364
    return mStickers[face/NUM_FACE_COLORS];
365
    }
366

    
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368
// public API
369

    
370
  public Static3D[] getRotationAxis()
371
    {
372
    return ROT_AXIS;
373
    }
374

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

    
377
  public Movement getMovement()
378
    {
379
    if( mMovement==null )
380
      {
381
      int numLayers = getNumLayers();
382
      if( mCuts==null ) getCuts(numLayers);
383
      getLayerRotatable(numLayers);
384

    
385
      mMovement = new MovementPyraminx(mCuts,mLayerRotatable,numLayers);
386
      }
387
    return mMovement;
388
    }
389

    
390
///////////////////////////////////////////////////////////////////////////////////////////////////
391

    
392
  public int[] getBasicAngle()
393
    {
394
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
395
    return mBasicAngle;
396
    }
397

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

    
400
  public int getObjectName(int numLayers)
401
    {
402
    switch(numLayers)
403
      {
404
      case 3: return R.string.pyra3;
405
      case 4: return R.string.pyra4;
406
      case 5: return R.string.pyra5;
407
      }
408
    return R.string.pyra3;
409
    }
410

    
411
///////////////////////////////////////////////////////////////////////////////////////////////////
412

    
413
  public int getInventor(int numLayers)
414
    {
415
    switch(numLayers)
416
      {
417
      case 3: return R.string.pyra3_inventor;
418
      case 4: return R.string.pyra4_inventor;
419
      case 5: return R.string.pyra5_inventor;
420
      }
421
    return R.string.pyra3_inventor;
422
    }
423

    
424
///////////////////////////////////////////////////////////////////////////////////////////////////
425

    
426
  public int getComplexity(int numLayers)
427
    {
428
    switch(numLayers)
429
      {
430
      case 3: return 4;
431
      case 4: return 6;
432
      case 5: return 8;
433
      }
434
    return 4;
435
    }
436
}
(41-41/48)