Project

General

Profile

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

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

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.ScrambleState;
35
import org.distorted.objectlib.main.ShapeTetrahedron;
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

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

    
49
  private ScrambleState[] mStates;
50
  private int[] mBasicAngle;
51
  private Static4D[] mQuats;
52
  private float[][] mCuts;
53

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

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

    
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62

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

    
71
    return mStates;
72
    }
73

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

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

    
95
///////////////////////////////////////////////////////////////////////////////////////////////////
96

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

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

    
111
      start++;
112
      }
113

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

    
117
///////////////////////////////////////////////////////////////////////////////////////////////////
118

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

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

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

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

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

    
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141

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

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

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

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

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

    
168
        currX += DX;
169
        }
170

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

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

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

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

    
190
    return ret;
191
    }
192

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

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

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

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

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

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

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

    
227
    return mCuts;
228
    }
229

    
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231

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

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

    
243
    return layerRotatable;
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247

    
248
  public int getTouchControlType()
249
    {
250
    return TC_TETRAHEDRON;
251
    }
252

    
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

    
255
  public int getTouchControlSplit()
256
    {
257
    return TYPE_NOT_SPLIT;
258
    }
259

    
260
///////////////////////////////////////////////////////////////////////////////////////////////////
261

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

    
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268

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

    
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275

    
276
  public int getNumCubitFaces()
277
    {
278
    return 8;
279
    }
280

    
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

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

    
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289

    
290
  public ObjectShape getObjectShape(int variant)
291
    {
292
    int numL = getNumLayers()[0];
293

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

    
324
///////////////////////////////////////////////////////////////////////////////////////////////////
325

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

    
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333

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

    
339
///////////////////////////////////////////////////////////////////////////////////////////////////
340

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

    
346
///////////////////////////////////////////////////////////////////////////////////////////////////
347

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

    
353
///////////////////////////////////////////////////////////////////////////////////////////////////
354

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

    
374
///////////////////////////////////////////////////////////////////////////////////////////////////
375

    
376
  public float getStickerRadius()
377
    {
378
    return 0.08f;
379
    }
380

    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

    
383
  public float getStickerStroke()
384
    {
385
    float stroke = 0.08f;
386

    
387
    if( ObjectControl.isInIconMode() )
388
      {
389
      int[] numLayers = getNumLayers();
390

    
391
      switch(numLayers[0])
392
        {
393
        case 2: stroke*=1.0f; break;
394
        case 3: stroke*=1.4f; break;
395
        case 4: stroke*=1.7f; break;
396
        default:stroke*=1.9f; break;
397
        }
398
      }
399

    
400
    return stroke;
401
    }
402

    
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404

    
405
  public float[][] getStickerAngles()
406
    {
407
    return null;
408
    }
409

    
410
///////////////////////////////////////////////////////////////////////////////////////////////////
411
// public API
412

    
413
  public Static3D[] getRotationAxis()
414
    {
415
    return ROT_AXIS;
416
    }
417

    
418
///////////////////////////////////////////////////////////////////////////////////////////////////
419

    
420
  public int[] getBasicAngle()
421
    {
422
    if( mBasicAngle ==null ) mBasicAngle = new int[] { 3,3,3,3 };
423
    return mBasicAngle;
424
    }
425

    
426
///////////////////////////////////////////////////////////////////////////////////////////////////
427

    
428
  public ObjectType intGetObjectType(int[] numLayers)
429
    {
430
    switch(numLayers[0])
431
      {
432
      case 3: return ObjectType.PYRA_3;
433
      case 4: return ObjectType.PYRA_4;
434
      case 5: return ObjectType.PYRA_5;
435
      }
436

    
437
    return ObjectType.PYRA_3;
438
    }
439

    
440
///////////////////////////////////////////////////////////////////////////////////////////////////
441

    
442
  public String getObjectName()
443
    {
444
    switch(getNumLayers()[0])
445
      {
446
      case 3: return "Pyraminx";
447
      case 4: return "Master Pyraminx";
448
      case 5: return "Professor's Pyraminx";
449
      }
450
    return "Pyraminx";
451
    }
452

    
453
///////////////////////////////////////////////////////////////////////////////////////////////////
454

    
455
  public String getInventor()
456
    {
457
    switch(getNumLayers()[0])
458
      {
459
      case 3: return "Uwe Meffert";
460
      case 4: return "Katsuhiko Okamoto";
461
      case 5: return "Timur Evbatyrov";
462
      }
463
    return "Uwe Meffert";
464
    }
465

    
466
///////////////////////////////////////////////////////////////////////////////////////////////////
467

    
468
  public int getYearOfInvention()
469
    {
470
    switch(getNumLayers()[0])
471
      {
472
      case 3: return 1970;
473
      case 4: return 2002;
474
      case 5: return 2011;
475
      }
476
    return 1970;
477
    }
478

    
479
///////////////////////////////////////////////////////////////////////////////////////////////////
480

    
481
  public int getComplexity()
482
    {
483
    switch(getNumLayers()[0])
484
      {
485
      case 3: return 1;
486
      case 4: return 2;
487
      case 5: return 3;
488
      }
489
    return 4;
490
    }
491
}
(18-18/26)