Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyCoinTetrahedron.java @ 4cd6a69c

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 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_SPLIT_EDGE_COIN;
14

    
15
import org.distorted.library.helpers.QuatHelper;
16
import org.distorted.library.type.Static3D;
17
import org.distorted.library.type.Static4D;
18
import org.distorted.objectlib.helpers.FactoryCubit;
19
import org.distorted.objectlib.helpers.ObjectFaceShape;
20
import org.distorted.objectlib.helpers.ObjectShape;
21
import org.distorted.objectlib.metadata.Metadata;
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.scrambling.ScrambleEdgeGenerator;
26
import org.distorted.objectlib.shape.ShapeTetrahedron;
27
import org.distorted.objectlib.touchcontrol.TouchControlTetrahedron;
28

    
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30

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

    
41
  private static final int N = 5;
42

    
43
  private int[][] mEdges;
44
  private int[][] mBasicAngle;
45
  private float[][] mCuts;
46
  private float[][] mPosition;
47
  private int[] mQuatIndex;
48
  private boolean[][] mRotatable;
49

    
50
  private float[][] V,M,L;
51

    
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53

    
54
  public TwistyCoinTetrahedron(int iconMode, Static4D quat, Static3D move, float scale, Metadata meta, InitAssets asset)
55
    {
56
    super(iconMode, meta.getNumLayers()[0], quat, move, scale, meta, asset);
57
    }
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

    
61
  @Override
62
  public float[][] returnRotationFactor()
63
    {
64
    float C1 = 1.0f;
65
    float C2 = 1.7f;
66
    float[] f = new float[] { C1,C1,C2 };
67
    return new float[][] { f,f,f,f };
68
    }
69

    
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71

    
72
  @Override
73
  public void adjustStickerCoords()
74
    {
75
    float Y = 0.02f;
76
    float Z = 0.06422593f - 0.25f*Y;
77
    float X = 0.5f - Y;
78

    
79
    float K = 1.00f;
80
    float A = K*0.50f;
81
    float B = K*0.25f;
82
    float C = K*0.43301257f;
83

    
84
    float D = 0.3580885f;
85
    float E = 0.12022744f;
86
    float F = 0.32227963f - 0.015f;
87
    float G = 0.14090173f + 0.01f;
88

    
89
    float H = 0.5f;
90
    float I = 0.0f;
91

    
92
    mStickerCoords = new float[][][][]
93
          {
94
                  { { {-D, E}, { I,-H}, {D, E}, {F, G}, {-F, G} } },
95
                  { { {-C,-B}, { C,-B}, {I, A} } },
96
                  { { {-X, Z}, { X, Z} } }
97
          };
98
    }
99

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

    
102
  @Override
103
  protected float[][][] getStickerStrokes()
104
    {
105
    boolean icon = isInIconMode();
106

    
107
    float S1 = icon ? 0.15f : 0.13f;
108
    float S2 = icon ? 0.15f : 0.07f;
109
    float S3 = icon ? 0.15f : 0.20f;
110

    
111
    return new float[][][] { {{ S1,S1,S1,S1,S1 }} , {{S2,S2,S2}} , {{S3,S3}} };
112
    }
113

    
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115

    
116
  @Override
117
  protected float[][][] getStickerRadii()
118
    {
119
    float R = 0.12f;
120
    return new float[][][] { {{ 0,R,0,0,0 }} , {{0,0,0}} , {{0,0}} };
121
    }
122

    
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124

    
125
  @Override
126
  public int[][] getScrambleAlgorithms()
127
    {
128
    setUpRotatable();
129
    return ScrambleEdgeGenerator.getScramblingAlgorithms(mBasicAngle, mRotatable);
130
    }
131

    
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133

    
134
  public int[][] getScrambleEdges()
135
    {
136
    if( mEdges==null )
137
      {
138
      mEdges = new int[][]
139
          {
140
              { 2,1,3,1, 6,1,7,1, 10,1,11,1, 14,1,15,1}, // tips
141
              { 0,0,1,0, 4,0,5,0,  8,0, 9,0, 12,0,13,0}, // centers
142
          };
143
      }
144

    
145
    return mEdges;
146
    }
147

    
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

    
150
  public float[][] getCuts(int[] numLayers)
151
    {
152
    if( mCuts==null )
153
      {
154
      float[] cut = new float[] { -0.620f,0.600f };
155
      mCuts = new float[][] { cut,cut,cut,cut };
156
      }
157

    
158
    return mCuts;
159
    }
160

    
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

    
163
  private void setUpRotatable()
164
    {
165
    if( mRotatable==null )
166
      {
167
      boolean[] tmp = new boolean[] {true,false,true};
168
      mRotatable = new boolean[][] { tmp,tmp,tmp,tmp };
169
      }
170
    }
171

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

    
174
  public boolean[][] getLayerRotatable(int[] numLayers)
175
    {
176
    setUpRotatable();
177
    return mRotatable;
178
    }
179

    
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181

    
182
  public int getTouchControlType()
183
    {
184
    return TC_TETRAHEDRON;
185
    }
186

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

    
189
  public int getTouchControlSplit()
190
    {
191
    return TYPE_SPLIT_EDGE_COIN;
192
    }
193

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

    
196
  public int[][][] getEnabled()
197
    {
198
    return new int[][][]
199
      {
200
         {{0},{0},{0},{1},{2},{3}},
201
         {{1},{1},{1},{0},{3},{2}},
202
         {{2},{2},{2},{3},{1},{0}},
203
         {{3},{3},{3},{2},{0},{1}}
204
      };
205
    }
206

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

    
209
  public float[] getDist3D(int[] numLayers)
210
    {
211
    return TouchControlTetrahedron.D3D;
212
    }
213

    
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215

    
216
  public Static3D[] getFaceAxis()
217
    {
218
    return TouchControlTetrahedron.FACE_AXIS;
219
    }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

    
223
  private void initVertices()
224
    {
225
    V = new float[][]
226
        {
227
            { 0.0f,-0.75f*SQ2,-1.5f},
228
            { 0.0f,-0.75f*SQ2, 1.5f},
229
            { 1.5f, 0.75f*SQ2, 0.0f},
230
            {-1.5f, 0.75f*SQ2, 0.0f},
231
        };
232

    
233
    M = new float[4][3];
234

    
235
    for(int i=0; i<4; i++)
236
      for(int j=0; j<3; j++)
237
        M[i][j] = (V[0][j]+V[1][j]+V[2][j]+V[3][j]-V[i][j])/3;
238

    
239
    final float B = 0.492f;
240
    L = new float[12][3];
241

    
242
    for(int i=0; i<3; i++)
243
      {
244
      L[ 0][i] = B*V[1][i] + (1-B)*(V[2][i] + V[3][i])/2;
245
      L[ 1][i] = B*V[3][i] + (1-B)*(V[1][i] + V[2][i])/2;
246
      L[ 2][i] = B*V[2][i] + (1-B)*(V[1][i] + V[3][i])/2;
247
      L[ 3][i] = B*V[0][i] + (1-B)*(V[2][i] + V[3][i])/2;
248
      L[ 4][i] = B*V[2][i] + (1-B)*(V[0][i] + V[3][i])/2;
249
      L[ 5][i] = B*V[3][i] + (1-B)*(V[0][i] + V[2][i])/2;
250
      L[ 6][i] = B*V[3][i] + (1-B)*(V[1][i] + V[0][i])/2;
251
      L[ 7][i] = B*V[0][i] + (1-B)*(V[1][i] + V[3][i])/2;
252
      L[ 8][i] = B*V[1][i] + (1-B)*(V[0][i] + V[3][i])/2;
253
      L[ 9][i] = B*V[2][i] + (1-B)*(V[1][i] + V[0][i])/2;
254
      L[10][i] = B*V[0][i] + (1-B)*(V[1][i] + V[2][i])/2;
255
      L[11][i] = B*V[1][i] + (1-B)*(V[0][i] + V[2][i])/2;
256
      }
257
    }
258

    
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260

    
261
  public float[][] getCubitPositions(int[] numLayers)
262
    {
263
    if( mPosition==null )
264
      {
265
      if( V==null ) initVertices();
266

    
267
      float A = -0.016f;
268
      float B =  1.06f;
269
      float[] r0 = new float[] { A*(V[0][0]-M[0][0]), A*(V[0][1]-M[0][1]), A*(V[0][2]-M[0][2]) };
270
      float[] r1 = new float[] { A*(V[1][0]-M[1][0]), A*(V[1][1]-M[1][1]), A*(V[1][2]-M[1][2]) };
271
      float[] r2 = new float[] { A*(V[2][0]-M[2][0]), A*(V[2][1]-M[2][1]), A*(V[2][2]-M[2][2]) };
272
      float[] r3 = new float[] { A*(V[3][0]-M[3][0]), A*(V[3][1]-M[3][1]), A*(V[3][2]-M[3][2]) };
273

    
274
      mPosition = new float[][]
275
         {
276
             {V[1][0],V[1][1],V[1][2]},
277
             {V[0][0],V[0][1],V[0][2]},
278
             {V[2][0],V[2][1],V[2][2]},
279
             {V[3][0],V[3][1],V[3][2]},
280

    
281
             {B*M[0][0],B*M[0][1],B*M[0][2]},
282
             {B*M[1][0],B*M[1][1],B*M[1][2]},
283
             {B*M[2][0],B*M[2][1],B*M[2][2]},
284
             {B*M[3][0],B*M[3][1],B*M[3][2]},
285

    
286
             {L[ 0][0] +r0[0],L[ 0][1] +r0[1],L[ 0][2] +r0[2]},
287
             {L[ 1][0] +r0[0],L[ 1][1] +r0[1],L[ 1][2] +r0[2]},
288
             {L[ 2][0] +r0[0],L[ 2][1] +r0[1],L[ 2][2] +r0[2]},
289
             {L[ 3][0] +r1[0],L[ 3][1] +r1[1],L[ 3][2] +r1[2]},
290
             {L[ 4][0] +r1[0],L[ 4][1] +r1[1],L[ 4][2] +r1[2]},
291
             {L[ 5][0] +r1[0],L[ 5][1] +r1[1],L[ 5][2] +r1[2]},
292
             {L[ 6][0] +r2[0],L[ 6][1] +r2[1],L[ 6][2] +r2[2]},
293
             {L[ 7][0] +r2[0],L[ 7][1] +r2[1],L[ 7][2] +r2[2]},
294
             {L[ 8][0] +r2[0],L[ 8][1] +r2[1],L[ 8][2] +r2[2]},
295
             {L[ 9][0] +r3[0],L[ 9][1] +r3[1],L[ 9][2] +r3[2]},
296
             {L[10][0] +r3[0],L[10][1] +r3[1],L[10][2] +r3[2]},
297
             {L[11][0] +r3[0],L[11][1] +r3[1],L[11][2] +r3[2]},
298
         };
299
      }
300

    
301
    return mPosition;
302
    }
303

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

    
306
  public Static4D getCubitQuats(int cubit, int[] numLayers)
307
    {
308
    if( mQuatIndex==null ) mQuatIndex = new int[] {0,6,1,2,
309
                                                   0,5,4,3,
310
                                                   0,2,1,10,8,5,11,7,4,9,6,3 };
311
    return mObjectQuats[mQuatIndex[cubit]];
312
    }
313

    
314
///////////////////////////////////////////////////////////////////////////////////////////////////
315

    
316
  private float[] rotateVertices(float angle, float[] vector, float[] center, float[] rotAxis)
317
    {
318
    float[] ret = new float[4];
319
    float sin = (float)Math.sin(angle/2);
320
    float cos = (float)Math.cos(angle/2);
321
    float[] quat= new float[] { sin*rotAxis[0], sin*rotAxis[1], sin*rotAxis[2], cos};
322
    QuatHelper.rotateVectorByQuat(ret,vector,quat);
323

    
324
    ret[0] += center[0];
325
    ret[1] += center[1];
326
    ret[2] += center[2];
327

    
328
    return ret;
329
    }
330

    
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332

    
333
  private void normalize(float[] v)
334
    {
335
    float len = (float)Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
336
    v[0] /= len;
337
    v[1] /= len;
338
    v[2] /= len;
339
    }
340

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

    
343
  private float[][] produceCorner()
344
    {
345
    float[][] ret = new float[5 + 3*(N+1) +3][];
346

    
347
    float C = 0.50f;
348
    ret[0] = new float[] { 0.00f,   0.0f     ,   0.00f };
349
    ret[1] = new float[] { 0.00f,   0.0f     ,  -1.50f };
350
    ret[2] = new float[] { 0.75f,   0.75f*SQ2,  -0.75f };
351
    ret[3] = new float[] {-0.75f,   0.75f*SQ2,  -0.75f };
352
    ret[4] = new float[] { 0.00f, C*0.75f*SQ2,C*-1.50f };
353

    
354
    float[] vect1 = new float[4];
355
    float[] vect2 = new float[4];
356
    float[] vect3 = new float[4];
357

    
358
    float G = 0.94f;
359

    
360
    for(int i=0; i<3; i++)
361
      {
362
      vect1[i] = -G*M[0][i] + G*(V[1][i]+V[3][i])/2;
363
      vect2[i] = -G*M[3][i] + G*(V[1][i]+V[2][i])/2;
364
      vect3[i] = -G*M[2][i] + G*(V[0][i]+V[1][i])/2;
365
      }
366

    
367
    float[] rot1 = new float[] { V[0][0]-M[0][0], V[0][1]-M[0][1], V[0][2]-M[0][2] };
368
    float[] rot2 = new float[] { V[3][0]-M[3][0], V[3][1]-M[3][1], V[3][2]-M[3][2] };
369
    float[] rot3 = new float[] { V[2][0]-M[2][0], V[2][1]-M[2][1], V[2][2]-M[2][2] };
370

    
371
    normalize(rot1);
372
    normalize(rot2);
373
    normalize(rot3);
374

    
375
    float[] center1 = { M[0][0]-V[1][0], M[0][1]-V[1][1], M[0][2]-V[1][2] };
376
    float[] center2 = { M[3][0]-V[1][0], M[3][1]-V[1][1], M[3][2]-V[1][2] };
377
    float[] center3 = { M[2][0]-V[1][0], M[2][1]-V[1][1], M[2][2]-V[1][2] };
378

    
379
    for(int i=0; i<N+1; i++)
380
      {
381
      float angle = (float)(2*Math.PI/3)*i/N;
382

    
383
      ret[5        +i] = rotateVertices(angle,vect1,center1,rot1);
384
      ret[5+   N+1 +i] = rotateVertices(angle,vect2,center2,rot2);
385
      ret[5+2*(N+1)+i] = rotateVertices(angle,vect3,center3,rot3);
386
      }
387

    
388
    float B = 0.85f;
389
    ret[ 5 + 3*(N+1)  ] = new float[] { ret[0][0]*B + ret[1][0]*(1-B), ret[0][1]*B + ret[1][1]*(1-B), ret[0][2]*B + ret[1][2]*(1-B) };
390
    ret[ 5 + 3*(N+1)+1] = new float[] { ret[0][0]*B + ret[2][0]*(1-B), ret[0][1]*B + ret[2][1]*(1-B), ret[0][2]*B + ret[2][2]*(1-B) };
391
    ret[ 5 + 3*(N+1)+2] = new float[] { ret[0][0]*B + ret[3][0]*(1-B), ret[0][1]*B + ret[3][1]*(1-B), ret[0][2]*B + ret[3][2]*(1-B) };
392

    
393
    return ret;
394
    }
395

    
396
///////////////////////////////////////////////////////////////////////////////////////////////////
397

    
398
  private float[][] produceCenter()
399
    {
400
    final float D = 0.96f;
401
    float[][] ret = new float[3*N+1][];
402

    
403
    float[] rot = new float[] { V[0][0]-M[0][0], V[0][1]-M[0][1], V[0][2]-M[0][2] };
404
    normalize(rot);
405

    
406
    float[] center1 = {   0.0f,-D*SQ2  , D  };
407
    float[] center2 = { D*1.5f, D*SQ2/2,-D/2};
408
    float[] center3 = {-D*1.5f, D*SQ2/2,-D/2};
409

    
410
    float[] vect1 = {  D*0.75f, D*0.75f*SQ2, -D*0.75f, 0.0f };
411
    float[] vect2 = { -D*1.50f,   0.00f    ,    0.00f, 0.0f };
412
    float[] vect3 = {  D*0.75f,-D*0.75f*SQ2,  D*0.75f, 0.0f };
413

    
414
    for(int i=0; i<N; i++)
415
      {
416
      float angle = (float)(Math.PI/3)*i/N;
417

    
418
      ret[  N-1-i] = rotateVertices(angle, vect1, center1, rot);
419
      ret[2*N-1-i] = rotateVertices(angle, vect2, center2, rot);
420
      ret[3*N-1-i] = rotateVertices(angle, vect3, center3, rot);
421
      }
422

    
423
    ret[3*N] = new float[] { 0.0f, -SQ2/4, -0.5f };
424

    
425
    return ret;
426
    }
427

    
428
///////////////////////////////////////////////////////////////////////////////////////////////////
429

    
430
  private float[][] produceLeaf()
431
    {
432
    float[][] ret = new float[2*N+1][];
433

    
434
    float[] rot = new float[] { V[0][0]-M[0][0], V[0][1]-M[0][1], V[0][2]-M[0][2] };
435
    normalize(rot);
436

    
437
    float[] center1 = { 0.0f, -0.75f*SQ2, 0.75f };
438
    float[] center2 = { 0.0f,  0.25f*SQ2,-0.25f };
439

    
440
    float[] vect1 = {  0.75f, 0.75f*SQ2, -0.75f, 0.0f };
441
    float[] vect2 = new float[4];
442
    for(int i=0; i<3; i++) vect2[i] = -M[0][i] + (V[1][i]+V[3][i])/2;
443

    
444
    final float G = 0.95f;
445

    
446
    for(int i=0; i<N; i++)
447
      {
448
      float angle1 = (float)(  Math.PI/3)*i/N;
449
      float angle2 = (float)(2*Math.PI/3)*i/N;
450

    
451
      ret[  N-1-i] = rotateVertices(angle1, vect1, center1, rot);
452
      ret[2*N-1-i] = rotateVertices(angle2, vect2, center2, rot);
453

    
454
      float[] tmp = ret[N-1-i];
455
      tmp[0]*=G;
456
      tmp[1]*=G;
457
      tmp[2]*=G;
458
      tmp = ret[2*N-1-i];
459
      tmp[0]*=G;
460
      tmp[1]*=G;
461
      tmp[2]*=G;
462
      }
463

    
464
    ret[2*N] = new float[] { 0.0f, -0.75f*SQ2/10, -1.5f/10 };
465

    
466
    return ret;
467
    }
468

    
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470

    
471
  private float[][] getVertices(int variant)
472
    {
473
         if( variant==0 ) return produceCorner();
474
    else if( variant==1 ) return produceCenter();
475
    else                  return produceLeaf();
476
    }
477

    
478
///////////////////////////////////////////////////////////////////////////////////////////////////
479

    
480
  private int[][] produceCornerShape()
481
    {
482
    int[][] ret = new int[9+3*N+3][];
483

    
484
    ret[0] = new int[N+4];
485
    ret[0][0] = 3;
486
    ret[0][1] = 0;
487
    ret[0][2] = 2;
488
    for(int i=0; i<N+1; i++) ret[0][3+i] = 5+N-i;
489

    
490
    ret[1] = new int[N+4];
491
    ret[1][0] = 2;
492
    ret[1][1] = 0;
493
    ret[1][2] = 1;
494
    for(int i=0; i<N+1; i++) ret[1][3+i] = 6+2*N-i;
495

    
496
    ret[2] = new int[N+4];
497
    ret[2][0] = 1;
498
    ret[2][1] = 0;
499
    ret[2][2] = 3;
500
    for(int i=0; i<N+1; i++) ret[2][3+i] = 7+3*N-i;
501

    
502
    ret[3] = new int[] {5+  N,2    , 4 };
503
    ret[4] = new int[] {2    ,6+  N, 4 };
504
    ret[5] = new int[] {6+2*N,1    , 4 };
505
    ret[6] = new int[] {1    ,7+2*N, 4 };
506
    ret[7] = new int[] {7+3*N,3    , 4 };
507
    ret[8] = new int[] {3    ,5    , 4 };
508

    
509
    for(int i=0; i<N; i++)
510
      {
511
      ret[9+    i] = new int[] {5    +i, 6    +i, 4};
512
      ret[9+  N+i] = new int[] {6+  N+i, 7+  N+i, 4};
513
      ret[9+2*N+i] = new int[] {7+2*N+i, 8+2*N+i, 4};
514
      }
515

    
516
    ret[3*N+ 9] = new int[] { 3*N+8, 3*N+ 9, 3 };
517
    ret[3*N+10] = new int[] { 3*N+9, 3*N+10, 1 };
518
    ret[3*N+11] = new int[] { 3*N+8, 3*N+10, 2 };
519

    
520
    return ret;
521
    }
522

    
523
///////////////////////////////////////////////////////////////////////////////////////////////////
524

    
525
  private int[][] produceCenterShape()
526
    {
527
    int[][] ret = new int[3+3*(N-1)+1][];
528

    
529
    ret[0] = new int[3*N];
530
    for(int i=0; i<3*N; i++) ret[0][i] = i;
531

    
532
    for(int i=1; i<=N-1; i++)
533
      {
534
      ret[i] = new int[3];
535
      ret[i][0] = 3*N;
536
      ret[i][1] = i;
537
      ret[i][2] = i-1;
538

    
539
      ret[N-1+i] = new int[3];
540
      ret[N-1+i][0] = 3*N;
541
      ret[N-1+i][1] = N+i;
542
      ret[N-1+i][2] = N+i-1;
543

    
544
      ret[2*N-2+i] = new int[3];
545
      ret[2*N-2+i][0] = 3*N;
546
      ret[2*N-2+i][1] = 2*N+i;
547
      ret[2*N-2+i][2] = 2*N+i-1;
548
      }
549

    
550
    ret[3*N-2] = new int[] {   N-1,   N, 3*N };
551
    ret[3*N-1] = new int[] { 2*N-1, 2*N, 3*N };
552
    ret[3*N  ] = new int[] { 3*N-1,   0, 3*N };
553

    
554
    return ret;
555
    }
556

    
557
///////////////////////////////////////////////////////////////////////////////////////////////////
558

    
559
  private int[][] produceLeafShape()
560
    {
561
    int[][] ret = new int[2+2*(N-1)+1][];
562

    
563
    ret[0] = new int[2*N];
564
    for(int i=0; i<2*N; i++) ret[0][i] = 2*N-1-i;
565

    
566
    for(int i=1; i<=N-1; i++)
567
      {
568
      ret[i] = new int[3];
569
      ret[i][0] = i;
570
      ret[i][1] = i-1;
571
      ret[i][2] = 2*N;
572

    
573
      ret[N-1+i] = new int[3];
574
      ret[N-1+i][0] = N+i;
575
      ret[N-1+i][1] = N+i-1;
576
      ret[N-1+i][2] = 2*N;
577
      }
578

    
579
    ret[2*N-1] = new int[] { N,  N-1, 2*N };
580
    ret[2*N  ] = new int[] { 0,2*N-1, 2*N };
581

    
582
    return ret;
583
    }
584

    
585
///////////////////////////////////////////////////////////////////////////////////////////////////
586

    
587
  public ObjectShape getObjectShape(int variant)
588
    {
589
    if( variant==0 )
590
      {
591
      int[][] indices = produceCornerShape();
592
      return new ObjectShape(getVertices(variant), indices);
593
      }
594
    else if( variant==1 )
595
      {
596
      int[][] indices = produceCenterShape();
597
      return new ObjectShape(getVertices(variant), indices);
598
      }
599
    else
600
      {
601
      int[][] indices = produceLeafShape();
602
      return new ObjectShape(getVertices(variant), indices);
603
      }
604
    }
605

    
606
///////////////////////////////////////////////////////////////////////////////////////////////////
607

    
608
  public ObjectFaceShape getObjectFaceShape(int variant)
609
    {
610
    if( variant==0 )
611
      {
612
      float h1 = isInIconMode() ? 0.0001f : 0.03f;
613
      float h2 = isInIconMode() ? 0.0001f : 0.01f;
614
      float[][] bands = { {h1,35,0.2f,0.4f,5,2,1}, {h2,35,0.2f,0.4f,2,0,0} };
615
      int num = 9+3*N+3;
616
      int[] indices   = new int[num];
617
      for(int i=3; i<num; i++) indices[i] = 1;
618
      float A = 0.5f;
619
      float[] convexCenter = { 0.0f*A, 0.75f*SQ2*A, -1.50f*A};
620
      return new ObjectFaceShape(bands,indices,convexCenter);
621
      }
622
    else if( variant==1 )
623
      {
624
      float h = isInIconMode() ? 0.0001f : 0.01f;
625
      float[][] bands = { {h,25,0.05f,0.1f,5,0,0}, {h,25,0.05f,0.1f,2,0,0} };
626
      int num = 3+3*(N-1)+1;
627
      int[] indices   = new int[num];
628
      for(int i=1; i<num; i++) indices[i] = 1;
629
      return new ObjectFaceShape(bands,indices,null);
630
      }
631
    else
632
      {
633
      float h1 = isInIconMode() ? 0.0001f : 0.01f;
634
      float h2 = isInIconMode() ? 0.0001f : 0.01f;
635
      float[][] bands = { {h1,35,0.30f,0.5f,5,0,0}, {h2,25,0.125f,0.2f,2,0,0} };
636
      int num = 2+2*(N-1)+1;
637
      int[] indices   = new int[num];
638
      for(int i=1; i<num; i++) indices[i] = 1;
639
      return new ObjectFaceShape(bands,indices,null);
640
      }
641
    }
642

    
643
///////////////////////////////////////////////////////////////////////////////////////////////////
644

    
645
  public ObjectVertexEffects getVertexEffects(int variant)
646
    {
647
    if( variant==0 )
648
      {
649
      float[][] corners = { {0.05f,0.20f} };
650
      int num = 5 + 3*(N+1) + 3;
651
      int[] indices     = new int[num];
652
      for(int i=1; i<num; i++) indices[i] = -1;
653
      float[][] centers = { { 0.00f, 0.75f*SQ2,-1.50f} };
654
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
655
      }
656
    else if( variant==1 )
657
      {
658
      float[][] corners = { {0.02f,0.20f} };
659
      int[] indices     = new int[3*N+1];
660
      for(int i=0; i<3*N+1; i++) indices[i] = -1;
661
      indices[  N-1] = 0;
662
      indices[2*N-1] = 0;
663
      indices[3*N-1] = 0;
664

    
665
      float[][] centers = { { 0.0f, -SQ2/4, -0.5f } };
666
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
667
      }
668
    else
669
      {
670
      float[][] corners = { {0.017f,0.10f} };
671
      int[] indices     = new int[2*N+1];
672
      for(int i=0; i<2*N+1; i++) indices[i] = -1;
673
      indices[  N-1] = 0;
674
      indices[2*N-1] = 0;
675

    
676
      float A = 10;
677
      float[][] centers = { { 0.0f, A*-0.75f*SQ2/10, A*-1.5f/10 } };
678
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
679
      }
680
    }
681

    
682
///////////////////////////////////////////////////////////////////////////////////////////////////
683

    
684
  public int getNumCubitVariants(int[] numLayers)
685
    {
686
    return 3;
687
    }
688

    
689
///////////////////////////////////////////////////////////////////////////////////////////////////
690

    
691
  public int getCubitVariant(int cubit, int[] numLayers)
692
    {
693
    return cubit<4 ? 0 : (cubit<8 ? 1:2);
694
    }
695

    
696
///////////////////////////////////////////////////////////////////////////////////////////////////
697
// doesn't matter, we're overriding getStickerRadii() anyway
698

    
699
  public float getStickerRadius()
700
    {
701
    return 0.0f;
702
    }
703

    
704
///////////////////////////////////////////////////////////////////////////////////////////////////
705
// doesn't matter, we're overriding getStickerStrokes() anyway
706

    
707
  public float getStickerStroke()
708
    {
709
    return 0.0f;
710
    }
711

    
712
///////////////////////////////////////////////////////////////////////////////////////////////////
713

    
714
  public float[][][] getStickerAngles()
715
    {
716
    float D1 = (float)(2*Math.PI/3);
717
    float D2 = (float)(Math.PI/3);
718
    return new float[][][] { {{ 0,0,0,-D1,0 }} , {{-D2,-D2,-D2}} , {{D1,D2}} };
719
    }
720

    
721
///////////////////////////////////////////////////////////////////////////////////////////////////
722
// PUBLIC API
723

    
724
  public Static3D[] getRotationAxis()
725
    {
726
    return ROT_AXIS;
727
    }
728

    
729
///////////////////////////////////////////////////////////////////////////////////////////////////
730

    
731
  public int[][] getBasicAngles()
732
    {
733
    if( mBasicAngle ==null )
734
      {
735
      int[] tmp = {3,3,3};
736
      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
737
      }
738

    
739
    return mBasicAngle;
740
    }
741

    
742
///////////////////////////////////////////////////////////////////////////////////////////////////
743

    
744
  public String getShortName()
745
    {
746
    return ListObjects.COIN_3.name();
747
    }
748

    
749
///////////////////////////////////////////////////////////////////////////////////////////////////
750

    
751
  public String[][] getTutorials()
752
    {
753
    return new String[][] {
754
                          {"gb","2WrDNfcfpAg","Coin Pyraminx Tutorial","Brent Richter"},
755
                          {"es","5pTfSCsHPWs","Tutorial Coin Pyraminx","Kubekings"},
756
                          {"ru","qUMQsn8kg1A","Как собрать Коин Пираминкс","Алексей Ярыгин"},
757
                          {"vn","TOaiOcEE0lk","Hướng Dẫn Giải Pyraminx Coin","Rubik Cube"},
758
                          {"tw","ofVag-kYgQ4","圓盤金字塔 ","1hrBLD"},
759
                         };
760
    }
761
}
(10-10/59)