Project

General

Profile

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

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

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.ObjectList;
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, ObjectList.PYRA, 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
  private void initializeQuats()
90
    {
91
    mQuats = new Static4D[]
92
         {
93
         new Static4D(  0.0f,   0.0f,   0.0f,  1.0f),
94
         new Static4D(  0.0f,   1.0f,   0.0f,  0.0f),
95
         new Static4D( SQ2/2,   0.5f,   0.0f,  0.5f),
96
         new Static4D(-SQ2/2,   0.5f,   0.0f,  0.5f),
97
         new Static4D(  0.0f,  -0.5f, -SQ2/2,  0.5f),
98
         new Static4D(  0.0f,  -0.5f,  SQ2/2,  0.5f),
99
         new Static4D( SQ2/2,   0.5f,   0.0f, -0.5f),
100
         new Static4D(-SQ2/2,   0.5f,   0.0f, -0.5f),
101
         new Static4D(  0.0f,  -0.5f, -SQ2/2, -0.5f),
102
         new Static4D(  0.0f,  -0.5f,  SQ2/2, -0.5f),
103
         new Static4D( SQ2/2,   0.0f,  SQ2/2,  0.0f),
104
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,  0.0f)
105
         };
106
    }
107

    
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109

    
110
  private int[][] generateState(int start, int end)
111
    {
112
    int len = end-start+1;
113
    int[] tmp = new int[6*len];
114

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

    
124
      start++;
125
      }
126

    
127
    return new int[][] {tmp,tmp,tmp,tmp};
128
    }
129

    
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131

    
132
  private void initializeScrambleStates(int numLayers)
133
    {
134
    mStates = new ScrambleState[numLayers];
135

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

    
141
    mStates[numLayers-1] = new ScrambleState( generateState(1,numLayers-2) );
142
    }
143

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

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

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

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

    
161
    float startX = 0.0f;
162
    float startY =-DY*(size-1)/2;
163
    float startZ = DZ*(size-1)/2;
164

    
165
    for(int layer=0; layer<size; layer++)
166
      {
167
      float currX = startX;
168
      float currY = startY;
169

    
170
      for(int x=0; x<layer+1; x++)
171
        {
172
        float currZ = startZ;
173

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

    
181
        currX += DX;
182
        }
183

    
184
      startX-=DX/2;
185
      startY+=DY;
186
      startZ-=DZ/2;
187
      }
188
    }
189

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191
// there are (n^3-n)/6 octahedrons and ((n+1)^3 - (n+1))/6 tetrahedrons
192

    
193
  protected float[][] getCubitPositions(int size)
194
    {
195
    int numOcta = (size-1)*size*(size+1)/6;
196
    int numTetra= size*(size+1)*(size+2)/6;
197
    float[][] ret = new float[numOcta+numTetra][];
198

    
199
    addTetrahedralLattice(size-1,      0,ret);
200
    addTetrahedralLattice(size  ,numOcta,ret);
201

    
202
    return ret;
203
    }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

    
207
  protected Static4D[] getQuats()
208
    {
209
    if( mQuats==null ) initializeQuats();
210
    return mQuats;
211
    }
212

    
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214

    
215
  protected int getSolvedFunctionIndex()
216
    {
217
    return 0;
218
    }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221

    
222
  protected int getNumStickerTypes(int numLayers)
223
    {
224
    return 1;
225
    }
226

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

    
229
  protected float[][] getCuts(int numLayers)
230
    {
231
    if( mCuts==null )
232
      {
233
      mCuts = new float[4][numLayers-1];
234

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

    
245
    return mCuts;
246
    }
247

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

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

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

    
264
  protected int getNumCubitFaces()
265
    {
266
    return 8;
267
    }
268

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

    
271
  private int getNumOctahedrons(int numLayers)
272
    {
273
    return (numLayers-1)*numLayers*(numLayers+1)/6;
274
    }
275

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

    
278
  private int faceColor(int cubit, int axis)
279
    {
280
    return CUBITS[cubit].getRotRow(axis) == 1 ? axis : NUM_TEXTURES;
281
    }
282

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

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

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

    
306
  protected ObjectShape getObjectShape(int cubit, int numLayers)
307
    {
308
    int variant = getCubitVariant(cubit,numLayers);
309

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

    
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341

    
342
  protected Static4D getQuat(int cubit, int numLayers)
343
    {
344
    if( mQuats==null ) initializeQuats();
345
    return mQuats[0];
346
    }
347

    
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

    
350
  protected int getNumCubitVariants(int numLayers)
351
    {
352
    return 2;
353
    }
354

    
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356

    
357
  protected int getCubitVariant(int cubit, int numLayers)
358
    {
359
    return cubit<getNumOctahedrons(numLayers) ? 0:1;
360
    }
361

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

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

    
376
    return mStickers[face/NUM_FACE_COLORS];
377
    }
378

    
379
///////////////////////////////////////////////////////////////////////////////////////////////////
380
// public API
381

    
382
  public Static3D[] getRotationAxis()
383
    {
384
    return ROT_AXIS;
385
    }
386

    
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388

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

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

    
403
  public int[] getBasicAngle()
404
    {
405
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
406
    return mBasicAngle;
407
    }
408

    
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410

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

    
422
///////////////////////////////////////////////////////////////////////////////////////////////////
423

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

    
435
///////////////////////////////////////////////////////////////////////////////////////////////////
436

    
437
  public int getComplexity(int numLayers)
438
    {
439
    switch(numLayers)
440
      {
441
      case 3: return 4;
442
      case 4: return 6;
443
      case 5: return 8;
444
      }
445
    return 4;
446
    }
447
}
(18-18/25)