Project

General

Profile

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

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

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.touchcontrol.TouchControl.TC_TETRAHEDRON;
23
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
24

    
25
import java.io.InputStream;
26

    
27
import org.distorted.library.type.Static3D;
28
import org.distorted.library.type.Static4D;
29

    
30
import org.distorted.objectlib.touchcontrol.TouchControlTetrahedron;
31
import org.distorted.objectlib.main.ObjectControl;
32
import org.distorted.objectlib.main.ObjectType;
33
import org.distorted.objectlib.helpers.ObjectShape;
34
import org.distorted.objectlib.helpers.ObjectSticker;
35
import org.distorted.objectlib.helpers.ScrambleState;
36
import org.distorted.objectlib.main.ShapeTetrahedron;
37

    
38
///////////////////////////////////////////////////////////////////////////////////////////////////
39

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

    
50
  private ScrambleState[] mStates;
51
  private int[] mBasicAngle;
52
  private Static4D[] mQuats;
53
  private float[][] mCuts;
54
  private ObjectSticker[] mStickers;
55

    
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57

    
58
  public TwistyPyraminx(int[] numL, int meshState, Static4D quat, Static3D move, float scale, InputStream stream)
59
    {
60
    super(numL, meshState, numL[0], quat, move, scale, stream);
61
    }
62

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

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

    
73
    return mStates;
74
    }
75

    
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77

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

    
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98

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

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

    
113
      start++;
114
      }
115

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

    
119
///////////////////////////////////////////////////////////////////////////////////////////////////
120

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

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

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

    
133
///////////////////////////////////////////////////////////////////////////////////////////////////
134

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

    
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143

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

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

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

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

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

    
170
        currX += DX;
171
        }
172

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

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

    
182
  public float[][] getCubitPositions(int[] numLayers)
183
    {
184
    int numL = numLayers[0];
185
    int numOcta = (numL-1)*numL*(numL+1)/6;
186
    int numTetra= numL*(numL+1)*(numL+2)/6;
187
    float[][] ret = new float[numOcta+numTetra][];
188

    
189
    addTetrahedralLattice(numL-1,      0,ret);
190
    addTetrahedralLattice(numL  ,numOcta,ret);
191

    
192
    return ret;
193
    }
194

    
195
///////////////////////////////////////////////////////////////////////////////////////////////////
196

    
197
  public Static4D[] getQuats()
198
    {
199
    if( mQuats==null ) initializeQuats();
200
    return mQuats;
201
    }
202

    
203
///////////////////////////////////////////////////////////////////////////////////////////////////
204

    
205
  public int getSolvedFunctionIndex()
206
    {
207
    return 0;
208
    }
209

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

    
212
  public float[][] getCuts(int[] numLayers)
213
    {
214
    if( mCuts==null )
215
      {
216
      int numL = numLayers[0];
217
      mCuts = new float[4][numL-1];
218

    
219
      for(int i=0; i<numL-1; i++)
220
        {
221
        float cut = (1.0f+i-numL/4.0f)*(SQ6/3);
222
        mCuts[0][i] = cut;
223
        mCuts[1][i] = cut;
224
        mCuts[2][i] = cut;
225
        mCuts[3][i] = cut;
226
        }
227
      }
228

    
229
    return mCuts;
230
    }
231

    
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233

    
234
  public boolean[][] getLayerRotatable(int[] numLayers)
235
    {
236
    int numAxis = ROT_AXIS.length;
237
    boolean[][] layerRotatable = new boolean[numAxis][];
238

    
239
    for(int i=0; i<numAxis; i++)
240
      {
241
      layerRotatable[i] = new boolean[numLayers[i]];
242
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
243
      }
244

    
245
    return layerRotatable;
246
    }
247

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

    
250
  public int getTouchControlType()
251
    {
252
    return TC_TETRAHEDRON;
253
    }
254

    
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256

    
257
  public int getTouchControlSplit()
258
    {
259
    return TYPE_NOT_SPLIT;
260
    }
261

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

    
264
  public int[][][] getEnabled()
265
    {
266
    return new int[][][] { {{1,2,3}},{{0,2,3}},{{0,1,3}},{{0,1,2}} };
267
    }
268

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

    
271
  public float[] getDist3D(int[] numLayers)
272
    {
273
    return null;
274
    }
275

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

    
278
  public 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
  public ObjectShape getObjectShape(int variant)
293
    {
294
    int numL = getNumLayers()[0];
295

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

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

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

    
334
///////////////////////////////////////////////////////////////////////////////////////////////////
335

    
336
  public int getNumCubitVariants(int[] numLayers)
337
    {
338
    return 2;
339
    }
340

    
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342

    
343
  public int getCubitVariant(int cubit, int[] numLayers)
344
    {
345
    return cubit<getNumOctahedrons(numLayers[0]) ? 0:1;
346
    }
347

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

    
350
  private int faceColor(int cubit, int face)
351
    {
352
    return CUBITS[cubit].getRotRow(face) == 1 ? face : -1;
353
    }
354

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

    
357
  public int getCubitFaceColor(int cubit, int face, int[] numLayers)
358
    {
359
    if( cubit < getNumOctahedrons(numLayers[0]) )
360
      {
361
      switch( face )
362
        {
363
        case 0: return faceColor(cubit,0);
364
        case 2: return faceColor(cubit,1);
365
        case 5: return faceColor(cubit,3);
366
        case 7: return faceColor(cubit,2);
367
        default:return -1;
368
        }
369
      }
370
    else
371
      {
372
      return face<NUM_FACE_COLORS ? faceColor(cubit,face) : -1;
373
      }
374
    }
375

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

    
378
  public int getVariantFaceColor(int variant, int face, int[] numLayers)
379
    {
380
    return face>=mStickerVariants[variant].length ? -1 : mStickerVariants[variant][face];
381
    }
382

    
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384

    
385
  private float getRadius()
386
    {
387
    return 0.06f;
388
    }
389

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

    
392
  private float getStroke()
393
    {
394
    float stroke = 0.08f;
395

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

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

    
409
    return stroke;
410
    }
411

    
412
///////////////////////////////////////////////////////////////////////////////////////////////////
413

    
414
  public ObjectSticker retSticker(int sticker)
415
    {
416
    if( mStickers==null )
417
      {
418
      float rad = getRadius();
419
      float str = getStroke();
420
      int numStickers = mStickerCoords.length;
421
      mStickers = new ObjectSticker[numStickers];
422

    
423
      for(int s=0; s<numStickers; s++)
424
        {
425
        float scale = mStickerScales[s];
426
        float radius = rad / scale;
427
        float stroke = str / scale;
428
        int len = mStickerCoords[s].length;
429
        float[] radii = new float[len];
430
        for(int r=0; r<len; r++) radii[r] = radius;
431
        mStickers[s] = new ObjectSticker(mStickerCoords[s],null,radii,stroke);
432
        }
433
      }
434

    
435
    return mStickers[sticker];
436
    }
437

    
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439
// public API
440

    
441
  public Static3D[] getRotationAxis()
442
    {
443
    return ROT_AXIS;
444
    }
445

    
446
///////////////////////////////////////////////////////////////////////////////////////////////////
447

    
448
  public int[] getBasicAngle()
449
    {
450
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
451
    return mBasicAngle;
452
    }
453

    
454
///////////////////////////////////////////////////////////////////////////////////////////////////
455

    
456
  public ObjectType intGetObjectType(int[] numLayers)
457
    {
458
    switch(numLayers[0])
459
      {
460
      case 3: return ObjectType.PYRA_3;
461
      case 4: return ObjectType.PYRA_4;
462
      case 5: return ObjectType.PYRA_5;
463
      }
464

    
465
    return ObjectType.PYRA_3;
466
    }
467

    
468
///////////////////////////////////////////////////////////////////////////////////////////////////
469

    
470
  public String getObjectName()
471
    {
472
    switch(getNumLayers()[0])
473
      {
474
      case 3: return "Pyraminx";
475
      case 4: return "Master Pyraminx";
476
      case 5: return "Professor's Pyraminx";
477
      }
478
    return "Pyraminx";
479
    }
480

    
481
///////////////////////////////////////////////////////////////////////////////////////////////////
482

    
483
  public String getInventor()
484
    {
485
    switch(getNumLayers()[0])
486
      {
487
      case 3: return "Uwe Meffert";
488
      case 4: return "Katsuhiko Okamoto";
489
      case 5: return "Timur Evbatyrov";
490
      }
491
    return "Uwe Meffert";
492
    }
493

    
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495

    
496
  public int getYearOfInvention()
497
    {
498
    switch(getNumLayers()[0])
499
      {
500
      case 3: return 1970;
501
      case 4: return 2002;
502
      case 5: return 2011;
503
      }
504
    return 1970;
505
    }
506

    
507
///////////////////////////////////////////////////////////////////////////////////////////////////
508

    
509
  public int getComplexity()
510
    {
511
    switch(getNumLayers()[0])
512
      {
513
      case 3: return 1;
514
      case 4: return 2;
515
      case 5: return 3;
516
      }
517
    return 4;
518
    }
519
}
(18-18/26)