Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyPenrose.java @ 0431e308

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2022 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_CHANGING_MIRROR;
13
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
14

    
15
import org.distorted.library.effect.EffectName;
16
import org.distorted.library.helpers.QuatHelper;
17
import org.distorted.library.type.Static3D;
18
import org.distorted.library.type.Static4D;
19
import org.distorted.objectlib.helpers.FactoryCubit;
20
import org.distorted.objectlib.helpers.ObjectFaceShape;
21
import org.distorted.objectlib.helpers.ObjectShape;
22
import org.distorted.objectlib.helpers.ObjectVertexEffects;
23
import org.distorted.objectlib.main.InitAssets;
24
import org.distorted.objectlib.metadata.ListObjects;
25
import org.distorted.objectlib.metadata.Metadata;
26
import org.distorted.objectlib.scrambling.ScrambleEdgeGenerator;
27
import org.distorted.objectlib.shape.ShapeHexahedron;
28
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
29

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

    
32
public class TwistyPenrose extends ShapeHexahedron
33
{
34
  static final Static3D[] ROT_AXIS = new Static3D[]
35
         {
36
           new Static3D(1,0,0),
37
           new Static3D(0,1,0),
38
           new Static3D(0,0,1)
39
         };
40

    
41
  private int[][] mEdges;
42
  private int[][] mBasicAngle;
43
  private float[][] mCuts;
44
  private int[] mQuatIndex;
45
  private int[][] mFaceMap;
46
  private int[][] mQuatDivided;
47

    
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49

    
50
  public TwistyPenrose(int iconMode, Static4D quat, Static3D move, float scale, Metadata meta, InitAssets asset)
51
    {
52
    super(iconMode, meta.getNumLayers()[0], quat, move, scale, meta, asset);
53
    }
54

    
55
///////////////////////////////////////////////////////////////////////////////////////////////////
56
// { -0.5f, -0.49999997f, 0.5f, -0.49999997f, 0.5f, 0.49999997f, -0.5f, 0.49999997f}
57
// { -0.24999999f, 0.5f, -0.24999999f, -0.24999999f, 0.5f, -0.24999999f}
58
// { -0.5f, -0.08578644f, -0.08578644f, -0.49999997f, 0.5f, 0.08578644f, 0.085786454f, 0.5f}
59

    
60
  @Override
61
  public void adjustStickerCoords()
62
    {
63
    final float A = 0.50f;
64
    final float B = 0.25f;
65
    final float C = 0.08578644f;
66
    final float D = 0.23f;
67

    
68
    final float E = (A+D)/5;
69
    final float F = 0.005f;
70
    final float G = (A+D)/2;
71
    final float H = 0.002f;
72

    
73
    mStickerCoords = new float[][][][]
74
          {
75
            { { {-A,-A},{ A,-A},{ A, A},{-A, A} } },
76
            { { {-B, A},{-B,-B},{ A,-B},{ A,-D},{A-E+F,-D+E+F},{A-2*E,-D+2*E},{A-G+H,-D+G+H},{-D+2*E,A-2*E},{-D+E+F,A-E+F},{-D, A} } },
77
            { { {-A,-C},{-C,-A},{ A, C},{ C, A} } }
78
          };
79
    }
80

    
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82

    
83
  @Override
84
  protected float[][][] getStickerRadii()
85
    {
86
    float R = getStickerRadius();
87
    float R2 = 1.3f*R;
88

    
89
    return new float[][][]
90
      {
91
        { { R, R, R, R } },
92
        { { R2, R, R2, 0, 0,0,0,0,0, 0 } },
93
        { { R, R, R, R } },
94
      };
95
    }
96

    
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98
// remember about the double cover or unit quaternions!
99

    
100
  private int mulQuat(int q1, int q2)
101
    {
102
    Static4D result = QuatHelper.quatMultiply(mObjectQuats[q1],mObjectQuats[q2]);
103
    return findQuatIndex(result);
104
    }
105

    
106
///////////////////////////////////////////////////////////////////////////////////////////////////
107
// remember about the double cover or unit quaternions!
108

    
109
  private int findQuatIndex(Static4D quat)
110
    {
111
    int numQ = mObjectQuats.length;
112

    
113
    float rX = quat.get0();
114
    float rY = quat.get1();
115
    float rZ = quat.get2();
116
    float rW = quat.get3();
117

    
118
    final float MAX_ERROR = 0.1f;
119
    float dX,dY,dZ,dW;
120

    
121
    for(int i=0; i<numQ; i++)
122
      {
123
      dX = mObjectQuats[i].get0() - rX;
124
      dY = mObjectQuats[i].get1() - rY;
125
      dZ = mObjectQuats[i].get2() - rZ;
126
      dW = mObjectQuats[i].get3() - rW;
127

    
128
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
129
          dY<MAX_ERROR && dY>-MAX_ERROR &&
130
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
131
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
132

    
133
      dX = mObjectQuats[i].get0() + rX;
134
      dY = mObjectQuats[i].get1() + rY;
135
      dZ = mObjectQuats[i].get2() + rZ;
136
      dW = mObjectQuats[i].get3() + rW;
137

    
138
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
139
          dY<MAX_ERROR && dY>-MAX_ERROR &&
140
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
141
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
142
      }
143

    
144
    return -1;
145
    }
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148
// QDivided[i][j] = ObjectQ[i]/ObjectQ[j] -> QDivided[i][j] * ObjectQ[j] = ObjectQ[i]
149

    
150
  private void createQuatDivided()
151
    {
152
    int numQ = mObjectQuats.length;
153

    
154
    mQuatDivided = new int[numQ][numQ];
155

    
156
    for(int i=0; i<numQ; i++)
157
      for(int j=0; j<numQ; j++) mQuatDivided[i][j] = -3;
158

    
159
    for(int i=0; i<numQ; i++)
160
      for(int j=0; j<numQ; j++)
161
        {
162
        int q = mulQuat(i,j);
163
        mQuatDivided[q][j] = i;
164
        }
165

    
166
    for(int i=0; i<numQ; i++)
167
      for(int j=0; j<numQ; j++)
168
        if( mQuatDivided[i][j] == -3 )
169
          android.util.Log.e("D", "quat divided: "+i+" "+j);
170
    }
171

    
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173

    
174
  @Override
175
  public int[][] getSolvedQuats()
176
    {
177
    if( mQuatDivided==null ) createQuatDivided();
178

    
179
    int[][] ret =  new int[][]
180
      {
181
              { 1, 12, mQuatDivided[15][12], mQuatDivided[17][12] },  // triplet of full edges 12<-->15<-->17
182
              { 1, 15, mQuatDivided[12][15], mQuatDivided[17][15] },
183
              { 1, 17, mQuatDivided[12][17], mQuatDivided[15][17] },
184
              { 1, 13, mQuatDivided[16][13], mQuatDivided[19][13] },  // triplet of full edges 13<-->16<-->19
185
              { 1, 16, mQuatDivided[13][16], mQuatDivided[19][16] },
186
              { 1, 19, mQuatDivided[13][19], mQuatDivided[16][19] },
187
              { 1, 11, mQuatDivided[14][11], mQuatDivided[18][11] },  // triplet of full edges 11<-->14<-->18
188
              { 1, 14, mQuatDivided[11][14], mQuatDivided[18][14] },
189
              { 1, 18, mQuatDivided[11][18], mQuatDivided[14][18] },
190

    
191
              { 1, 20, 1, 2, 3 },  // +X center; in-face rotations.
192
              { 1, 21, 1, 2, 3 },  // -X center
193
              { 1, 22, 4, 5, 6 },  // +Y center
194
              { 1, 23, 4, 5, 6 },  // -Y center
195
              { 1, 24, 7, 8, 9 },  // +Z center
196
              { 1, 25, 7, 8, 9 }   // -Z center
197
      };
198

    
199
    StringBuilder sb = new StringBuilder();
200
    int l = ret.length;
201
    sb.append("SOLVED QUATS");
202

    
203
    for(int i=0; i<l; i++)
204
      {
205
      sb.append("\ngroup ");
206
      sb.append(i);
207
      sb.append(" : ");
208

    
209
      for( int s : ret[i] )
210
        {
211
        sb.append(' ');
212
        sb.append(s);
213
        }
214
      }
215

    
216
    android.util.Log.e("D", sb.toString() );
217

    
218
    return ret;
219
    }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222
// we need to manually change the colors of the faces
223

    
224
  @Override
225
  public int getCubitFaceMap(int cubit, int face)
226
    {
227
    if( mFaceMap==null )
228
      {
229
      final int C1 = 1;
230
      final int C2 = 2;
231
      final int C3 = 4;
232

    
233
      mFaceMap = new int[][]
234
         {
235
                 {-1,C2,-1,C1,-1,C3},
236
                 {-1,C1,-1,C2,-1,C3},
237

    
238
                 {-1,C1,C2,-1,-1,-1},
239
                 {-1,C3,C2,-1,-1,-1},
240
                 {-1,C2,C3,-1,-1,-1},
241
                 {-1,C2,C1,-1,-1,-1},
242
                 {-1,C3,C1,-1,-1,-1},
243
                 {-1,C1,C3,-1,-1,-1},
244

    
245
                 {-1,-1,C3,-1,-1,-1},
246
                 {-1,-1,C1,-1,-1,-1},
247
                 {-1,-1,C2,-1,-1,-1},
248

    
249
                 {-1,-1,-1,C2,-1,C1},
250
                 {-1,-1,-1,C3,-1,C2},
251
                 {-1,-1,-1,C1,-1,C3},
252
                 {-1,-1,-1,C2,-1,C1},
253
                 {-1,-1,-1,C3,-1,C2},
254
                 {-1,-1,-1,C3,-1,C1},
255
                 {-1,-1,-1,C3,-1,C2},
256
                 {-1,-1,-1,C2,-1,C1},
257
                 {-1,-1,-1,C3,-1,C1},
258

    
259
                 {-1,-1,-1,-1,C1,-1},
260
                 {-1,-1,-1,-1,C2,-1},
261
                 {-1,-1,-1,-1,C3,-1},
262
                 {-1,-1,-1,-1,C2,-1},
263
                 {-1,-1,-1,-1,C3,-1},
264
                 {-1,-1,-1,-1,C1,-1},
265
         };
266
      }
267

    
268
    return mFaceMap[cubit][face];
269
    }
270

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

    
273
  public int[][] getScrambleEdges()
274
    {
275
    int[] numL = getNumLayers();
276
    if( mEdges==null ) mEdges = ScrambleEdgeGenerator.getScrambleEdgesCuboid(numL[0],numL[1],numL[2]);
277
    return mEdges;
278
    }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

    
282
  public float[][] getCuts(int[] numLayers)
283
    {
284
    if( mCuts==null )
285
      {
286
      mCuts = new float[3][];
287

    
288
      for(int axis=0; axis<3; axis++)
289
        {
290
        int len = numLayers[axis];
291
        float start = (2-len)*0.5f;
292

    
293
        if( len>=2 )
294
          {
295
          mCuts[axis] = new float[len-1];
296
          for(int i=0; i<len-1; i++) mCuts[axis][i] = start+i;
297
          }
298
        }
299
      }
300

    
301
    return mCuts;
302
    }
303

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

    
306
  public boolean[][] getLayerRotatable(int[] numLayers)
307
    {
308
    int numAxis = ROT_AXIS.length;
309
    boolean[][] layerRotatable = new boolean[numAxis][];
310

    
311
    for(int i=0; i<numAxis; i++)
312
      {
313
      layerRotatable[i] = new boolean[numLayers[i]];
314
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
315
      }
316

    
317
    return layerRotatable;
318
    }
319

    
320
///////////////////////////////////////////////////////////////////////////////////////////////////
321

    
322
  public int getTouchControlType()
323
    {
324
    return TC_CHANGING_MIRROR;
325
    }
326

    
327
///////////////////////////////////////////////////////////////////////////////////////////////////
328

    
329
  public int getTouchControlSplit()
330
    {
331
    return TYPE_NOT_SPLIT;
332
    }
333

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

    
336
  public int[][][] getEnabled()
337
    {
338
    return new int[][][] { {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}} };
339
    }
340

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

    
343
  public float[] getDist3D(int[] numLayers)
344
    {
345
    return TouchControlHexahedron.D3D;
346
    }
347

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

    
350
  public Static3D[] getFaceAxis()
351
    {
352
    return TouchControlHexahedron.FACE_AXIS;
353
    }
354

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

    
357
  public float[][] getCubitPositions(int[] numLayers)
358
    {
359
    final int X = numLayers[0];
360
    final int Y = numLayers[1];
361
    final int Z = numLayers[2];
362

    
363
    final float lenX = 0.5f*(X-1);
364
    final float lenY = 0.5f*(Y-1);
365
    final float lenZ = 0.5f*(Z-1);
366

    
367
    int curPos = 0;
368
    int numCubits = X*Y*Z - (X-2)*(Y-2)*(Z-2);
369
    float[][] pos = new float[numCubits][];
370

    
371
    pos[curPos++] = new float[] {-lenX,+lenY,-lenZ};   // 2 full corners
372
    pos[curPos++] = new float[] {+lenX,-lenY,+lenZ};
373

    
374
    pos[curPos++] = new float[] {-lenX,-lenY,-lenZ};   // 6 round corners
375
    pos[curPos++] = new float[] {-lenX,-lenY,+lenZ};
376
    pos[curPos++] = new float[] {-lenX,+lenY,+lenZ};
377
    pos[curPos++] = new float[] {+lenX,-lenY,-lenZ};
378
    pos[curPos++] = new float[] {+lenX,+lenY,-lenZ};
379
    pos[curPos++] = new float[] {+lenX,+lenY,+lenZ};
380

    
381
    for(int i=1; i<X-1; i++) pos[curPos++] = new float[] { i-lenX,  +lenY,  +lenZ };  // round edges
382
    for(int i=1; i<Y-1; i++) pos[curPos++] = new float[] {  +lenX, i-lenY,  -lenZ };
383
    for(int i=1; i<Z-1; i++) pos[curPos++] = new float[] {  -lenX,  -lenY, i-lenZ };
384

    
385
    for(int i=1; i<X-1; i++) pos[curPos++] = new float[] { i-lenX,  -lenY,  -lenZ };  // normal edges
386
    for(int i=1; i<X-1; i++) pos[curPos++] = new float[] { i-lenX,  -lenY,  +lenZ };
387
    for(int i=1; i<X-1; i++) pos[curPos++] = new float[] { i-lenX,  +lenY,  -lenZ };
388
    for(int i=1; i<Y-1; i++) pos[curPos++] = new float[] {  -lenX, i-lenY,  -lenZ };
389
    for(int i=1; i<Y-1; i++) pos[curPos++] = new float[] {  -lenX, i-lenY,  +lenZ };
390
    for(int i=1; i<Y-1; i++) pos[curPos++] = new float[] {  +lenX, i-lenY,  +lenZ };
391
    for(int i=1; i<Z-1; i++) pos[curPos++] = new float[] {  -lenX,  +lenY, i-lenZ };
392
    for(int i=1; i<Z-1; i++) pos[curPos++] = new float[] {  +lenX,  -lenY, i-lenZ };
393
    for(int i=1; i<Z-1; i++) pos[curPos++] = new float[] {  +lenX,  +lenY, i-lenZ };
394

    
395
    for(int y=1; y<Y-1; y++)
396
      for(int z=1; z<Z-1; z++) pos[curPos++] = new float[] {+lenX,y-lenY,z-lenZ};     // centers
397

    
398
    for(int y=1; y<Y-1; y++)
399
      for(int z=1; z<Z-1; z++) pos[curPos++] = new float[] {-lenX,y-lenY,z-lenZ};
400

    
401
    for(int x=1; x<X-1; x++)
402
      for(int z=1; z<Z-1; z++) pos[curPos++] = new float[] {x-lenX,+lenY,z-lenZ};
403

    
404
    for(int x=1; x<X-1; x++)
405
      for(int z=1; z<Z-1; z++) pos[curPos++] = new float[] {x-lenX,-lenY,z-lenZ};
406

    
407
    for(int x=1; x<X-1; x++)
408
      for(int y=1; y<Y-1; y++) pos[curPos++] = new float[] {x-lenX,y-lenY,+lenZ};
409

    
410
    for(int x=1; x<X-1; x++)
411
      for(int y=1; y<Y-1; y++) pos[curPos++] = new float[] {x-lenX,y-lenY,-lenZ};
412

    
413
    return pos;
414
    }
415

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

    
418
  public Static4D getCubitQuats(int cubit, int[] numLayers)
419
    {
420
    if( mQuatIndex==null )
421
      {
422
      mQuatIndex = new int[] { 3,5,
423
                               2,9,20,11,13,6,
424
                               6,11,2,
425
                               0,1,3,7,12,10,17,4,16,
426
                               6,4,1,3,0,2
427
                             };
428
      }
429
    return mObjectQuats[mQuatIndex[cubit]];
430
    }
431

    
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433

    
434
  private float[][] getVertices(int variant)
435
    {
436
    if( variant==1 || variant==2 )
437
      {
438
      return new float[][]
439
          {
440
              {-0.5f,-0.5f,-0.5f },
441
              {+0.5f,-0.5f,-0.5f },
442
              {+0.5f,+0.5f,-0.5f },
443
              {-0.5f,-0.5f,+0.5f },
444
              {+0.5f,-0.5f,+0.5f },
445
              {+0.5f,+0.5f,+0.5f },
446
          };
447
      }
448
    else
449
      {
450
      return new float[][]
451
          {
452
              { 0.5f, 0.5f, 0.5f },
453
              { 0.5f, 0.5f,-0.5f },
454
              { 0.5f,-0.5f, 0.5f },
455
              { 0.5f,-0.5f,-0.5f },
456
              {-0.5f, 0.5f, 0.5f },
457
              {-0.5f, 0.5f,-0.5f },
458
              {-0.5f,-0.5f, 0.5f },
459
              {-0.5f,-0.5f,-0.5f },
460
          };
461
      }
462
    }
463

    
464
///////////////////////////////////////////////////////////////////////////////////////////////////
465

    
466
  public ObjectShape getObjectShape(int variant)
467
    {
468
    if( variant==1 || variant==2 )
469
      {
470
      int[][] indices =
471
          {
472
              {2,1,0},
473
              {3,4,5},
474
              {0,3,5,2},
475
              {0,1,4,3},
476
              {5,4,1,2}
477
          };
478

    
479
      return new ObjectShape(getVertices(variant), indices);
480
      }
481
    else
482
      {
483
      int[][] indices =
484
          {
485
              {2,3,1,0},
486
              {7,6,4,5},
487
              {4,0,1,5},
488
              {7,3,2,6},
489
              {6,2,0,4},
490
              {3,7,5,1}
491
          };
492

    
493
      return new ObjectShape(getVertices(variant), indices);
494
      }
495
    }
496

    
497
///////////////////////////////////////////////////////////////////////////////////////////////////
498

    
499
  public ObjectFaceShape getObjectFaceShape(int variant)
500
    {
501
    int extraI, extraV, n1, n2, numL = getNumLayers()[0];
502

    
503
    switch(numL)
504
        {
505
        case 2 : n1 = 6; n2 = 8; extraI = 2; extraV = 1; break;
506
        case 3 : n1 = 5; n2 = 7; extraI = 1; extraV = 1; break;
507
        case 4 : n1 = 5; n2 = 6; extraI = 1; extraV = 1; break;
508
        default: n1 = 5; n2 = 6; extraI = 0; extraV = 0; break;
509
        }
510

    
511
    float h1 = isInIconMode() ? 0.001f : 0.045f;
512
    float h2 = isInIconMode() ? 0.001f : 0.030f;
513
    int angle = 35;
514
    float R = 0.5f;
515
    float S = 0.7f;
516

    
517
    float[][] bands  =
518
         {
519
             {    h1,angle,R,S,n1,extraI,extraV},
520
             {0.001f,angle,R,S, 2,  n1-2,extraV},
521
             {0.001f,angle,R,S, 2,     0,     0},
522
             {0.001f,angle,R,S,n1,extraI,extraV},
523
             {    h2,angle,R,S,n2,extraI,extraV},
524
             {0.001f,angle,R,S,n2,extraI,extraV},
525
         };
526

    
527
    switch(variant)
528
      {
529
      case 0: return new ObjectFaceShape(bands,new int[] {3,0,3,0,3,0},null);
530
      case 1: return new ObjectFaceShape(bands,new int[] { 5,4,4,5,5 },null);
531
      case 2: return new ObjectFaceShape(bands,new int[] { 5,5,4,5,5 },null);
532
      case 3: return new ObjectFaceShape(bands,new int[] {1,1,1,0,1,0},null);
533
      case 4: return new ObjectFaceShape(bands,new int[] {2,2,2,2,0,2},null);
534
      }
535

    
536
    return null;
537
    }
538

    
539
///////////////////////////////////////////////////////////////////////////////////////////////////
540

    
541
  public ObjectVertexEffects getVertexEffects(int variant)
542
    {
543
    float[][] corners= { {0.030f,0.12f} };
544
    float[][] centers= { {0.0f, 0.0f, 0.0f} };
545
    float[][] vertices= getVertices(variant);
546

    
547
    if( variant==1 || variant==2 )
548
      {
549
      int[] indices = { 0,0,0,0,0,0 };
550
      ObjectVertexEffects effects = FactoryCubit.generateVertexEffect(vertices,corners,indices,centers,indices);
551
      String n = EffectName.PIPE.name();
552
      float[] v = {0.5f,0,0,1,0.92f};
553
      float[] c = {-0.5f,0.5f,0.0f};
554
      float[] r = {0,0,0,0};
555
      effects.joinEffect(n,v,c,r,true);
556
      return effects;
557
      }
558
    else
559
      {
560
      int[] indices = { 0,0,0,0,0,0,0,0 };
561
      return FactoryCubit.generateVertexEffect(vertices,corners,indices,centers,indices);
562
      }
563
    }
564

    
565
///////////////////////////////////////////////////////////////////////////////////////////////////
566

    
567
  public int getNumCubitVariants(int[] numLayers)
568
    {
569
    return 5;
570
    }
571

    
572
///////////////////////////////////////////////////////////////////////////////////////////////////
573

    
574
  public int getCubitVariant(int cubit, int[] numLayers)
575
    {
576
    if( cubit<2  ) return 0;
577
    if( cubit<8  ) return 1;
578
    if( cubit<11 ) return 2;
579
    if( cubit<20 ) return 3;
580

    
581
    return 4;
582
    }
583

    
584
///////////////////////////////////////////////////////////////////////////////////////////////////
585

    
586
  public float getStickerRadius()
587
    {
588
    return 0.10f;
589
    }
590

    
591
///////////////////////////////////////////////////////////////////////////////////////////////////
592

    
593
  public float getStickerStroke()
594
    {
595
    return isInIconMode() ? 0.22f : 0.10f;
596
    }
597

    
598
///////////////////////////////////////////////////////////////////////////////////////////////////
599

    
600
  public float[][][] getStickerAngles()
601
    {
602
    return null;
603
    }
604

    
605
///////////////////////////////////////////////////////////////////////////////////////////////////
606
// PUBLIC API
607

    
608
  public Static3D[] getRotationAxis()
609
    {
610
    return ROT_AXIS;
611
    }
612

    
613
///////////////////////////////////////////////////////////////////////////////////////////////////
614

    
615
  public String getShortName()
616
    {
617
    return ListObjects.PENR_3.name();
618
    }
619

    
620
///////////////////////////////////////////////////////////////////////////////////////////////////
621

    
622
  public int[][] getBasicAngles()
623
    {
624
    if( mBasicAngle ==null )
625
      {
626
      int num = getNumLayers()[0];
627
      int[] tmp = new int[num];
628
      for(int i=0; i<num; i++) tmp[i] = 4;
629
      mBasicAngle = new int[][] { tmp,tmp,tmp };
630
      }
631

    
632
    return mBasicAngle;
633
    }
634

    
635
///////////////////////////////////////////////////////////////////////////////////////////////////
636

    
637
  public String[][] getTutorials()
638
    {
639
    return new String[][]{
640
                          {"gb","Qit_PhYq-AI","Penrose Cube Tutorial","Manqube Manish Rathod"},
641
                          {"es","e6q1GwDeqFc","Tutorial del Penrose Cube","Rubiking"},
642
                          {"ru","LeYvajdcizQ","Как собрать Penrose Cube","YG Cuber"},
643
                          {"fr","jrHq_nZuQGk","Résolution du Penrose Cube","asthalis"},
644
                          {"de","P5dck40kTU0","Penrose Cube Tutorial","rofrisch"},
645
                          {"pl","o_c_pIOC6RU","Jak ułożyć kostkę Penrose","Kostki logiczne TV"},
646
                          {"br","6Iz95dtq1dE","Como resolver o Cubo Penrose","Cubo vício"},
647
                          {"kr","uzeoQzkDWM0","펜로즈 큐브","큐브놀이터"},
648
                          {"vn","PjyCCsxJyBU","Hướng dẫn giải Penrose Cube","Rubik Ocean"},
649
                          {"tw","lkzFMKmlB_8","Penrose Cube","不正常魔術方塊研究中心"},
650
                         };
651
    }
652
}
(41-41/59)