Project

General

Profile

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

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

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.helpers.ObjectSignature;
22
import org.distorted.objectlib.helpers.ObjectVertexEffects;
23
import org.distorted.objectlib.main.InitAssets;
24
import org.distorted.objectlib.main.InitData;
25
import org.distorted.objectlib.main.ObjectSignatures;
26
import org.distorted.objectlib.main.ObjectType;
27
import org.distorted.objectlib.scrambling.ScrambleEdgeGenerator;
28
import org.distorted.objectlib.shape.ShapeTetrahedron;
29
import org.distorted.objectlib.touchcontrol.TouchControlTetrahedron;
30

    
31
///////////////////////////////////////////////////////////////////////////////////////////////////
32

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

    
43
  private static final int N = 5;
44
  private static final float D = 0.9f;
45

    
46
  private int[][] mEdges;
47
  private int[][] mBasicAngle;
48
  private float[][] mCuts;
49
  private float[][] mPosition;
50
  private int[] mQuatIndex;
51
  private boolean[][] mRotatable;
52

    
53
  private float[][] V,M,L;
54

    
55
///////////////////////////////////////////////////////////////////////////////////////////////////
56

    
57
  public TwistyCoinTetrahedron(int meshState, int iconMode, Static4D quat, Static3D move, float scale, InitData data, InitAssets asset)
58
    {
59
    super(meshState, iconMode, data.getNumLayers()[0], quat, move, scale, data, asset);
60
    }
61

    
62
///////////////////////////////////////////////////////////////////////////////////////////////////
63

    
64
  public int[][] getScrambleEdges()
65
    {
66
    if( mEdges==null )
67
      {
68
      setUpRotatable();
69
      mEdges = ScrambleEdgeGenerator.getScrambleEdgesSingle(mBasicAngle, mRotatable);
70
      }
71

    
72
    return mEdges;
73
    }
74

    
75
///////////////////////////////////////////////////////////////////////////////////////////////////
76

    
77
  @Override
78
  public int[][] getScrambleAlgorithms()
79
    {
80
    setUpRotatable();
81
    return ScrambleEdgeGenerator.getScramblingAlgorithms(mBasicAngle, mRotatable);
82
    }
83

    
84
///////////////////////////////////////////////////////////////////////////////////////////////////
85

    
86
  public float[][] getCuts(int[] numLayers)
87
    {
88
    if( mCuts==null )
89
      {
90
      float[] cut = new float[] { -0.620f,0.621f };
91
      mCuts = new float[][] { cut,cut,cut,cut };
92
      }
93

    
94
    return mCuts;
95
    }
96

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

    
99
  private void setUpRotatable()
100
    {
101
    if( mRotatable==null )
102
      {
103
      boolean[] tmp = new boolean[] {true,false,true};
104
      mRotatable = new boolean[][] { tmp,tmp,tmp,tmp };
105
      }
106
    }
107

    
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109

    
110
  public boolean[][] getLayerRotatable(int[] numLayers)
111
    {
112
    setUpRotatable();
113
    return mRotatable;
114
    }
115

    
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117

    
118
  public int getTouchControlType()
119
    {
120
    return TC_TETRAHEDRON;
121
    }
122

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

    
125
  public int getTouchControlSplit()
126
    {
127
    return TYPE_SPLIT_EDGE_COIN;
128
    }
129

    
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131

    
132
  public int[][][] getEnabled()
133
    {
134
    return new int[][][]
135
      {
136
         {{0},{0},{0},{1},{2},{3}},
137
         {{1},{1},{1},{0},{3},{2}},
138
         {{2},{2},{2},{3},{1},{0}},
139
         {{3},{3},{3},{2},{0},{1}}
140
      };
141
    }
142

    
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144

    
145
  public float[] getDist3D(int[] numLayers)
146
    {
147
    return TouchControlTetrahedron.D3D;
148
    }
149

    
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

    
152
  public Static3D[] getFaceAxis()
153
    {
154
    return TouchControlTetrahedron.FACE_AXIS;
155
    }
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158

    
159
  private void initVertices()
160
    {
161
    V = new float[][]
162
        {
163
            { 0.0f,-0.75f*SQ2,-1.5f},
164
            { 0.0f,-0.75f*SQ2, 1.5f},
165
            { 1.5f, 0.75f*SQ2, 0.0f},
166
            {-1.5f, 0.75f*SQ2, 0.0f},
167
        };
168

    
169
    float A = 1.06f;
170
    M = new float[4][3];
171

    
172
    for(int i=0; i<4; i++)
173
      for(int j=0; j<3; j++)
174
        M[i][j] = A*(V[0][j]+V[1][j]+V[2][j]+V[3][j]-V[i][j])/3;
175

    
176
    L = new float[12][3];
177

    
178
    for(int i=0; i<3; i++)
179
      {
180
      L[ 0][i] = 0.5f*V[1][i] + 0.25f*V[2][i] + 0.25f*V[3][i];
181
      L[ 1][i] = 0.5f*V[3][i] + 0.25f*V[1][i] + 0.25f*V[2][i];
182
      L[ 2][i] = 0.5f*V[2][i] + 0.25f*V[1][i] + 0.25f*V[3][i];
183
      L[ 3][i] = 0.5f*V[0][i] + 0.25f*V[2][i] + 0.25f*V[3][i];
184
      L[ 4][i] = 0.5f*V[2][i] + 0.25f*V[0][i] + 0.25f*V[3][i];
185
      L[ 5][i] = 0.5f*V[3][i] + 0.25f*V[0][i] + 0.25f*V[2][i];
186
      L[ 6][i] = 0.5f*V[3][i] + 0.25f*V[1][i] + 0.25f*V[0][i];
187
      L[ 7][i] = 0.5f*V[0][i] + 0.25f*V[1][i] + 0.25f*V[3][i];
188
      L[ 8][i] = 0.5f*V[1][i] + 0.25f*V[0][i] + 0.25f*V[3][i];
189
      L[ 9][i] = 0.5f*V[2][i] + 0.25f*V[1][i] + 0.25f*V[0][i];
190
      L[10][i] = 0.5f*V[0][i] + 0.25f*V[1][i] + 0.25f*V[2][i];
191
      L[11][i] = 0.5f*V[1][i] + 0.25f*V[0][i] + 0.25f*V[2][i];
192
      }
193
    }
194

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

    
197
  public float[][] getCubitPositions(int[] numLayers)
198
    {
199
    if( mPosition==null )
200
      {
201
      if( V==null ) initVertices();
202

    
203
      float A = -0.016f;
204
      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]) };
205
      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]) };
206
      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]) };
207
      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]) };
208

    
209
      mPosition = new float[][]
210
         {
211
             {V[1][0],V[1][1],V[1][2]},
212
             {V[0][0],V[0][1],V[0][2]},
213
             {V[2][0],V[2][1],V[2][2]},
214
             {V[3][0],V[3][1],V[3][2]},
215

    
216
             {M[0][0],M[0][1],M[0][2]},
217
             {M[1][0],M[1][1],M[1][2]},
218
             {M[2][0],M[2][1],M[2][2]},
219
             {M[3][0],M[3][1],M[3][2]},
220

    
221
             {L[ 0][0] +r0[0],L[ 0][1] +r0[1],L[ 0][2] +r0[2]},
222
             {L[ 1][0] +r0[0],L[ 1][1] +r0[1],L[ 1][2] +r0[2]},
223
             {L[ 2][0] +r0[0],L[ 2][1] +r0[1],L[ 2][2] +r0[2]},
224
             {L[ 3][0] +r1[0],L[ 3][1] +r1[1],L[ 3][2] +r1[2]},
225
             {L[ 4][0] +r1[0],L[ 4][1] +r1[1],L[ 4][2] +r1[2]},
226
             {L[ 5][0] +r1[0],L[ 5][1] +r1[1],L[ 5][2] +r1[2]},
227
             {L[ 6][0] +r2[0],L[ 6][1] +r2[1],L[ 6][2] +r2[2]},
228
             {L[ 7][0] +r2[0],L[ 7][1] +r2[1],L[ 7][2] +r2[2]},
229
             {L[ 8][0] +r2[0],L[ 8][1] +r2[1],L[ 8][2] +r2[2]},
230
             {L[ 9][0] +r3[0],L[ 9][1] +r3[1],L[ 9][2] +r3[2]},
231
             {L[10][0] +r3[0],L[10][1] +r3[1],L[10][2] +r3[2]},
232
             {L[11][0] +r3[0],L[11][1] +r3[1],L[11][2] +r3[2]},
233
         };
234
      }
235

    
236
    return mPosition;
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

    
241
  public Static4D getCubitQuats(int cubit, int[] numLayers)
242
    {
243
    if( mQuatIndex==null ) mQuatIndex = new int[] {0,6,1,2,
244
                                                   0,5,4,3,
245
                                                   0,2,1,10,8,5,11,7,4,9,6,3 };
246
    return mObjectQuats[mQuatIndex[cubit]];
247
    }
248

    
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250

    
251
  private float[] rotateVertices(float angle, float[] vector, float[] center, float[] rotAxis)
252
    {
253
    float[] ret = new float[4];
254
    float sin = (float)Math.sin(angle/2);
255
    float cos = (float)Math.cos(angle/2);
256
    float[] quat= new float[] { sin*rotAxis[0], sin*rotAxis[1], sin*rotAxis[2], cos};
257
    QuatHelper.rotateVectorByQuat(ret,vector,quat);
258

    
259
    ret[0] += center[0];
260
    ret[1] += center[1];
261
    ret[2] += center[2];
262

    
263
    return ret;
264
    }
265

    
266
///////////////////////////////////////////////////////////////////////////////////////////////////
267

    
268
  private void normalize(float[] v)
269
    {
270
    float len = (float)Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
271
    v[0] /= len;
272
    v[1] /= len;
273
    v[2] /= len;
274
    }
275

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

    
278
  private float[][] produceCorner()
279
    {
280
    float[][] ret = new float[5 + 3*(N+1) +3][];
281

    
282
    float C = 0.97f;
283
    ret[0] = new float[] { 0.00f,   0.0f     ,   0.00f };
284
    ret[1] = new float[] { 0.00f,   0.0f     ,  -1.50f };
285
    ret[2] = new float[] { 0.75f,   0.75f*SQ2,  -0.75f };
286
    ret[3] = new float[] {-0.75f,   0.75f*SQ2,  -0.75f };
287
    ret[4] = new float[] { 0.00f, C*0.75f*SQ2,C*-1.50f };
288

    
289
    float[] vect1 = new float[4];
290
    float[] vect2 = new float[4];
291
    float[] vect3 = new float[4];
292

    
293
    for(int i=0; i<3; i++)
294
      {
295
      vect1[i] = -D*M[0][i] + D*(V[1][i]+V[3][i])/2;
296
      vect2[i] = -D*M[3][i] + D*(V[1][i]+V[2][i])/2;
297
      vect3[i] = -D*M[2][i] + D*(V[0][i]+V[1][i])/2;
298
      }
299

    
300
    float[] rot1 = new float[] { V[0][0]-M[0][0], V[0][1]-M[0][1], V[0][2]-M[0][2] };
301
    float[] rot2 = new float[] { V[3][0]-M[3][0], V[3][1]-M[3][1], V[3][2]-M[3][2] };
302
    float[] rot3 = new float[] { V[2][0]-M[2][0], V[2][1]-M[2][1], V[2][2]-M[2][2] };
303

    
304
    normalize(rot1);
305
    normalize(rot2);
306
    normalize(rot3);
307

    
308
    float[] center1 = { M[0][0]-V[1][0], M[0][1]-V[1][1], M[0][2]-V[1][2] };
309
    float[] center2 = { M[3][0]-V[1][0], M[3][1]-V[1][1], M[3][2]-V[1][2] };
310
    float[] center3 = { M[2][0]-V[1][0], M[2][1]-V[1][1], M[2][2]-V[1][2] };
311

    
312
    for(int i=0; i<N+1; i++)
313
      {
314
      float angle = (float)(2*Math.PI/3)*i/N;
315

    
316
      ret[5        +i] = rotateVertices(angle,vect1,center1,rot1);
317
      ret[5+   N+1 +i] = rotateVertices(angle,vect2,center2,rot2);
318
      ret[5+2*(N+1)+i] = rotateVertices(angle,vect3,center3,rot3);
319
      }
320

    
321
    float B = 0.85f;
322
    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) };
323
    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) };
324
    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) };
325

    
326
    return ret;
327
    }
328

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

    
331
  private float[][] produceCenter()
332
    {
333
    float[][] ret = new float[3*N+1][];
334

    
335
    float[] rot = new float[] { V[0][0]-M[0][0], V[0][1]-M[0][1], V[0][2]-M[0][2] };
336
    normalize(rot);
337

    
338
    float[] center1 = {   0.0f,-D*SQ2  , D  };
339
    float[] center2 = { D*1.5f, D*SQ2/2,-D/2};
340
    float[] center3 = {-D*1.5f, D*SQ2/2,-D/2};
341

    
342
    float[] vect1 = {  D*0.75f, D*0.75f*SQ2, -D*0.75f, 0.0f };
343
    float[] vect2 = { -D*1.50f,   0.00f    ,    0.00f, 0.0f };
344
    float[] vect3 = {  D*0.75f,-D*0.75f*SQ2,  D*0.75f, 0.0f };
345

    
346
    for(int i=0; i<N; i++)
347
      {
348
      float angle = (float)(Math.PI/3)*i/N;
349

    
350
      ret[  N-1-i] = rotateVertices(angle, vect1, center1, rot);
351
      ret[2*N-1-i] = rotateVertices(angle, vect2, center2, rot);
352
      ret[3*N-1-i] = rotateVertices(angle, vect3, center3, rot);
353
      }
354

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

    
357
    return ret;
358
    }
359

    
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361

    
362
  private float[][] produceLeaf()
363
    {
364
    float[][] ret = new float[2*N+1][];
365

    
366
    float[] rot = new float[] { V[0][0]-M[0][0], V[0][1]-M[0][1], V[0][2]-M[0][2] };
367
    normalize(rot);
368

    
369
    float[] center1 = { 0.0f, -D*0.75f*SQ2, D*0.75f };
370
    float[] center2 = { 0.0f,    0.25f*SQ2,  -0.25f };
371

    
372
    float[] vect1 = {  D*0.75f, D*0.75f*SQ2, -D*0.75f, 0.0f };
373
    float[] vect2 = new float[4];
374
    for(int i=0; i<3; i++) vect2[i] = -D*M[0][i] + D*(V[1][i]+V[3][i])/2;
375

    
376
    for(int i=0; i<N; i++)
377
      {
378
      float angle1 = (float)(  Math.PI/3)*i/N;
379
      float angle2 = (float)(2*Math.PI/3)*i/N;
380

    
381
      ret[  N-1-i] = rotateVertices(angle1, vect1, center1, rot);
382
      ret[2*N-1-i] = rotateVertices(angle2, vect2, center2, rot);
383
      }
384

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

    
387
    return ret;
388
    }
389

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

    
392
  private float[][] getVertices(int variant)
393
    {
394
         if( variant==0 ) return produceCorner();
395
    else if( variant==1 ) return produceCenter();
396
    else                  return produceLeaf();
397
    }
398

    
399
///////////////////////////////////////////////////////////////////////////////////////////////////
400

    
401
  private int[][] produceCornerShape()
402
    {
403
    int[][] ret = new int[9+3*N+3][];
404

    
405
    ret[0] = new int[N+4];
406
    ret[0][0] = 3;
407
    ret[0][1] = 0;
408
    ret[0][2] = 2;
409
    for(int i=0; i<N+1; i++) ret[0][3+i] = 5+N-i;
410

    
411
    ret[1] = new int[N+4];
412
    ret[1][0] = 2;
413
    ret[1][1] = 0;
414
    ret[1][2] = 1;
415
    for(int i=0; i<N+1; i++) ret[1][3+i] = 6+2*N-i;
416

    
417
    ret[2] = new int[N+4];
418
    ret[2][0] = 1;
419
    ret[2][1] = 0;
420
    ret[2][2] = 3;
421
    for(int i=0; i<N+1; i++) ret[2][3+i] = 7+3*N-i;
422

    
423
    ret[3] = new int[] {5+  N,2    , 4 };
424
    ret[4] = new int[] {2    ,6+  N, 4 };
425
    ret[5] = new int[] {6+2*N,1    , 4 };
426
    ret[6] = new int[] {1    ,7+2*N, 4 };
427
    ret[7] = new int[] {7+3*N,3    , 4 };
428
    ret[8] = new int[] {3    ,5    , 4 };
429

    
430
    for(int i=0; i<N; i++)
431
      {
432
      ret[9+    i] = new int[] {5    +i, 6    +i, 4};
433
      ret[9+  N+i] = new int[] {6+  N+i, 7+  N+i, 4};
434
      ret[9+2*N+i] = new int[] {7+2*N+i, 8+2*N+i, 4};
435
      }
436

    
437
    ret[3*N+ 9] = new int[] { 3*N+8, 3*N+ 9, 3 };
438
    ret[3*N+10] = new int[] { 3*N+9, 3*N+10, 1 };
439
    ret[3*N+11] = new int[] { 3*N+8, 3*N+10, 2 };
440

    
441
    return ret;
442
    }
443

    
444
///////////////////////////////////////////////////////////////////////////////////////////////////
445

    
446
  private int[][] produceCenterShape()
447
    {
448
    int[][] ret = new int[3+3*(N-1)+1][];
449

    
450
    ret[0] = new int[3*N];
451
    for(int i=0; i<3*N; i++) ret[0][i] = i;
452

    
453
    for(int i=1; i<=N-1; i++)
454
      {
455
      ret[i] = new int[3];
456
      ret[i][0] = i-1;
457
      ret[i][1] = i;
458
      ret[i][2] = 3*N;
459

    
460
      ret[N-1+i] = new int[3];
461
      ret[N-1+i][0] = N+i-1;
462
      ret[N-1+i][1] = N+i;
463
      ret[N-1+i][2] = 3*N;
464

    
465
      ret[2*N-2+i] = new int[3];
466
      ret[2*N-2+i][0] = 2*N+i-1;
467
      ret[2*N-2+i][1] = 2*N+i;
468
      ret[2*N-2+i][2] = 3*N;
469
      }
470

    
471
    ret[3*N-2] = new int[] {   N-1,   N, 3*N };
472
    ret[3*N-1] = new int[] { 2*N-1, 2*N, 3*N };
473
    ret[3*N  ] = new int[] { 3*N-1,   0, 3*N };
474

    
475
    return ret;
476
    }
477

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

    
480
  private int[][] produceLeafShape()
481
    {
482
    int[][] ret = new int[2+2*(N-1)+1][];
483

    
484
    ret[0] = new int[2*N];
485
    for(int i=0; i<2*N; i++) ret[0][i] = 2*N-1-i;
486

    
487
    for(int i=1; i<=N-1; i++)
488
      {
489
      ret[i] = new int[3];
490
      ret[i][0] = i;
491
      ret[i][1] = i-1;
492
      ret[i][2] = 2*N;
493

    
494
      ret[N-1+i] = new int[3];
495
      ret[N-1+i][0] = N+i;
496
      ret[N-1+i][1] = N+i-1;
497
      ret[N-1+i][2] = 2*N;
498
      }
499

    
500
    ret[2*N-1] = new int[] { N,  N-1, 2*N };
501
    ret[2*N  ] = new int[] { 0,2*N-1, 2*N };
502

    
503
    return ret;
504
    }
505

    
506
///////////////////////////////////////////////////////////////////////////////////////////////////
507

    
508
  public ObjectShape getObjectShape(int variant)
509
    {
510
    if( variant==0 )
511
      {
512
      int[][] indices = produceCornerShape();
513
      return new ObjectShape(getVertices(variant), indices);
514
      }
515
    else if( variant==1 )
516
      {
517
      int[][] indices = produceCenterShape();
518
      return new ObjectShape(getVertices(variant), indices);
519
      }
520
    else
521
      {
522
      int[][] indices = produceLeafShape();
523
      return new ObjectShape(getVertices(variant), indices);
524
      }
525
    }
526

    
527
///////////////////////////////////////////////////////////////////////////////////////////////////
528

    
529
  public ObjectFaceShape getObjectFaceShape(int variant)
530
    {
531
    if( variant==0 )
532
      {
533
      float h1 = isInIconMode() ? 0.0001f : 0.03f;
534
      float h2 = isInIconMode() ? 0.0001f : 0.01f;
535
      float[][] bands = { {h1,35,0.2f,0.4f,5,2,1}, {h2,35,0.2f,0.4f,2,0,0} };
536
      int num = 9+3*N+3;
537
      int[] indices   = new int[num];
538
      for(int i=3; i<num; i++) indices[i] = 1;
539
      float A = 0.5f;
540
      float[] convexCenter = { 0.0f*A, 0.75f*SQ2*A, -1.50f*A};
541
      return new ObjectFaceShape(bands,indices,convexCenter);
542
      }
543
    else if( variant==1 )
544
      {
545
      float h = isInIconMode() ? 0.0001f : 0.001f;
546
      float[][] bands = { {h,15,0.05f,0.1f,5,0,0}, {h,15,0.05f,0.1f,2,0,0} };
547
      int num = 3+3*(N-1)+1;
548
      int[] indices   = new int[num];
549
      for(int i=1; i<num; i++) indices[i] = 1;
550
      return new ObjectFaceShape(bands,indices,null);
551
      }
552
    else
553
      {
554
      float h1 = isInIconMode() ? 0.0001f : 0.015f;
555
      float h2 = isInIconMode() ? 0.0001f : 0.001f;
556
      float[][] bands = { {h1,15,0.250f,0.7f,5,0,0}, {h2,15,0.125f,0.2f,2,0,0} };
557
      int num = 2+2*(N-1)+1;
558
      int[] indices   = new int[num];
559
      for(int i=1; i<num; i++) indices[i] = 1;
560
      return new ObjectFaceShape(bands,indices,null);
561
      }
562
    }
563

    
564
///////////////////////////////////////////////////////////////////////////////////////////////////
565

    
566
  public ObjectVertexEffects getVertexEffects(int variant)
567
    {
568
    if( variant==0 )
569
      {
570
      float[][] corners = { {0.05f,0.20f} };
571
      int num = 5 + 3*(N+1) + 3;
572
      int[] indices     = new int[num];
573
      for(int i=4; i<num; i++) indices[i] = -1;
574
      float[][] centers = { { 0.00f, 0.75f*SQ2,-1.50f} };
575
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
576
      }
577
    else if( variant==1 )
578
      {
579
      float[][] corners = { {0.06f,0.12f} };
580
      int[] indices     = new int[3*N+1];
581
      for(int i=0; i<3*N+1; i++) indices[i] = -1;
582
      float[][] centers = { { 0,0,0 } };
583
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
584
      }
585
    else
586
      {
587
      float[][] corners = { {0.06f,0.20f} };
588
      int[] indices     = new int[2*N+1];
589
      for(int i=0; i<2*N+1; i++) indices[i] = -1;
590
      float[][] centers = { { 0,0,0 } };
591
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
592
      }
593
    }
594

    
595
///////////////////////////////////////////////////////////////////////////////////////////////////
596

    
597
  public int getNumCubitVariants(int[] numLayers)
598
    {
599
    return 3;
600
    }
601

    
602
///////////////////////////////////////////////////////////////////////////////////////////////////
603

    
604
  public int getCubitVariant(int cubit, int[] numLayers)
605
    {
606
    return cubit<4 ? 0 : (cubit<8 ? 1:2);
607
    }
608

    
609
///////////////////////////////////////////////////////////////////////////////////////////////////
610

    
611
  public float getStickerRadius()
612
    {
613
    return 0.12f;
614
    }
615

    
616
///////////////////////////////////////////////////////////////////////////////////////////////////
617

    
618
  public float getStickerStroke()
619
    {
620
    return isInIconMode() ? 0.15f : 0.12f;
621
    }
622

    
623
///////////////////////////////////////////////////////////////////////////////////////////////////
624

    
625
  @Override
626
  public void adjustStickerCoords()
627
    {
628
    float L = 0.02f;
629
    float Z = 0.06422593f - 0.25f*L;
630
    float X = 0.5f - L;
631

    
632
    float K = 1.45f;
633
    float A = K*0.50f;
634
    float B = K*0.25f;
635
    float C = K*0.43301257f;
636

    
637
    float D = 0.3580885f;
638
    float E = 0.12022744f;
639
    float F = 0.32227963f - 0.015f;
640
    float G = 0.14090173f + 0.01f;
641

    
642
    mStickerCoords = new float[][]
643
          {
644
            { -D, E, 0.0f, -0.5f, D, E, F, G, -F, G },
645
            { -C, B, C, B, 0.0f, -A },
646
            { -X, Z, X, Z }
647
          };
648
    }
649

    
650
///////////////////////////////////////////////////////////////////////////////////////////////////
651

    
652
  public float[][] getStickerAngles()
653
    {
654
    float D1 = (float)(Math.PI/3);
655
    float D2 = (float)(Math.PI/5);
656
    float D3 = (float)(Math.PI/6);
657
    return new float[][] { { 0,0,0,-D1,0 },{D2,D2,D2},{D1,D3} };
658
    }
659

    
660
///////////////////////////////////////////////////////////////////////////////////////////////////
661
// PUBLIC API
662

    
663
  public Static3D[] getRotationAxis()
664
    {
665
    return ROT_AXIS;
666
    }
667

    
668
///////////////////////////////////////////////////////////////////////////////////////////////////
669

    
670
  public int[][] getBasicAngles()
671
    {
672
    if( mBasicAngle ==null )
673
      {
674
      int[] tmp = {3,3,3};
675
      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
676
      }
677

    
678
    return mBasicAngle;
679
    }
680

    
681
///////////////////////////////////////////////////////////////////////////////////////////////////
682

    
683
  public String getShortName()
684
    {
685
    return ObjectType.COIN_3.name();
686
    }
687

    
688
///////////////////////////////////////////////////////////////////////////////////////////////////
689

    
690
  public ObjectSignature getSignature()
691
    {
692
    return new ObjectSignature(ObjectSignatures.COIN_3);
693
    }
694

    
695
///////////////////////////////////////////////////////////////////////////////////////////////////
696

    
697
  public String getObjectName()
698
    {
699
    return "Coin Tetrahedron";
700
    }
701

    
702
///////////////////////////////////////////////////////////////////////////////////////////////////
703

    
704
  public String getInventor()
705
    {
706
    return "Kevin Uhrik";
707
    }
708

    
709
///////////////////////////////////////////////////////////////////////////////////////////////////
710

    
711
  public int getYearOfInvention()
712
    {
713
    return 2019;
714
    }
715

    
716
///////////////////////////////////////////////////////////////////////////////////////////////////
717

    
718
  public int getComplexity()
719
    {
720
    return 0;
721
    }
722

    
723
///////////////////////////////////////////////////////////////////////////////////////////////////
724

    
725
  public String[][] getTutorials()
726
    {
727
    return new String[][] {
728
                          {"gb","2WrDNfcfpAg","Coin Pyraminx Tutorial","Brent Richter"},
729
                          {"es","5pTfSCsHPWs","Tutorial Coin Pyraminx","Kubekings"},
730
                          {"ru","qUMQsn8kg1A","Как собрать Коин Пираминкс","Алексей Ярыгин"},
731
                          {"vn","TOaiOcEE0lk","Hướng Dẫn Giải Pyraminx Coin","Rubik Cube"},
732
                         };
733
    }
734
}
(7-7/47)