Project

General

Profile

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

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

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.objects;
11

    
12
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_TETRAHEDRON;
13
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
14

    
15
import org.distorted.library.type.Static3D;
16
import org.distorted.library.type.Static4D;
17

    
18
import org.distorted.objectlib.helpers.FactoryCubit;
19
import org.distorted.objectlib.helpers.ObjectFaceShape;
20
import org.distorted.objectlib.helpers.ObjectSignature;
21
import org.distorted.objectlib.helpers.ObjectVertexEffects;
22
import org.distorted.objectlib.main.InitAssets;
23
import org.distorted.objectlib.main.InitData;
24
import org.distorted.objectlib.main.ObjectSignatures;
25
import org.distorted.objectlib.touchcontrol.TouchControlTetrahedron;
26
import org.distorted.objectlib.main.ObjectType;
27
import org.distorted.objectlib.helpers.ObjectShape;
28
import org.distorted.objectlib.shape.ShapeTetrahedron;
29

    
30
///////////////////////////////////////////////////////////////////////////////////////////////////
31

    
32
public class TwistyPyraminx extends ShapeTetrahedron
33
{
34
  static final Static3D[] ROT_AXIS = new Static3D[]
35
         {
36
           new Static3D(     0,-SQ3/3,-SQ6/3),
37
           new Static3D(     0,-SQ3/3, SQ6/3),
38
           new Static3D( SQ6/3, SQ3/3,     0),
39
           new Static3D(-SQ6/3, SQ3/3,     0),
40
         };
41

    
42
  private int[][] mEdges;
43
  private int[][] mBasicAngle;
44
  private float[][] mCuts;
45

    
46
///////////////////////////////////////////////////////////////////////////////////////////////////
47

    
48
  public TwistyPyraminx(int meshState, int iconMode, Static4D quat, Static3D move, float scale, InitData data, InitAssets asset)
49
    {
50
    super(meshState, iconMode, data.getNumLayers()[0], quat, move, scale, data, asset);
51
    }
52

    
53
///////////////////////////////////////////////////////////////////////////////////////////////////
54
// edge[i] is the state after moving layer i (0 is the largest)
55

    
56
  public int[][] getScrambleEdges()
57
    {
58
    if( mEdges==null )
59
      {
60
      int nL = getNumLayers()[0];
61
      mEdges = new int[nL][];
62

    
63
      for(int i=0; i<nL; i++)
64
        {
65
        int numEnabledMoves = 2*(nL-i);
66
        mEdges[i] = new int[4*2*numEnabledMoves];
67

    
68
        int index = 0;
69
        int startMove= 0;
70
        int offset = (i==nL-1 ? 2:0);  // if the last move was a tip, the only possible
71
                                       // next move is the second-to-largest layer.
72
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
73
        index += (2*numEnabledMoves);
74
        startMove += (2*nL);
75
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
76
        index += (2*numEnabledMoves);
77
        startMove += (2*nL);
78
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
79
        index += (2*numEnabledMoves);
80
        startMove += (2*nL);
81
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
82
        }
83
      }
84

    
85
    return mEdges;
86
    }
87

    
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89

    
90
  private void fillEdge(int[] edge, int index, int move, int offset, int num)
91
    {
92
    for(int i=0; i<num; i++)
93
      {
94
      edge[index+2*i  ] = (move+offset);
95
      edge[index+2*i+1] = (i+offset)/2;
96
      move++;
97
      }
98
    }
99

    
100
///////////////////////////////////////////////////////////////////////////////////////////////////
101

    
102
  private void addTetrahedralLattice(int size, int index, float[][] pos)
103
    {
104
    final float DX = 1.0f;
105
    final float DY = SQ2/2;
106
    final float DZ = 1.0f;
107

    
108
    float startX = 0.0f;
109
    float startY =-DY*(size-1)/2;
110
    float startZ = DZ*(size-1)/2;
111

    
112
    for(int layer=0; layer<size; layer++)
113
      {
114
      float currX = startX;
115
      float currY = startY;
116

    
117
      for(int x=0; x<layer+1; x++)
118
        {
119
        float currZ = startZ;
120

    
121
        for(int z=0; z<size-layer; z++)
122
          {
123
          pos[index] = new float[] {currX,currY,currZ};
124
          index++;
125
          currZ -= DZ;
126
          }
127

    
128
        currX += DX;
129
        }
130

    
131
      startX-=DX/2;
132
      startY+=DY;
133
      startZ-=DZ/2;
134
      }
135
    }
136

    
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

    
139
  private int getNumOctahedrons(int numLayers)
140
    {
141
    return (numLayers-1)*numLayers*(numLayers+1)/6;
142
    }
143

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

    
146
  public float[][] getCuts(int[] numLayers)
147
    {
148
    if( mCuts==null )
149
      {
150
      int numL = numLayers[0];
151
      mCuts = new float[4][numL-1];
152

    
153
      for(int i=0; i<numL-1; i++)
154
        {
155
        float cut = (1.0f+i-numL/4.0f)*(SQ6/3);
156
        mCuts[0][i] = cut;
157
        mCuts[1][i] = cut;
158
        mCuts[2][i] = cut;
159
        mCuts[3][i] = cut;
160
        }
161
      }
162

    
163
    return mCuts;
164
    }
165

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

    
168
  public boolean[][] getLayerRotatable(int[] numLayers)
169
    {
170
    int numAxis = ROT_AXIS.length;
171
    boolean[][] layerRotatable = new boolean[numAxis][];
172

    
173
    for(int i=0; i<numAxis; i++)
174
      {
175
      layerRotatable[i] = new boolean[numLayers[i]];
176
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
177
      }
178

    
179
    return layerRotatable;
180
    }
181

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183

    
184
  public int getTouchControlType()
185
    {
186
    return TC_TETRAHEDRON;
187
    }
188

    
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190

    
191
  public int getTouchControlSplit()
192
    {
193
    return TYPE_NOT_SPLIT;
194
    }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

    
198
  public int[][][] getEnabled()
199
    {
200
    return new int[][][] { {{1,2,3}},{{0,2,3}},{{0,1,3}},{{0,1,2}} };
201
    }
202

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

    
205
  public float[] getDist3D(int[] numLayers)
206
    {
207
    return TouchControlTetrahedron.D3D;
208
    }
209

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

    
212
  public Static3D[] getFaceAxis()
213
    {
214
    return TouchControlTetrahedron.FACE_AXIS;
215
    }
216

    
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218
// there are (n^3-n)/6 octahedrons and ((n+1)^3 - (n+1))/6 tetrahedrons
219

    
220
  public float[][] getCubitPositions(int[] numLayers)
221
    {
222
    int numL = numLayers[0];
223
    int numOcta = (numL-1)*numL*(numL+1)/6;
224
    int numTetra= numL*(numL+1)*(numL+2)/6;
225
    float[][] ret = new float[numOcta+numTetra][];
226

    
227
    addTetrahedralLattice(numL-1,      0,ret);
228
    addTetrahedralLattice(numL  ,numOcta,ret);
229

    
230
    return ret;
231
    }
232

    
233
///////////////////////////////////////////////////////////////////////////////////////////////////
234

    
235
  public Static4D getCubitQuats(int cubit, int[] numLayers)
236
    {
237
    return mObjectQuats[0];
238
    }
239

    
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241

    
242
  private float[][] getVertices(int variant)
243
    {
244
    if( variant==0 )
245
      {
246
      return 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} };
247
      }
248
    else
249
      {
250
      return 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} };
251
      }
252
    }
253

    
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255

    
256
  public ObjectShape getObjectShape(int variant)
257
    {
258
    if( variant==0 )
259
      {
260
      int[][] indices   = { {3,0,4},{0,1,4},{1,2,4},{2,3,4},{5,0,3},{5,1,0},{5,2,1},{5,3,2} };
261
      return new ObjectShape(getVertices(variant), indices);
262
      }
263
    else
264
      {
265
      int[][] indices   = { {2,1,0},{3,0,1},{3,2,0},{2,3,1} };
266
      return new ObjectShape(getVertices(variant), indices);
267
      }
268
    }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271

    
272
  public ObjectFaceShape getObjectFaceShape(int variant)
273
    {
274
    int numL = getNumLayers()[0];
275
    float height = isInIconMode() ? 0.001f : 0.05f;
276

    
277
    if( variant==0 )
278
      {
279
      int N = numL==3? 6 : 5;
280
      int E = numL==3? 2 : 1;
281
      float[][] bands = { {height,20,0.5f,0.8f,N,E,E} };
282
      int[] indices   = { 0,0,0,0,0,0,0,0 };
283
      return new ObjectFaceShape(bands,indices,null);
284
      }
285
    else
286
      {
287
      int N = numL==3? 6 : 5;
288
      int E = numL==3? 2 : 1;
289
      float[][] bands = { {height,35,0.5f,0.8f,N,E,E} };
290
      int[] indices   = { 0,0,0,0 };
291
      return new ObjectFaceShape(bands,indices,null);
292
      }
293
    }
294

    
295
///////////////////////////////////////////////////////////////////////////////////////////////////
296

    
297
  public ObjectVertexEffects getVertexEffects(int variant)
298
    {
299
    if( variant==0 )
300
      {
301
      float[][] corners = { {0.04f,0.20f} };
302
      int[] indices     = { 0,0,0,0,0,0 };
303
      float[][] centers = { {0.0f, 0.0f, 0.0f} };
304
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
305
      }
306
    else
307
      {
308
      float[][] corners = { {0.06f,0.15f} };
309
      int[] indices     = { 0,0,0,0 };
310
      float[][] centers = { {0.0f, 0.0f, 0.0f} };
311
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
312
      }
313
    }
314

    
315
///////////////////////////////////////////////////////////////////////////////////////////////////
316

    
317
  public int getNumCubitVariants(int[] numLayers)
318
    {
319
    return 2;
320
    }
321

    
322
///////////////////////////////////////////////////////////////////////////////////////////////////
323

    
324
  public int getCubitVariant(int cubit, int[] numLayers)
325
    {
326
    return cubit<getNumOctahedrons(numLayers[0]) ? 0:1;
327
    }
328

    
329
///////////////////////////////////////////////////////////////////////////////////////////////////
330

    
331
  public float getStickerRadius()
332
    {
333
    return 0.08f;
334
    }
335

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

    
338
  public float getStickerStroke()
339
    {
340
    float stroke = 0.08f;
341

    
342
    if( isInIconMode() )
343
      {
344
      int[] numLayers = getNumLayers();
345

    
346
      switch(numLayers[0])
347
        {
348
        case 2: stroke*=1.0f; break;
349
        case 3: stroke*=1.4f; break;
350
        case 4: stroke*=1.7f; break;
351
        default:stroke*=1.9f; break;
352
        }
353
      }
354

    
355
    return stroke;
356
    }
357

    
358
///////////////////////////////////////////////////////////////////////////////////////////////////
359

    
360
  public float[][] getStickerAngles()
361
    {
362
    return null;
363
    }
364

    
365
///////////////////////////////////////////////////////////////////////////////////////////////////
366
// public API
367

    
368
  public Static3D[] getRotationAxis()
369
    {
370
    return ROT_AXIS;
371
    }
372

    
373
///////////////////////////////////////////////////////////////////////////////////////////////////
374

    
375
  public int[][] getBasicAngles()
376
    {
377
    if( mBasicAngle ==null )
378
      {
379
      int num = getNumLayers()[0];
380
      int[] tmp = new int[num];
381
      for(int i=0; i<num; i++) tmp[i] = 3;
382
      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
383
      }
384

    
385
    return mBasicAngle;
386
    }
387

    
388
///////////////////////////////////////////////////////////////////////////////////////////////////
389

    
390
  public String getShortName()
391
    {
392
    switch(getNumLayers()[0])
393
      {
394
      case 3: return ObjectType.PYRA_3.name();
395
      case 4: return ObjectType.PYRA_4.name();
396
      case 5: return ObjectType.PYRA_5.name();
397
      }
398

    
399
    return ObjectType.PYRA_3.name();
400
    }
401

    
402
///////////////////////////////////////////////////////////////////////////////////////////////////
403

    
404
  public ObjectSignature getSignature()
405
    {
406
    switch(getNumLayers()[0])
407
      {
408
      case 3: return new ObjectSignature(ObjectSignatures.PYRA_3);
409
      case 4: return new ObjectSignature(ObjectSignatures.PYRA_4);
410
      case 5: return new ObjectSignature(ObjectSignatures.PYRA_5);
411
      }
412

    
413
    return null;
414
    }
415

    
416
///////////////////////////////////////////////////////////////////////////////////////////////////
417

    
418
  public String getObjectName()
419
    {
420
    switch(getNumLayers()[0])
421
      {
422
      case 3: return "Pyraminx";
423
      case 4: return "Master Pyraminx";
424
      case 5: return "Professor's Pyraminx";
425
      }
426
    return null;
427
    }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430

    
431
  public String getInventor()
432
    {
433
    switch(getNumLayers()[0])
434
      {
435
      case 3: return "Uwe Meffert";
436
      case 4: return "Katsuhiko Okamoto";
437
      case 5: return "Timur Evbatyrov";
438
      }
439
    return null;
440
    }
441

    
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443

    
444
  public int getYearOfInvention()
445
    {
446
    switch(getNumLayers()[0])
447
      {
448
      case 3: return 1970;
449
      case 4: return 2002;
450
      case 5: return 2011;
451
      }
452
    return 1970;
453
    }
454

    
455
///////////////////////////////////////////////////////////////////////////////////////////////////
456

    
457
  public int getComplexity()
458
    {
459
    switch(getNumLayers()[0])
460
      {
461
      case 3: return 1;
462
      case 4: return 2;
463
      case 5: return 3;
464
      }
465
    return 4;
466
    }
467

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

    
470
  public String[][] getTutorials()
471
    {
472
    int[] numLayers = getNumLayers();
473

    
474
    switch(numLayers[0])
475
      {
476
      case 3: return new String[][] {
477
                          {"gb","xIQtn2qazvg","Pyraminx Layer By Layer","Z3"},
478
                          {"es","4cJJe9RAzAU","Resolver Pyraminx","Cuby"},
479
                          {"ru","F4_bhfWyVRQ","Как собрать ПИРАМИДКУ","Е Бондаренко"},
480
                          {"fr","Z2h1YI6jPes","Comment résoudre le Pyraminx","ValentinoCube"},
481
                          {"de","x_DMA8htJpY","Pyraminx lösen","Pezcraft"},
482
                          {"pl","uNpKpJfAa5I","Jak ułożyć: Pyraminx","DżoDżo"},
483
                          {"br","dtC0GNGyXqw","Como resolver o Pyraminx","Pedro Filho"},
484
                          {"kr","mO3excjvvoA","피라밍크스 맞추는 방법","iamzoone"},
485
                          {"vn","p9LUWUW5iYg","Tutorial N.4 - Pyraminx","Duy Thích Rubik"},
486
                    //    {"tw","YS3cDcP6Aro","金字塔方塊解法","1hrBLD"},
487
                         };
488
      case 4: return new String[][] {
489
                          {"gb","tGQDqDcSa6U","How to Solve the Master Pyraminx","Z3"},
490
                          {"es","74PIPm9-uPg","Resolver Master Pyraminx 4x4","Cuby"},
491
                          {"ru","-F_xJAwkobU","Как собрать Мастер Пираминкс"," Алексей Ярыгин"},
492
                          {"fr","F3gzBs7uvmw","Tuto: résoudre le Master Pyraminx","Spaghetti Cubing"},
493
                          {"de","3Q_bO7_FfAI","Master Pyraminx lösen","CubaroCubing"},
494
                          {"pl","EamwvhmHC7Q","4x4 (Master) Pyraminx PL","MrUk"},
495
                          {"br","cKql6YZ7yAg","Como resolver o Pyraminx 4x4 1/3","Rafael Cinoto"},
496
                          {"br","gtNQDPsN2Dg","Como resolver o Pyraminx 4x4 2/3","Rafael Cinoto"},
497
                          {"br","j8_-s4rd8mw","Como resolver o Pyraminx 4x4 3/3","Rafael Cinoto"},
498
                          {"kr","JlmBKaHESyY","마스터 피라밍크스 해법","주누후누"},
499
                          {"vn","AMCll82WcJY","Tutorial N.13 - Master Pyraminx","Duy Thích Rubik"},
500
                         };
501
      case 5: return new String[][] {
502
                          {"gb","2nsPEECDdN0","Professor Pyraminx Solve","RedKB"},
503
                          {"es","cSDj8OQK3TU","Tutorial del Professor Pyraminx","QBAndo"},
504
                          {"ru","gMp1tbDyDWg","Как собрать Professor Pyraminx","RBcuber"},
505
                          {"de","pCHx9bVMSgI","Professor Pyraminx Teil 1","Arvid Bollmann"},
506
                          {"de","iiNXJMVNmCM","Professor Pyraminx Teil 2","Arvid Bollmann"},
507
                          {"br","t2QJSSjNxPw","Resolver o Professor Pyraminx 1/4","Rafael Cinoto"},
508
                          {"br","mI6W6IFyVv0","Resolver o Professor Pyraminx 2/4","Rafael Cinoto"},
509
                          {"br","0HoOp6JlLSs","Resolver o Professor Pyraminx 3/4","Rafael Cinoto"},
510
                          {"br","Xg1jnCRsw_I","Resolver o Professor Pyraminx 4/4","Rafael Cinoto"},
511
                          {"vn","OHwPqp3kQdE","Professor Pyraminx làm chậm","TRẦN QUANG HÙNG"},
512
                         };
513
      }
514
    return null;
515
    }
516
}
(28-28/41)