Project

General

Profile

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

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

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 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.main.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.ShapeHexahedron;
29
import org.distorted.objectlib.touchcontrol.TouchControlTetrahedron;
30

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

    
33
public class TwistyCoinTetrahedron extends ShapeHexahedron
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

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

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

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

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

    
63
  public int[][] getScrambleEdges()
64
    {
65
    if( mEdges==null ) mEdges = ScrambleEdgeGenerator.getScrambleEdgesSingle(mBasicAngle);
66
    return mEdges;
67
    }
68

    
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70

    
71
  public float[][] getCuts(int[] numLayers)
72
    {
73
    if( mCuts==null )
74
      {
75
      float[] cut = new float[] {-0.95f*(SQ6/4),0};
76
      mCuts = new float[][] { cut,cut,cut,cut };
77
      }
78

    
79
    return mCuts;
80
    }
81

    
82
///////////////////////////////////////////////////////////////////////////////////////////////////
83

    
84
  public boolean[][] getLayerRotatable(int[] numLayers)
85
    {
86
    boolean[] tmp = new boolean[] {true,false,true};
87
    return new boolean[][] { tmp,tmp,tmp,tmp };
88
    }
89

    
90
///////////////////////////////////////////////////////////////////////////////////////////////////
91

    
92
  public int getTouchControlType()
93
    {
94
    return TC_TETRAHEDRON;
95
    }
96

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

    
99
  public int getTouchControlSplit()
100
    {
101
    return TYPE_SPLIT_EDGE_COIN;
102
    }
103

    
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105

    
106
  public int[][][] getEnabled()
107
    {
108
    return new int[][][]
109
      {
110
         {{0},{0},{0},{1},{3},{2}},
111
         {{1},{1},{1},{0},{2},{3}},
112
         {{2},{2},{2},{3},{1},{0}},
113
         {{3},{3},{3},{2},{0},{1}}
114
      };
115
    }
116

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

    
119
  public float[] getDist3D(int[] numLayers)
120
    {
121
    return TouchControlTetrahedron.D3D;
122
    }
123

    
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125

    
126
  public Static3D[] getFaceAxis()
127
    {
128
    return TouchControlTetrahedron.FACE_AXIS;
129
    }
130

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

    
133
  private void initVertices()
134
    {
135
    V = new float[][]
136
        {
137
            { 0.0f,-0.75f*SQ2,-1.5f},
138
            { 0.0f,-0.75f*SQ2, 1.5f},
139
            { 1.5f, 0.75f*SQ2, 0.0f},
140
            {-1.5f, 0.75f*SQ2, 0.0f},
141
        };
142

    
143
    float A = 1.04f;
144
    M = new float[4][3];
145

    
146
    for(int i=0; i<4; i++)
147
      for(int j=0; j<3; j++)
148
        M[i][j] = A*(V[0][j]+V[1][j]+V[2][j]+V[3][j]-V[i][j])/3;
149

    
150
    L = new float[12][3];
151

    
152
    for(int i=0; i<3; i++)
153
      {
154
      L[ 0][i] = 0.5f*V[1][i] + 0.25f*V[2][i] + 0.25f*V[3][i];
155
      L[ 1][i] = 0.5f*V[3][i] + 0.25f*V[1][i] + 0.25f*V[2][i];
156
      L[ 2][i] = 0.5f*V[2][i] + 0.25f*V[1][i] + 0.25f*V[3][i];
157
      L[ 3][i] = 0.5f*V[0][i] + 0.25f*V[2][i] + 0.25f*V[3][i];
158
      L[ 4][i] = 0.5f*V[2][i] + 0.25f*V[0][i] + 0.25f*V[3][i];
159
      L[ 5][i] = 0.5f*V[3][i] + 0.25f*V[0][i] + 0.25f*V[2][i];
160
      L[ 6][i] = 0.5f*V[3][i] + 0.25f*V[1][i] + 0.25f*V[0][i];
161
      L[ 7][i] = 0.5f*V[0][i] + 0.25f*V[1][i] + 0.25f*V[3][i];
162
      L[ 8][i] = 0.5f*V[1][i] + 0.25f*V[0][i] + 0.25f*V[3][i];
163
      L[ 9][i] = 0.5f*V[2][i] + 0.25f*V[1][i] + 0.25f*V[0][i];
164
      L[10][i] = 0.5f*V[0][i] + 0.25f*V[1][i] + 0.25f*V[2][i];
165
      L[11][i] = 0.5f*V[1][i] + 0.25f*V[0][i] + 0.25f*V[2][i];
166
      }
167
    }
168

    
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170

    
171
  public float[][] getCubitPositions(int[] numLayers)
172
    {
173
    if( mPosition==null )
174
      {
175
      if( V==null ) initVertices();
176

    
177
      float A = -0.015f;
178
      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]) };
179
      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]) };
180
      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]) };
181
      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]) };
182

    
183
      mPosition = new float[][]
184
         {
185
             {V[1][0],V[1][1],V[1][2]},
186
             {V[0][0],V[0][1],V[0][2]},
187
             {V[2][0],V[2][1],V[2][2]},
188
             {V[3][0],V[3][1],V[3][2]},
189

    
190
             {M[0][0],M[0][1],M[0][2]},
191
             {M[1][0],M[1][1],M[1][2]},
192
             {M[2][0],M[2][1],M[2][2]},
193
             {M[3][0],M[3][1],M[3][2]},
194

    
195
             {L[ 0][0] +r0[0],L[ 0][1] +r0[1],L[ 0][2] +r0[2]},
196
             {L[ 1][0] +r0[0],L[ 1][1] +r0[1],L[ 1][2] +r0[2]},
197
             {L[ 2][0] +r0[0],L[ 2][1] +r0[1],L[ 2][2] +r0[2]},
198
             {L[ 3][0] +r1[0],L[ 3][1] +r1[1],L[ 3][2] +r1[2]},
199
             {L[ 4][0] +r1[0],L[ 4][1] +r1[1],L[ 4][2] +r1[2]},
200
             {L[ 5][0] +r1[0],L[ 5][1] +r1[1],L[ 5][2] +r1[2]},
201
             {L[ 6][0] +r2[0],L[ 6][1] +r2[1],L[ 6][2] +r2[2]},
202
             {L[ 7][0] +r2[0],L[ 7][1] +r2[1],L[ 7][2] +r2[2]},
203
             {L[ 8][0] +r2[0],L[ 8][1] +r2[1],L[ 8][2] +r2[2]},
204
             {L[ 9][0] +r3[0],L[ 9][1] +r3[1],L[ 9][2] +r3[2]},
205
             {L[10][0] +r3[0],L[10][1] +r3[1],L[10][2] +r3[2]},
206
             {L[11][0] +r3[0],L[11][1] +r3[1],L[11][2] +r3[2]},
207
         };
208
      }
209

    
210
    return mPosition;
211
    }
212

    
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214

    
215
  public Static4D getCubitQuats(int cubit, int[] numLayers)
216
    {
217
    if( mQuatIndex==null ) mQuatIndex = new int[] {0,6,1,2,
218
                                                   0,5,4,3,
219
                                                   0,2,1,10,8,5,11,7,4,9,6,3 };
220
    return mObjectQuats[mQuatIndex[cubit]];
221
    }
222

    
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224

    
225
  private float[] rotateVertices(float angle, float[] vector, float[] center, float[] rotAxis)
226
    {
227
    float[] ret = new float[4];
228
    float sin = (float)Math.sin(angle/2);
229
    float cos = (float)Math.cos(angle/2);
230
    float[] quat= new float[] { sin*rotAxis[0], sin*rotAxis[1], sin*rotAxis[2], cos};
231
    QuatHelper.rotateVectorByQuat(ret,vector,quat);
232

    
233
    ret[0] += center[0];
234
    ret[1] += center[1];
235
    ret[2] += center[2];
236

    
237
    return ret;
238
    }
239

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

    
242
  private void normalize(float[] v)
243
    {
244
    float len = (float)Math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
245
    v[0] /= len;
246
    v[1] /= len;
247
    v[2] /= len;
248
    }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
  private float[][] produceCorner()
253
    {
254
    float[][] ret = new float[5 + 3*(N+1) +3][];
255

    
256
    ret[0] = new float[] { 0.00f, 0.0f     , 0.00f };
257
    ret[1] = new float[] { 0.00f, 0.0f     ,-1.50f };
258
    ret[2] = new float[] { 0.75f, 0.75f*SQ2,-0.75f };
259
    ret[3] = new float[] {-0.75f, 0.75f*SQ2,-0.75f };
260
    ret[4] = new float[] { 0.00f, 0.75f*SQ2,-1.50f };
261

    
262
    float[] vect1 = new float[4];
263
    float[] vect2 = new float[4];
264
    float[] vect3 = new float[4];
265

    
266
    for(int i=0; i<3; i++)
267
      {
268
      vect1[i] = -D*M[0][i] + D*(V[1][i]+V[3][i])/2;
269
      vect2[i] = -D*M[3][i] + D*(V[1][i]+V[2][i])/2;
270
      vect3[i] = -D*M[2][i] + D*(V[0][i]+V[1][i])/2;
271
      }
272

    
273
    float[] rot1 = new float[] { V[0][0]-M[0][0], V[0][1]-M[0][1], V[0][2]-M[0][2] };
274
    float[] rot2 = new float[] { V[3][0]-M[3][0], V[3][1]-M[3][1], V[3][2]-M[3][2] };
275
    float[] rot3 = new float[] { V[2][0]-M[2][0], V[2][1]-M[2][1], V[2][2]-M[2][2] };
276

    
277
    normalize(rot1);
278
    normalize(rot2);
279
    normalize(rot3);
280

    
281
    float[] center1 = { M[0][0]-V[1][0], M[0][1]-V[1][1], M[0][2]-V[1][2] };
282
    float[] center2 = { M[3][0]-V[1][0], M[3][1]-V[1][1], M[3][2]-V[1][2] };
283
    float[] center3 = { M[2][0]-V[1][0], M[2][1]-V[1][1], M[2][2]-V[1][2] };
284

    
285
    for(int i=0; i<N+1; i++)
286
      {
287
      float angle = (float)(2*Math.PI/3)*i/N;
288

    
289
      ret[5        +i] = rotateVertices(angle,vect1,center1,rot1);
290
      ret[5+   N+1 +i] = rotateVertices(angle,vect2,center2,rot2);
291
      ret[5+2*(N+1)+i] = rotateVertices(angle,vect3,center3,rot3);
292
      }
293

    
294
    float B = 0.85f;
295
    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) };
296
    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) };
297
    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) };
298

    
299
    return ret;
300
    }
301

    
302
///////////////////////////////////////////////////////////////////////////////////////////////////
303

    
304
  private float[][] produceCenter()
305
    {
306
    float[][] ret = new float[3*N+1][];
307

    
308
    float[] rot = new float[] { V[0][0]-M[0][0], V[0][1]-M[0][1], V[0][2]-M[0][2] };
309
    normalize(rot);
310

    
311
    float[] center1 = {   0.0f,-D*SQ2  , D  };
312
    float[] center2 = { D*1.5f, D*SQ2/2,-D/2};
313
    float[] center3 = {-D*1.5f, D*SQ2/2,-D/2};
314

    
315
    float[] vect1 = {  D*0.75f, D*0.75f*SQ2, -D*0.75f, 0.0f };
316
    float[] vect2 = { -D*1.50f,   0.00f    ,    0.00f, 0.0f };
317
    float[] vect3 = {  D*0.75f,-D*0.75f*SQ2,  D*0.75f, 0.0f };
318

    
319
    for(int i=0; i<N; i++)
320
      {
321
      float angle = (float)(Math.PI/3)*i/N;
322

    
323
      ret[  N-1-i] = rotateVertices(angle, vect1, center1, rot);
324
      ret[2*N-1-i] = rotateVertices(angle, vect2, center2, rot);
325
      ret[3*N-1-i] = rotateVertices(angle, vect3, center3, rot);
326
      }
327

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

    
330
    return ret;
331
    }
332

    
333
///////////////////////////////////////////////////////////////////////////////////////////////////
334

    
335
  private float[][] produceLeaf()
336
    {
337
    float[][] ret = new float[2*N+1][];
338

    
339
    float[] rot = new float[] { V[0][0]-M[0][0], V[0][1]-M[0][1], V[0][2]-M[0][2] };
340
    normalize(rot);
341

    
342
    float[] center1 = { 0.0f, -D*0.75f*SQ2, D*0.75f };
343
    float[] center2 = { 0.0f,    0.25f*SQ2,  -0.25f };
344

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

    
349
    for(int i=0; i<N; i++)
350
      {
351
      float angle1 = (float)(  Math.PI/3)*i/N;
352
      float angle2 = (float)(2*Math.PI/3)*i/N;
353

    
354
      ret[  N-1-i] = rotateVertices(angle1, vect1, center1, rot);
355
      ret[2*N-1-i] = rotateVertices(angle2, vect2, center2, rot);
356
      }
357

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

    
360
    return ret;
361
    }
362

    
363
///////////////////////////////////////////////////////////////////////////////////////////////////
364

    
365
  private float[][] getVertices(int variant)
366
    {
367
         if( variant==0 ) return produceCorner();
368
    else if( variant==1 ) return produceCenter();
369
    else                  return produceLeaf();
370
    }
371

    
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373

    
374
  private int[][] produceCornerShape()
375
    {
376
    int[][] ret = new int[9+3*N+3][];
377

    
378
    ret[0] = new int[N+4];
379
    ret[0][0] = 3;
380
    ret[0][1] = 0;
381
    ret[0][2] = 2;
382
    for(int i=0; i<N+1; i++) ret[0][3+i] = 5+N-i;
383

    
384
    ret[1] = new int[N+4];
385
    ret[1][0] = 2;
386
    ret[1][1] = 0;
387
    ret[1][2] = 1;
388
    for(int i=0; i<N+1; i++) ret[1][3+i] = 6+2*N-i;
389

    
390
    ret[2] = new int[N+4];
391
    ret[2][0] = 1;
392
    ret[2][1] = 0;
393
    ret[2][2] = 3;
394
    for(int i=0; i<N+1; i++) ret[2][3+i] = 7+3*N-i;
395

    
396
    ret[3] = new int[] {5+  N,2    , 4 };
397
    ret[4] = new int[] {2    ,6+  N, 4 };
398
    ret[5] = new int[] {6+2*N,1    , 4 };
399
    ret[6] = new int[] {1    ,7+2*N, 4 };
400
    ret[7] = new int[] {7+3*N,3    , 4 };
401
    ret[8] = new int[] {3    ,5    , 4 };
402

    
403
    for(int i=0; i<N; i++)
404
      {
405
      ret[9+    i] = new int[] {5    +i, 6    +i, 4};
406
      ret[9+  N+i] = new int[] {6+  N+i, 7+  N+i, 4};
407
      ret[9+2*N+i] = new int[] {7+2*N+i, 8+2*N+i, 4};
408
      }
409

    
410
    ret[3*N+ 9] = new int[] { 3*N+8, 3*N+ 9, 3 };
411
    ret[3*N+10] = new int[] { 3*N+9, 3*N+10, 1 };
412
    ret[3*N+11] = new int[] { 3*N+8, 3*N+10, 2 };
413

    
414
    return ret;
415
    }
416

    
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418

    
419
  private int[][] produceCenterShape()
420
    {
421
    int[][] ret = new int[3+3*(N-1)+1][];
422

    
423
    ret[0] = new int[3*N];
424
    for(int i=0; i<3*N; i++) ret[0][i] = 3*N-1-i;
425

    
426
    for(int i=1; i<=N-1; i++)
427
      {
428
      ret[i] = new int[3];
429
      ret[i][0] = i;
430
      ret[i][1] = i-1;
431
      ret[i][2] = 3*N;
432

    
433
      ret[N-1+i] = new int[3];
434
      ret[N-1+i][0] = N+i;
435
      ret[N-1+i][1] = N+i-1;
436
      ret[N-1+i][2] = 3*N;
437

    
438
      ret[2*N-2+i] = new int[3];
439
      ret[2*N-2+i][0] = 2*N+i;
440
      ret[2*N-2+i][1] = 2*N+i-1;
441
      ret[2*N-2+i][2] = 3*N;
442
      }
443

    
444
    ret[3*N-2] = new int[] {   N-1,   N, 3*N };
445
    ret[3*N-1] = new int[] { 2*N-1, 2*N, 3*N };
446
    ret[3*N  ] = new int[] { 3*N-1,   0, 3*N };
447

    
448
    return ret;
449
    }
450

    
451
///////////////////////////////////////////////////////////////////////////////////////////////////
452

    
453
  private int[][] produceLeafShape()
454
    {
455
    int[][] ret = new int[2+2*(N-1)+1][];
456

    
457
    ret[0] = new int[2*N];
458
    for(int i=0; i<2*N; i++) ret[0][i] = 2*N-1-i;
459

    
460
    for(int i=1; i<=N-1; i++)
461
      {
462
      ret[i] = new int[3];
463
      ret[i][0] = i;
464
      ret[i][1] = i-1;
465
      ret[i][2] = 2*N;
466

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

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

    
476
    return ret;
477
    }
478

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

    
481
  public ObjectShape getObjectShape(int variant)
482
    {
483
    if( variant==0 )
484
      {
485
      int[][] indices = produceCornerShape();
486
      return new ObjectShape(getVertices(variant), indices);
487
      }
488
    else if( variant==1 )
489
      {
490
      int[][] indices = produceCenterShape();
491
      return new ObjectShape(getVertices(variant), indices);
492
      }
493
    else
494
      {
495
      int[][] indices = produceLeafShape();
496
      return new ObjectShape(getVertices(variant), indices);
497
      }
498
    }
499

    
500
///////////////////////////////////////////////////////////////////////////////////////////////////
501

    
502
  public ObjectFaceShape getObjectFaceShape(int variant)
503
    {
504
    if( variant==0 )
505
      {
506
      float h1 = isInIconMode() ? 0.001f : 0.02f;
507
      float h2 = isInIconMode() ? 0.001f : 0.01f;
508
      float[][] bands = { {h1,35,0.2f,0.4f,5,1,0}, {h2,35,0.2f,0.4f,2,0,0} };
509
      int num = 9+3*N+3;
510
      int[] indices   = new int[num];
511
      for(int i=3; i<num; i++) indices[i] = 1;
512
      float A = 0.5f;
513
      float[] convexCenter = { 0.0f*A, 0.75f*SQ2*A, -1.50f*A};
514
      return new ObjectFaceShape(bands,indices,convexCenter);
515
      }
516
    else if( variant==1 )
517
      {
518
      float h1 = isInIconMode() ? 0.001f : 0.00f;
519
      float h2 = isInIconMode() ? 0.001f : 0.00f;
520
      float[][] bands = { {h1,15,0.1f,0.2f,5,0,0}, {h2,15,0.1f,0.2f,2,0,0} };
521
      int num = 3+3*(N-1)+1;
522
      int[] indices   = new int[num];
523
      for(int i=1; i<num; i++) indices[i] = 1;
524
      return new ObjectFaceShape(bands,indices,null);
525
      }
526
    else
527
      {
528
      float h1 = isInIconMode() ? 0.001f : 0.02f;
529
      float h2 = isInIconMode() ? 0.001f : 0.00f;
530
      float[][] bands = { {h1,15,0.250f,0.7f,5,0,0}, {h2,15,0.125f,0.2f,2,0,0} };
531
      int num = 2+2*(N-1)+1;
532
      int[] indices   = new int[num];
533
      for(int i=1; i<num; i++) indices[i] = 1;
534
      return new ObjectFaceShape(bands,indices,null);
535
      }
536
    }
537

    
538
///////////////////////////////////////////////////////////////////////////////////////////////////
539

    
540
  public ObjectVertexEffects getVertexEffects(int variant)
541
    {
542
    if( variant==0 )
543
      {
544
      float[][] corners = { {0.04f,0.10f} };
545
      int num = 5 + 3*(N+1) + 3;
546
      int[] indices     = new int[num];
547
      for(int i=4; i<num; i++) indices[i] = -1;
548
      float[][] centers = { { 0.00f, 0.75f*SQ2,-1.50f} };
549
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
550
      }
551
    else if( variant==1 )
552
      {
553
      float[][] corners = { {0.06f,0.12f} };
554
      int[] indices     = new int[3*N+1];
555
      for(int i=0; i<3*N+1; i++) indices[i] = -1;
556
      float[][] centers = { { 0,0,0 } };
557
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
558
      }
559
    else
560
      {
561
      float[][] corners = { {0.06f,0.20f} };
562
      int[] indices     = new int[2*N+1];
563
      for(int i=0; i<2*N+1; i++) indices[i] = -1;
564
      float[][] centers = { { 0,0,0 } };
565
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
566
      }
567
    }
568

    
569
///////////////////////////////////////////////////////////////////////////////////////////////////
570

    
571
  public int getNumCubitVariants(int[] numLayers)
572
    {
573
    return 3;
574
    }
575

    
576
///////////////////////////////////////////////////////////////////////////////////////////////////
577

    
578
  public int getCubitVariant(int cubit, int[] numLayers)
579
    {
580
    return cubit<4 ? 0 : (cubit<8 ? 1:2);
581
    }
582

    
583
///////////////////////////////////////////////////////////////////////////////////////////////////
584

    
585
  public float getStickerRadius()
586
    {
587
    return 0.12f;
588
    }
589

    
590
///////////////////////////////////////////////////////////////////////////////////////////////////
591

    
592
  public float getStickerStroke()
593
    {
594
    return isInIconMode() ? 0.20f : 0.12f;
595
    }
596

    
597
///////////////////////////////////////////////////////////////////////////////////////////////////
598

    
599
  @Override
600
  public void adjustStickerCoords()
601
    {
602
    float B = 0.06422593f;
603
    float C = 0.43301257f;
604
    float D = 0.3580885f;
605
    float E = 0.12022744f;
606
    float F = 0.32227963f - 0.015f;
607
    float G = 0.14090173f + 0.01f;
608

    
609
    mStickerCoords = new float[][]
610
          {
611
            { -D, E, 0.0f, -0.5f, D, E, F, G, -F, G },
612
            { -C, -0.25f, 0.0f, 0.5f, C, -0.25f },
613
            { -0.5f, B, 0.5f, B }
614
          };
615
    }
616

    
617
///////////////////////////////////////////////////////////////////////////////////////////////////
618

    
619
  public float[][] getStickerAngles()
620
    {
621
    float D1 = (float)(Math.PI/3);
622
    float D2 = (float)(Math.PI/8);  // really 6, but with 8 it looks better
623
    return new float[][] { { 0,0,0,-D1,0 },{-D2,-D2,-D2},{D1,D2} };
624
    }
625

    
626
///////////////////////////////////////////////////////////////////////////////////////////////////
627
// PUBLIC API
628

    
629
  public Static3D[] getRotationAxis()
630
    {
631
    return ROT_AXIS;
632
    }
633

    
634
///////////////////////////////////////////////////////////////////////////////////////////////////
635

    
636
  public int[][] getBasicAngles()
637
    {
638
    if( mBasicAngle ==null )
639
      {
640
      int[] tmp = {3,3,3};
641
      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
642
      }
643

    
644
    return mBasicAngle;
645
    }
646

    
647
///////////////////////////////////////////////////////////////////////////////////////////////////
648

    
649
  public String getShortName()
650
    {
651
    return ObjectType.COIN_3.name();
652
    }
653

    
654
///////////////////////////////////////////////////////////////////////////////////////////////////
655

    
656
  public ObjectSignature getSignature()
657
    {
658
    return new ObjectSignature(ObjectSignatures.COIN_3);
659
    }
660

    
661
///////////////////////////////////////////////////////////////////////////////////////////////////
662

    
663
  public String getObjectName()
664
    {
665
    return "Coin Tetrahedron";
666
    }
667

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

    
670
  public String getInventor()
671
    {
672
    return "Kevin Uhrik";
673
    }
674

    
675
///////////////////////////////////////////////////////////////////////////////////////////////////
676

    
677
  public int getYearOfInvention()
678
    {
679
    return 2019;
680
    }
681

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

    
684
  public int getComplexity()
685
    {
686
    return 0;
687
    }
688

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

    
691
  public String[][] getTutorials()
692
    {
693
    return new String[][] {
694
                          {"gb","2WrDNfcfpAg","Coin Pyraminx Tutorial","Brent Richter"},
695
                          {"es","5pTfSCsHPWs","Tutorial Coin Pyraminx","Kubekings"},
696
                          {"ru","qUMQsn8kg1A","Как собрать Коин Пираминкс","Алексей Ярыгин"},
697
                          {"vn","TOaiOcEE0lk","Hướng Dẫn Giải Pyraminx Coin","Rubik Cube"},
698
                         };
699
    }
700
}
(5-5/44)