Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyCrazy.java @ a8295031

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2022 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objectlib.objects;
21

    
22
import java.io.InputStream;
23

    
24
import org.distorted.library.type.Static3D;
25
import org.distorted.library.type.Static4D;
26
import org.distorted.objectlib.helpers.ObjectFaceShape;
27
import org.distorted.objectlib.helpers.ObjectShape;
28
import org.distorted.objectlib.helpers.ObjectSignature;
29
import org.distorted.objectlib.main.InitData;
30
import org.distorted.objectlib.main.ObjectType;
31
import org.distorted.objectlib.main.ShapeHexahedron;
32
import org.distorted.objectlib.scrambling.ScrambleState;
33
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
34

    
35
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_HEXAHEDRON;
36
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
37

    
38
///////////////////////////////////////////////////////////////////////////////////////////////////
39

    
40
public class TwistyCrazy extends ShapeHexahedron
41
{
42
  private static final float DIAMETER_RATIO = 0.75f;
43
  private static final int NUMBER_CORNER_SEGMENTS = 4;
44
  private static final int NUMBER_EDGE_SEGMENTS = 4;
45

    
46
  static final Static3D[] ROT_AXIS = new Static3D[]
47
         {
48
           new Static3D(1,0,0),
49
           new Static3D(0,1,0),
50
           new Static3D(0,0,1)
51
         };
52

    
53
  private ScrambleState[] mStates;
54
  private int[][] mBasicAngle;
55
  private float[][] mCuts;
56
  private float[][] mPositions;
57
  private int[] mQuatIndex;
58

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

    
61
  public TwistyCrazy(InitData data, int meshState, int iconMode, Static4D quat, Static3D move, float scale, InputStream stream)
62
    {
63
    super(data, meshState, iconMode, data.getNumLayers()[0], quat, move, scale, stream);
64
    }
65

    
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67

    
68
  @Override
69
  public void adjustStickerCoords()
70
    {
71
    final float A = 0.3645522f;
72
    final float B = 0.0744520f;
73
    final float C = 0.1823852f;
74
    final float D = 0.3098326f;
75
    final float E = 0.1033291f;
76
    final float F = 0.4044531f;
77
    final float G = 0.4103489f;
78

    
79
    mStickerCoords = new float[][]
80
      {
81
         { A, 0.5f, -0.5f, 0.5f, -0.5f, -A, -B, -A, A, B },
82
         { 0.5f, -C, 0.5f, D, -0.5f, D, -0.5f, -C },
83
         { -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f },
84
         { -0.5f, E, -0.5f, -F, 0.5f, -F, 0.5f, E },
85
         { -G, 0.5f, -G, -G, 0.5f, -G }
86
      };
87
    }
88

    
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90
// Normal 3x3
91

    
92
  public ScrambleState[] getScrambleStates()
93
    {
94
    if( mStates==null )
95
      {
96
      int[][] m = new int[16][];
97

    
98
      for(int i=0; i<16; i++) m[i] = new int[] { 0,-1,i,0,1,i,0,2,i, 1,-1,i,1,1,i,1,2,i, 2,-1,i,2,1,i,2,2,i};
99

    
100
      mStates = new ScrambleState[]
101
          {
102
          new ScrambleState( new int[][] { m[ 1], m[ 2], m[ 3] } ),  //  0 0
103
          new ScrambleState( new int[][] {  null, m[ 4], m[ 5] } ),  //  1 x
104
          new ScrambleState( new int[][] { m[ 6],  null, m[ 7] } ),  //  2 y
105
          new ScrambleState( new int[][] { m[ 8], m[ 9],  null } ),  //  3 z
106
          new ScrambleState( new int[][] { m[10],  null, m[ 7] } ),  //  4 xy
107
          new ScrambleState( new int[][] { m[11], m[ 9],  null } ),  //  5 xz
108
          new ScrambleState( new int[][] {  null, m[12], m[ 5] } ),  //  6 yx
109
          new ScrambleState( new int[][] { m[ 8], m[13],  null } ),  //  7 yz
110
          new ScrambleState( new int[][] {  null, m[ 4], m[14] } ),  //  8 zx
111
          new ScrambleState( new int[][] { m[ 6],  null, m[15] } ),  //  9 zy
112
          new ScrambleState( new int[][] {  null,  null, m[ 5] } ),  // 10 xyx
113
          new ScrambleState( new int[][] {  null, m[ 4],  null } ),  // 11 xzx
114
          new ScrambleState( new int[][] {  null,  null, m[ 7] } ),  // 12 yxy
115
          new ScrambleState( new int[][] { m[ 6],  null,  null } ),  // 13 yzy
116
          new ScrambleState( new int[][] {  null, m[ 9],  null } ),  // 14 zxz
117
          new ScrambleState( new int[][] { m[ 8],  null,  null } ),  // 15 zyz
118
          };
119
      }
120

    
121
    return mStates;
122
    }
123

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

    
126
  public float[][] getCuts(int[] numLayers)
127
    {
128
    if( mCuts==null )
129
      {
130
      float C = 0.5f;
131
      float[] cut = new float[] {-C,+C};
132
      mCuts = new float[][] { cut,cut,cut };
133
      }
134

    
135
    return mCuts;
136
    }
137

    
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139

    
140
  public boolean[][] getLayerRotatable(int[] numLayers)
141
    {
142
    boolean[] tmp = new boolean[] {true,true,true};
143
    return new boolean[][] { tmp,tmp,tmp };
144
    }
145

    
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147

    
148
  public int getTouchControlType()
149
    {
150
    return TC_HEXAHEDRON;
151
    }
152

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

    
155
  public int getTouchControlSplit()
156
    {
157
    return TYPE_NOT_SPLIT;
158
    }
159

    
160
///////////////////////////////////////////////////////////////////////////////////////////////////
161

    
162
  public int[][][] getEnabled()
163
    {
164
    return new int[][][] { {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}} };
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  public float[] getDist3D(int[] numLayers)
170
    {
171
    return TouchControlHexahedron.D3D;
172
    }
173

    
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175

    
176
  public Static3D[] getFaceAxis()
177
    {
178
    return TouchControlHexahedron.FACE_AXIS;
179
    }
180

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

    
183
  public float[][] getCubitPositions(int[] numLayers)
184
    {
185
    if( mPositions==null )
186
      {
187
      mPositions = new float[][]
188
         {
189
             { 1.0f, 1.0f, 1.0f},
190
             { 1.0f, 1.0f,-1.0f},
191
             { 1.0f,-1.0f, 1.0f},
192
             { 1.0f,-1.0f,-1.0f},
193
             {-1.0f, 1.0f, 1.0f},
194
             {-1.0f, 1.0f,-1.0f},
195
             {-1.0f,-1.0f, 1.0f},
196
             {-1.0f,-1.0f,-1.0f},
197

    
198
             { 1.0f, 1.0f, 0.0f},
199
             { 1.0f,-1.0f, 0.0f},
200
             { 1.0f, 0.0f, 1.0f},
201
             { 1.0f, 0.0f,-1.0f},
202
             {-1.0f, 1.0f, 0.0f},
203
             {-1.0f,-1.0f, 0.0f},
204
             {-1.0f, 0.0f, 1.0f},
205
             {-1.0f, 0.0f,-1.0f},
206
             { 0.0f, 1.0f, 1.0f},
207
             { 0.0f, 1.0f,-1.0f},
208
             { 0.0f,-1.0f, 1.0f},
209
             { 0.0f,-1.0f,-1.0f},
210

    
211
             { 0.0f, 0.0f, 0.0f},
212
             { 0.0f, 0.0f, 0.0f},
213
             { 0.0f, 0.0f, 0.0f},
214
             { 0.0f, 0.0f, 0.0f},
215
             { 0.0f, 0.0f, 0.0f},
216
             { 0.0f, 0.0f, 0.0f},
217

    
218
             { 0.0f, 1.0f, 0.0f},
219
             { 0.0f, 1.0f, 0.0f},
220
             { 0.0f, 1.0f, 0.0f},
221
             { 0.0f, 1.0f, 0.0f},
222
             { 0.0f,-1.0f, 0.0f},
223
             { 0.0f,-1.0f, 0.0f},
224
             { 0.0f,-1.0f, 0.0f},
225
             { 0.0f,-1.0f, 0.0f},
226
             { 0.0f, 0.0f, 1.0f},
227
             { 0.0f, 0.0f, 1.0f},
228
             { 0.0f, 0.0f, 1.0f},
229
             { 0.0f, 0.0f, 1.0f},
230
             { 0.0f, 0.0f,-1.0f},
231
             { 0.0f, 0.0f,-1.0f},
232
             { 0.0f, 0.0f,-1.0f},
233
             { 0.0f, 0.0f,-1.0f},
234
             { 1.0f, 0.0f, 0.0f},
235
             { 1.0f, 0.0f, 0.0f},
236
             { 1.0f, 0.0f, 0.0f},
237
             { 1.0f, 0.0f, 0.0f},
238
             {-1.0f, 0.0f, 0.0f},
239
             {-1.0f, 0.0f, 0.0f},
240
             {-1.0f, 0.0f, 0.0f},
241
             {-1.0f, 0.0f, 0.0f},
242

    
243
             { 1.0f, 1.0f, 0.0f},
244
             { 1.0f, 1.0f, 0.0f},
245
             { 1.0f,-1.0f, 0.0f},
246
             { 1.0f,-1.0f, 0.0f},
247
             { 1.0f, 0.0f, 1.0f},
248
             { 1.0f, 0.0f, 1.0f},
249
             { 1.0f, 0.0f,-1.0f},
250
             { 1.0f, 0.0f,-1.0f},
251
             {-1.0f, 1.0f, 0.0f},
252
             {-1.0f, 1.0f, 0.0f},
253
             {-1.0f,-1.0f, 0.0f},
254
             {-1.0f,-1.0f, 0.0f},
255
             {-1.0f, 0.0f, 1.0f},
256
             {-1.0f, 0.0f, 1.0f},
257
             {-1.0f, 0.0f,-1.0f},
258
             {-1.0f, 0.0f,-1.0f},
259
             { 0.0f, 1.0f, 1.0f},
260
             { 0.0f, 1.0f, 1.0f},
261
             { 0.0f, 1.0f,-1.0f},
262
             { 0.0f, 1.0f,-1.0f},
263
             { 0.0f,-1.0f, 1.0f},
264
             { 0.0f,-1.0f, 1.0f},
265
             { 0.0f,-1.0f,-1.0f},
266
             { 0.0f,-1.0f,-1.0f},
267
         };
268
      }
269

    
270
    return mPositions;
271
    }
272

    
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274

    
275
  public Static4D getCubitQuats(int cubit, int[] numLayers)
276
    {
277
    if( mQuatIndex==null ) mQuatIndex = new int[] { 0,1,17,22,4,5,8,19,
278
                                                    6,17,7,12,4,16,9,10,0,5,3,2,
279
                                                    0,2,1,3,6,4,
280
                                                    0,4,5,6, 2,8,16,17, 3,14,20,21, 1,10,11,12, 7,13,18,22, 9,15,19,23,
281
                                                    0,18,2,7, 3,13,1,22, 5,9,8,19, 14,23,11,15, 4,21,6,10, 17,20,12,16 };
282
    return mObjectQuats[mQuatIndex[cubit]];
283
    }
284

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286

    
287
  private ObjectShape getCornerShape()
288
    {
289
    final float INIT_ALPHA = (float)Math.asin(1/(3*DIAMETER_RATIO));
290
    final float STEP_CORNER= (float)((Math.PI/2-2*INIT_ALPHA)/NUMBER_CORNER_SEGMENTS);
291
    final int SINGLE_ARC = NUMBER_CORNER_SEGMENTS+1;
292
    final int SINGLE_INNER_ARC = (NUMBER_CORNER_SEGMENTS+1)/2;
293
    final int NUM_VERTICES = 4 + 3*SINGLE_ARC + 1 + 3*SINGLE_INNER_ARC;
294
    float[][] tmp = new float[SINGLE_ARC][2];
295

    
296
    for(int i=0; i<SINGLE_ARC; i++)
297
      {
298
      float alpha = INIT_ALPHA + i*STEP_CORNER;
299
      tmp[i][0] = (float)(1.5f*DIAMETER_RATIO*Math.sin(alpha) - 1.0f);
300
      tmp[i][1] = (float)(1.5f*DIAMETER_RATIO*Math.cos(alpha) - 1.0f);
301
      }
302

    
303
    float[][] vertices = new float[NUM_VERTICES][];
304

    
305
    vertices[0] = new float[] { +0.5f, +0.5f, +0.5f };
306
    vertices[1] = new float[] { -0.5f, +0.5f, +0.5f };
307
    vertices[2] = new float[] { +0.5f, -0.5f, +0.5f };
308
    vertices[3] = new float[] { +0.5f, +0.5f, -0.5f };
309

    
310
    for(int i=0; i<SINGLE_ARC; i++)
311
      {
312
      float s = tmp[i][0];
313
      float c = tmp[i][1];
314

    
315
      vertices[4             +i] = new float[] {0.5f,+s,+c};
316
      vertices[4+  SINGLE_ARC+i] = new float[] {+c,0.5f,+s};
317
      vertices[4+2*SINGLE_ARC+i] = new float[] {+s,+c,0.5f};
318
      }
319

    
320
    final float EXTRA = (NUMBER_CORNER_SEGMENTS%2)==0 ? 1.0f : (float)Math.cos((Math.PI/2-2*INIT_ALPHA)/(2*NUMBER_CORNER_SEGMENTS));
321
    final float LEN = 1.5f*DIAMETER_RATIO*EXTRA;
322
    final float M = (float)(LEN*Math.sin(Math.PI/4) - 1.0f);
323
    vertices[4+3*SINGLE_ARC] = new float[] {M,M,M};
324

    
325
    for(int i=0; i<SINGLE_INNER_ARC; i++)
326
      {
327
      float s = tmp[i][0];
328
      float c = tmp[i][1];
329

    
330
      vertices[4+3*SINGLE_ARC+1                   +i] = new float[] {s,c,c};
331
      vertices[4+3*SINGLE_ARC+1+  SINGLE_INNER_ARC+i] = new float[] {c,s,c};
332
      vertices[4+3*SINGLE_ARC+1+2*SINGLE_INNER_ARC+i] = new float[] {c,c,s};
333
      }
334

    
335
    final int NUM_FACES = 6 + 3*NUMBER_CORNER_SEGMENTS;
336
    final int NUM_VERTS = 4 +   NUMBER_CORNER_SEGMENTS;
337

    
338
    int[][] indices = new int[NUM_FACES][];
339

    
340
    indices[0] = new int[NUM_VERTS];
341
    indices[1] = new int[NUM_VERTS];
342
    indices[2] = new int[NUM_VERTS];
343

    
344
    indices[0][0] = 3;
345
    indices[0][1] = 0;
346
    indices[0][2] = 2;
347
    indices[1][0] = 1;
348
    indices[1][1] = 0;
349
    indices[1][2] = 3;
350
    indices[2][0] = 2;
351
    indices[2][1] = 0;
352
    indices[2][2] = 1;
353

    
354
    for(int i=0; i<SINGLE_ARC; i++)
355
      {
356
      indices[0][3+i] = 4+i;
357
      indices[1][3+i] = 4+i+  SINGLE_ARC;
358
      indices[2][3+i] = 4+i+2*SINGLE_ARC;
359
      }
360

    
361
    indices[3] = new int[] { 1, 4+2*SINGLE_ARC-1, 4+3*SINGLE_ARC+1                   , 4+2*SINGLE_ARC};
362
    indices[4] = new int[] { 2, 4+3*SINGLE_ARC-1, 4+3*SINGLE_ARC+1+  SINGLE_INNER_ARC, 4             };
363
    indices[5] = new int[] { 3, 4+  SINGLE_ARC-1, 4+3*SINGLE_ARC+1+2*SINGLE_INNER_ARC, 4+  SINGLE_ARC};
364

    
365
    int start,i0,i1,i2,i3;
366
    int MID = (NUMBER_CORNER_SEGMENTS)/2;
367
    int MID2= (NUMBER_CORNER_SEGMENTS+1)/2;
368

    
369
    if( (NUMBER_CORNER_SEGMENTS%2) == 0 )
370
      {
371
      start = 12;
372
      indices[ 6] = new int[] { 4+3*SINGLE_ARC, 4+SINGLE_ARC+MID, 4+SINGLE_ARC+MID-1, 4+3*SINGLE_ARC+1+2*SINGLE_INNER_ARC+MID-1};
373
      indices[ 7] = new int[] { 4+3*SINGLE_ARC, 4+3*SINGLE_ARC+1+MID-1,  4+SINGLE_ARC+MID+1, 4+SINGLE_ARC+MID};
374
      indices[ 8] = new int[] { 4+3*SINGLE_ARC, 4+3*SINGLE_ARC+1+2*SINGLE_INNER_ARC+MID-1, 4+MID+1, 4+MID };
375
      indices[ 9] = new int[] { 4+3*SINGLE_ARC, 4+MID, 4+MID-1, 4+3*SINGLE_ARC+1+SINGLE_INNER_ARC+MID-1 };
376
      indices[10] = new int[] { 4+3*SINGLE_ARC, 4+2*SINGLE_ARC+MID, 4+2*SINGLE_ARC+MID-1, 4+3*SINGLE_ARC+1+MID-1 };
377
      indices[11] = new int[] { 4+3*SINGLE_ARC, 4+3*SINGLE_ARC+1+SINGLE_INNER_ARC+MID-1, 4+2*SINGLE_ARC+MID+1, 4+2*SINGLE_ARC+MID };
378
      }
379
    else
380
      {
381
      start = 9;
382
      indices[ 6] = new int[] { 4+3*SINGLE_ARC, 4+3*SINGLE_ARC+1+MID, 4+SINGLE_ARC+MID+1, 4+SINGLE_ARC+MID, 4+3*SINGLE_ARC+1+2*SINGLE_INNER_ARC+MID};
383
      indices[ 7] = new int[] { 4+3*SINGLE_ARC, 4+3*SINGLE_ARC+1+2*SINGLE_INNER_ARC+MID,  4+MID+1, 4+MID, 4+3*SINGLE_ARC+1+SINGLE_INNER_ARC+MID};
384
      indices[ 8] = new int[] { 4+3*SINGLE_ARC, 4+3*SINGLE_ARC+1+SINGLE_INNER_ARC+MID, 4+2*SINGLE_ARC+MID+1, 4+2*SINGLE_ARC+MID, 4+3*SINGLE_ARC+1+MID};
385
      }
386

    
387
    for(int j=0; j<MID2-1; j++)
388
      {
389
      i0 = 4+3*SINGLE_ARC+1+2*SINGLE_INNER_ARC+j;
390
      i1 = 4+3*SINGLE_ARC+1+2*SINGLE_INNER_ARC+j+1;
391
      i2 = 4+SINGLE_ARC+j+1;
392
      i3 = 4+SINGLE_ARC+j;
393

    
394
      indices[start+j] = new int[] {i0,i1,i2,i3};
395

    
396
      i0 = 4+3*SINGLE_ARC+1+2*SINGLE_INNER_ARC+j+1;
397
      i1 = 4+3*SINGLE_ARC+1+2*SINGLE_INNER_ARC+j;
398
      i2 = 4+(SINGLE_ARC-1)-j;
399
      i3 = 4+(SINGLE_ARC-1)-(j+1);
400

    
401
      indices[start+j+(MID2-1)] = new int[] {i0,i1,i2,i3};
402

    
403
      i0 = 4+3*SINGLE_ARC+1+j;
404
      i1 = 4+3*SINGLE_ARC+1+j+1;
405
      i2 = 4+2*SINGLE_ARC+j+1;
406
      i3 = 4+2*SINGLE_ARC+j;
407

    
408
      indices[start+j+2*(MID2-1)] = new int[] {i0,i1,i2,i3};
409

    
410
      i0 = 4+3*SINGLE_ARC+1+j+1;
411
      i1 = 4+3*SINGLE_ARC+1+j;
412
      i2 = 4+(2*SINGLE_ARC-1)-j;
413
      i3 = 4+(2*SINGLE_ARC-1)-(j+1);
414

    
415
      indices[start+j+3*(MID2-1)] = new int[] {i0,i1,i2,i3};
416

    
417
      i0 = 4+3*SINGLE_ARC+1+SINGLE_INNER_ARC+j;
418
      i1 = 4+3*SINGLE_ARC+1+SINGLE_INNER_ARC+j+1;
419
      i2 = 4+j+1;
420
      i3 = 4+j;
421

    
422
      indices[start+j+4*(MID2-1)] = new int[] {i0,i1,i2,i3};
423

    
424
      i0 = 4+3*SINGLE_ARC+1+SINGLE_INNER_ARC+j+1;
425
      i1 = 4+3*SINGLE_ARC+1+SINGLE_INNER_ARC+j;
426
      i2 = 4+(3*SINGLE_ARC-1)-j;
427
      i3 = 4+(3*SINGLE_ARC-1)-(j+1);
428

    
429
      indices[start+j+5*(MID2-1)] = new int[] {i0,i1,i2,i3};
430
      }
431

    
432
    return new ObjectShape(vertices,indices);
433
    }
434

    
435
///////////////////////////////////////////////////////////////////////////////////////////////////
436

    
437
  private ObjectShape getEdgeShape()
438
    {
439
    final int NUM_VERTICES = 8 + 3*(NUMBER_EDGE_SEGMENTS-1);
440
    final float INIT_ALPHA = (float)Math.asin(1/(3*DIAMETER_RATIO));
441
    final float H = 0.5f*((float)Math.sqrt(9*DIAMETER_RATIO*DIAMETER_RATIO-1))-1.0f;
442
    float[][] vertices = new float[NUM_VERTICES][];
443

    
444
    vertices[0] = new float[] {-0.5f,+0.5f,+0.5f};
445
    vertices[1] = new float[] {+0.5f,+0.5f,+0.5f};
446
    vertices[2] = new float[] {-0.5f,    H,+0.5f};
447
    vertices[3] = new float[] {+0.5f,    H,+0.5f};
448
    vertices[4] = new float[] {-0.5f,+0.5f,    H};
449
    vertices[5] = new float[] {+0.5f,+0.5f,    H};
450
    vertices[6] = new float[] {-0.5f,    H,    H};
451
    vertices[7] = new float[] {+0.5f,    H,    H};
452

    
453
    final int NUM_VERTS = NUMBER_EDGE_SEGMENTS-1;
454
    for(int i=0; i<NUM_VERTS; i++)
455
      {
456
      float beta = INIT_ALPHA*((2.0f*(i+1))/NUMBER_EDGE_SEGMENTS -1 );
457
      float A = (float)(1.5f*DIAMETER_RATIO*Math.sin(beta));
458
      float B = (float)(1.5f*DIAMETER_RATIO*Math.cos(beta)-1.0f);
459
      vertices[8            +i] = new float[] {A,B,0.5f};
460
      vertices[8+  NUM_VERTS+i] = new float[] {A,0.5f,B};
461
      vertices[8+2*NUM_VERTS+i] = new float[] {A,B,B};
462
      }
463

    
464
    final int NUM_FACES = 4 + 2*NUMBER_EDGE_SEGMENTS;
465
    int[][] indices = new int[NUM_FACES][];
466

    
467
    int NUMV = 3+NUMBER_EDGE_SEGMENTS;
468

    
469
    indices[0] = new int[NUMV];
470
    indices[0][0] = 3;
471
    indices[0][1] = 1;
472
    indices[0][2] = 0;
473
    indices[0][3] = 2;
474
    for(int i=0; i<NUM_VERTS; i++) indices[0][4+i] = 8+i;
475

    
476
    indices[1] = new int[NUMV];
477
    indices[1][0] = 4;
478
    indices[1][1] = 0;
479
    indices[1][2] = 1;
480
    indices[1][3] = 5;
481
    for(int i=0; i<NUM_VERTS; i++) indices[1][4+i] = 7+2*NUM_VERTS-i;
482

    
483
    indices[2] = new int[] {5,1,3,7};
484
    indices[3] = new int[] {0,4,6,2};
485
    indices[4] = new int[] {8,2,6,8+2*NUM_VERTS};
486
    indices[5] = new int[] {3,7+NUM_VERTS,7+3*NUM_VERTS,7};
487
    indices[6] = new int[] {6,4,8+NUM_VERTS,8+2*NUM_VERTS};
488
    indices[7] = new int[] {5,7,7+3*NUM_VERTS,7+2*NUM_VERTS};
489

    
490
    int i0,i1,i2,i3;
491

    
492
    for(int i=0; i<NUMBER_EDGE_SEGMENTS-2; i++)
493
      {
494
      i0 = 9+i;
495
      i1 = 8+i;
496
      i2 = 8+2*NUM_VERTS+i;
497
      i3 = 9+2*NUM_VERTS+i;
498

    
499
      indices[8+i] = new int[] {i0,i1,i2,i3};
500

    
501
      i0 = 9+2*NUM_VERTS+i;
502
      i1 = 8+2*NUM_VERTS+i;
503
      i2 = 8+NUM_VERTS+i;
504
      i3 = 9+NUM_VERTS+i;
505

    
506
      indices[8+NUMBER_EDGE_SEGMENTS-2+i] = new int[] {i0,i1,i2,i3};
507
      }
508

    
509
    return new ObjectShape(vertices,indices);
510
    }
511

    
512
///////////////////////////////////////////////////////////////////////////////////////////////////
513

    
514
  private ObjectShape getCenterShape(float D)
515
    {
516
    float[][] vertices = new float[][]
517
        {
518
            {-0.5f,-0.5f,-0.5f+D},
519
            {-0.5f,-0.5f,+0.5f+D},
520
            {-0.5f,+0.5f,-0.5f+D},
521
            {-0.5f,+0.5f,+0.5f+D},
522
            {+0.5f,-0.5f,-0.5f+D},
523
            {+0.5f,-0.5f,+0.5f+D},
524
            {+0.5f,+0.5f,-0.5f+D},
525
            {+0.5f,+0.5f,+0.5f+D},
526
        };
527

    
528
    int[][] indices = new int[][]
529
        {
530
            {1,5,7,3},
531
            {5,4,6,7},
532
            {0,1,3,2},
533
            {3,7,6,2},
534
            {0,4,5,1},
535
            {4,0,2,6}
536
        };
537

    
538
    return new ObjectShape(vertices,indices);
539
    }
540

    
541
///////////////////////////////////////////////////////////////////////////////////////////////////
542

    
543
  private ObjectShape getBigCircleShape(float D)
544
    {
545
    final float INIT_ALPHA = (float)Math.asin(1/(3*DIAMETER_RATIO));
546
    final float H = 0.5f*((float)Math.sqrt(9*DIAMETER_RATIO*DIAMETER_RATIO-1))-1.0f;
547
    final int NUM_VERTICES = 8 + 2*(NUMBER_EDGE_SEGMENTS-1);
548
    float[][] vertices = new float[NUM_VERTICES][];
549

    
550
    vertices[0] = new float[] {-0.5f,-0.5f,+0.5f+D};
551
    vertices[1] = new float[] {-0.5f,-0.5f,-0.5f+D};
552
    vertices[2] = new float[] {+0.5f,-0.5f,+0.5f+D};
553
    vertices[3] = new float[] {+0.5f,-0.5f,-0.5f+D};
554
    vertices[4] = new float[] {-0.5f,    H,+0.5f+D};
555
    vertices[5] = new float[] {-0.5f,    H,-0.5f+D};
556
    vertices[6] = new float[] {+0.5f,    H,+0.5f+D};
557
    vertices[7] = new float[] {+0.5f,    H,-0.5f+D};
558

    
559
    final int NUM_VERTS = NUMBER_EDGE_SEGMENTS-1;
560
    for(int i=0; i<NUM_VERTS; i++)
561
      {
562
      float beta = INIT_ALPHA*((2.0f*(i+1))/NUMBER_EDGE_SEGMENTS -1 );
563
      float A = (float)(1.5f*DIAMETER_RATIO*Math.sin(beta));
564
      float B = (float)(1.5f*DIAMETER_RATIO*Math.cos(beta)-1.0f);
565
      vertices[8          +i] = new float[] {A,B,+0.5f+D};
566
      vertices[8+NUM_VERTS+i] = new float[] {A,B,-0.5f+D};
567
      }
568

    
569
    final int NUM_FACES = 5 + NUMBER_EDGE_SEGMENTS;
570
    int[][] indices = new int[NUM_FACES][];
571

    
572
    int NUMV = 4+NUM_VERTS;
573
    indices[0] = new int[NUMV];
574
    indices[0][0] = 4;
575
    indices[0][1] = 0;
576
    indices[0][2] = 2;
577
    indices[0][3] = 6;
578
    for(int i=0; i<NUM_VERTS; i++) indices[0][4+i] = 7+NUM_VERTS-i;
579

    
580
    indices[1] = new int[NUMV];
581
    indices[1][0] = 7;
582
    indices[1][1] = 3;
583
    indices[1][2] = 1;
584
    indices[1][3] = 5;
585
    for(int i=0; i<NUM_VERTS; i++) indices[1][4+i] = 8+NUM_VERTS+i;
586

    
587
    indices[2] = new int[] {7,3,2,6};
588
    indices[3] = new int[] {4,0,1,5};
589
    indices[4] = new int[] {1,3,2,0};
590

    
591
    indices[5] = new int[] {5,4,8,8+NUM_VERTS};
592
    indices[6] = new int[] {7+NUM_VERTS,6,7,7+2*NUM_VERTS};
593

    
594
    for(int i=0; i<NUMBER_EDGE_SEGMENTS-2; i++)
595
      {
596
      int i0 = 8+i;
597
      int i1 = 9+i;
598
      int i2 = 9+NUM_VERTS+i;
599
      int i3 = 8+NUM_VERTS+i;
600

    
601
      indices[7+i] = new int[] {i0,i1,i2,i3};
602
      }
603

    
604
    return new ObjectShape(vertices,indices);
605
    }
606

    
607
///////////////////////////////////////////////////////////////////////////////////////////////////
608

    
609
  private ObjectShape getSmallCircleShape(float D)
610
    {
611
    final float H = 0.5f*((float)Math.sqrt(9*DIAMETER_RATIO*DIAMETER_RATIO-1))-1.0f;
612
    final float INIT_ALPHA = (float)Math.asin(1/(3*DIAMETER_RATIO));
613
    final float STEP_CORNER= (float)((Math.PI/2-2*INIT_ALPHA)/NUMBER_CORNER_SEGMENTS);
614
    final int NUM_VERTICES = 6 + 2*(NUMBER_CORNER_SEGMENTS-1);
615
    float[][] vertices = new float[NUM_VERTICES][];
616

    
617
    vertices[0] = new float[] {-0.5f,    H, 0.5f+D};
618
    vertices[1] = new float[] {    H,-0.5f, 0.5f+D};
619
    vertices[2] = new float[] {-0.5f,-0.5f, 0.5f+D};
620
    vertices[3] = new float[] {-0.5f,    H,-0.5f+D};
621
    vertices[4] = new float[] {    H,-0.5f,-0.5f+D};
622
    vertices[5] = new float[] {-0.5f,-0.5f,-0.5f+D};
623

    
624
    for(int i=0; i<NUMBER_CORNER_SEGMENTS-1; i++)
625
      {
626
      float alpha = INIT_ALPHA + (i+1)*STEP_CORNER;
627
      float A = (float)(1.5f*DIAMETER_RATIO*Math.sin(alpha) - 1.0f);
628
      float B = (float)(1.5f*DIAMETER_RATIO*Math.cos(alpha) - 1.0f);
629

    
630
      vertices[6                       +i] = new float[] {A,B, 0.5f+D};
631
      vertices[5+NUMBER_CORNER_SEGMENTS+i] = new float[] {A,B,-0.5f+D};
632
      }
633

    
634
    final int NUM_FACES = 4 + NUMBER_CORNER_SEGMENTS;
635
    int[][] indices = new int[NUM_FACES][];
636

    
637
    int NUMV = 2+NUMBER_CORNER_SEGMENTS;
638
    indices[0] = new int[NUMV];
639
    indices[0][0] = 0;
640
    indices[0][1] = 2;
641
    indices[0][2] = 1;
642
    for(int i=3; i<NUMV; i++) indices[0][i] = 5+(NUMBER_CORNER_SEGMENTS-1)-(i-3);
643

    
644
    indices[1] = new int[NUMV];
645
    indices[1][0] = 4;
646
    indices[1][1] = 5;
647
    indices[1][2] = 3;
648
    for(int i=3; i<NUMV; i++) indices[1][i] = 5+NUMBER_CORNER_SEGMENTS+(i-3);
649

    
650
    indices[2] = new int[] {0,3,5,2};
651
    indices[3] = new int[] {1,2,5,4};
652

    
653
    indices[4] = new int[] {5+NUMBER_CORNER_SEGMENTS,3,0,6};
654
    indices[5] = new int[] {1,4,5+2*(NUMBER_CORNER_SEGMENTS-1),5+(NUMBER_CORNER_SEGMENTS-1)};
655

    
656
    for(int i=0; i<NUMBER_CORNER_SEGMENTS-2; i++)
657
      {
658
      int i0 = 6+i;
659
      int i1 = 7+i;
660
      int i2 = 6+NUMBER_CORNER_SEGMENTS+i;
661
      int i3 = 5+NUMBER_CORNER_SEGMENTS+i;
662

    
663
      indices[6+i] = new int[] {i0,i1,i2,i3};
664
      }
665

    
666
    return new ObjectShape(vertices,indices);
667
    }
668

    
669
///////////////////////////////////////////////////////////////////////////////////////////////////
670

    
671
  public ObjectShape getObjectShape(int variant)
672
    {
673
    switch(variant)
674
      {
675
      case 0: return getCornerShape();
676
      case 1: return getEdgeShape();
677
      case 2: return getCenterShape(1.0f);
678
      case 3: return getBigCircleShape(1.0f);
679
      case 4: return getSmallCircleShape(1.02f);
680
      }
681

    
682
    return null;
683
    }
684

    
685
///////////////////////////////////////////////////////////////////////////////////////////////////
686

    
687
  public ObjectFaceShape getObjectFaceShape(int variant)
688
    {
689
    if( variant==0 )
690
      {
691
      float h1 = isInIconMode() ? 0.001f : 0.04f;
692
      float h2 = 0.001f;
693
      float[][] bands   = { {h1,45,0.3f,0.7f,5,0,0}, {h2,5,0.3f,0.2f,2,0,0} };
694
      final int NUM_BANDS = 6+3*NUMBER_CORNER_SEGMENTS;
695
      int[] bandIndices = new int[NUM_BANDS];
696
      bandIndices[0] = bandIndices[1] = bandIndices[2] = 0;
697
      for(int i=3; i<NUM_BANDS; i++) bandIndices[i] = 1;
698
      float[][] corners = { {0.02f,0.09f} };
699
      float[][] centers = { { 0.0f, 0.0f, 0.0f } };
700
      final int SINGLE_ARC = NUMBER_CORNER_SEGMENTS+1;
701
      final int SINGLE_INNER_ARC = (NUMBER_CORNER_SEGMENTS+1)/2;
702
      final int NUM_VERTICES = 4 + 3*SINGLE_ARC + 1 + 3*SINGLE_INNER_ARC;
703
      int[] indices = new int[NUM_VERTICES];
704
      indices[0] = indices[1] = indices[2] = indices[3] = 0;
705
      for(int i=4; i<NUM_VERTICES; i++) indices[i] = -1;
706
      return new ObjectFaceShape(bands,bandIndices,corners,indices,centers,indices,null);
707
      }
708
    if( variant==1 )
709
      {
710
      float h1 = isInIconMode() ? 0.001f : 0.03f;
711
      float[][] bands   = { {h1,45,0.2f,0.4f,5,0,0}, {0.001f,1,0.3f,0.5f,3,0,0}, {0.001f,1,0.3f,0.5f,2,0,0} };
712
      final int NUM_BANDS = 4 + 2*NUMBER_EDGE_SEGMENTS;
713
      int[] bandIndices = new int[NUM_BANDS];
714
      bandIndices[0] = bandIndices[1] = 0;
715
      bandIndices[2] = bandIndices[3] = 1;
716
      for(int i=4; i<NUM_BANDS; i++) bandIndices[i] = 2;
717
      float[][] corners = { {0.02f,0.09f} };
718
      float[][] centers = { { 0.0f, 0.0f, 0.0f } };
719
      final int NUM_VERTICES = 8 + 3*(NUMBER_EDGE_SEGMENTS-1);
720
      int[] indices = new int[NUM_VERTICES];
721
      indices[0] = indices[1] = indices[2] = indices[3] = indices[4] = indices[5] = 0;
722
      for(int i=6; i<NUM_VERTICES; i++) indices[i] = -1;
723
      return new ObjectFaceShape(bands,bandIndices,corners,indices,centers,indices,null);
724
      }
725
    if( variant==2 )
726
      {
727
      float h1 = isInIconMode() ? 0.001f : 0.05f;
728
      float[][] bands   = { {h1,45,0.2f,0.4f,5,0,0}, {0.001f,1,0.3f,0.5f,2,0,0} };
729
      int[] bandIndices = new int[] {0,1,1,1,1,1};
730
      float[][] corners = { {0.02f,0.09f} };
731
      float[][] centers = { { 0.0f, 0.0f, 1.0f } };
732
      int[] indices = new int[] {0,0,0,0,-1,-1,-1,-1};
733
      return new ObjectFaceShape(bands,bandIndices,corners,indices,centers,indices,null);
734
      }
735
    if( variant==3 )
736
      {
737
      float h1 = isInIconMode() ? 0.001f : 0.03f;
738
      float[][] bands   = { {h1,45,0.2f,0.4f,5,0,0}, {0.001f,1,0.3f,0.5f,3,0,0}, {0.001f,1,0.3f,0.5f,2,0,0} };
739
      final int NUM_BANDS = 5 + NUMBER_EDGE_SEGMENTS;
740
      int[] bandIndices = new int[NUM_BANDS];
741
      bandIndices[0] = 0;
742
      bandIndices[1] = 2;
743
      bandIndices[2] = bandIndices[3] = bandIndices[4] = 1;
744
      for(int i=5; i<NUM_BANDS; i++) bandIndices[i] = 2;
745
      float[][] corners = { {0.02f,0.09f} };
746
      float[][] centers = { { 0.0f, 0.0f, 1.0f } };
747
      final int NUM_VERTICES = 8 + 2*(NUMBER_EDGE_SEGMENTS-1);
748
      int[] indices = new int[NUM_VERTICES];
749
      for(int i=0; i<NUM_VERTICES; i++) indices[i] = -1;
750
      indices[0] = indices[2] = indices[4] = indices[6] = 0;
751
      return new ObjectFaceShape(bands,bandIndices,corners,indices,centers,indices,null);
752
      }
753
    else
754
      {
755
      float h1 = isInIconMode() ? 0.001f : 0.02f;
756
      float[][] bands   = { {h1,45,0.2f,0.4f,5,0,0}, {0.001f,1,0.3f,0.5f,3,0,0}, {0.001f,1,0.3f,0.5f,2,0,0} };
757
      final int NUM_BANDS = 4 + NUMBER_CORNER_SEGMENTS;
758
      int[] bandIndices = new int[NUM_BANDS];
759
      bandIndices[0] = 0;
760
      bandIndices[1] = 2;
761
      bandIndices[2] = bandIndices[3] = 1;
762
      for(int i=4; i<NUM_BANDS; i++) bandIndices[i] = 2;
763
      float[][] corners = { {0.02f,0.09f} };
764
      float[][] centers = { { 0.0f, 0.0f, 1.0f } };
765
      final int NUM_VERTICES = 6 + 2*(NUMBER_CORNER_SEGMENTS-1);
766
      int[] indices = new int[NUM_VERTICES];
767
      for(int i=0; i<NUM_VERTICES; i++) indices[i] = -1;
768
      indices[0] = indices[1] = indices[2] = 0;
769
      return new ObjectFaceShape(bands,bandIndices,corners,indices,centers,indices,null);
770
      }
771
    }
772

    
773
///////////////////////////////////////////////////////////////////////////////////////////////////
774

    
775
  public int getNumCubitVariants(int[] numLayers)
776
    {
777
    return 5;
778
    }
779

    
780
///////////////////////////////////////////////////////////////////////////////////////////////////
781

    
782
  public int getCubitVariant(int cubit, int[] numLayers)
783
    {
784
    if( cubit< 8 ) return 0;
785
    if( cubit<20 ) return 1;
786
    if( cubit<26 ) return 2;
787
    if( cubit<50 ) return 3;
788

    
789
    return 4;
790
    }
791

    
792
///////////////////////////////////////////////////////////////////////////////////////////////////
793

    
794
  public float getStickerRadius()
795
    {
796
    return 0.05f;
797
    }
798

    
799
///////////////////////////////////////////////////////////////////////////////////////////////////
800

    
801
  public float getStickerStroke()
802
    {
803
    return isInIconMode() ? 0.22f : 0.12f;
804
    }
805

    
806
///////////////////////////////////////////////////////////////////////////////////////////////////
807

    
808
  public float[][] getStickerAngles()
809
    {
810
    float D = (float)(Math.PI/8);
811
    return new float[][] { { 0,0,0,-D,0 },{ 0,0,0,-D },{0,0,0,0},{ 0,0,0,D },{ 0,0,D } };
812
    }
813

    
814
///////////////////////////////////////////////////////////////////////////////////////////////////
815
// PUBLIC API
816

    
817
  public Static3D[] getRotationAxis()
818
    {
819
    return ROT_AXIS;
820
    }
821

    
822
///////////////////////////////////////////////////////////////////////////////////////////////////
823

    
824
  public int[][] getBasicAngles()
825
    {
826
    if( mBasicAngle==null )
827
      {
828
      int[] tmp = new int[] {4,4,4};
829
      mBasicAngle = new int[][] { tmp,tmp,tmp };
830
      }
831

    
832
    return mBasicAngle;
833
    }
834

    
835
///////////////////////////////////////////////////////////////////////////////////////////////////
836

    
837
  public String getShortName()
838
    {
839
    return ObjectType.CRA1_3.name();
840
    }
841

    
842
///////////////////////////////////////////////////////////////////////////////////////////////////
843

    
844
  public ObjectSignature getSignature()
845
    {
846
    return new ObjectSignature(ObjectType.CRA1_3);
847
    }
848

    
849
///////////////////////////////////////////////////////////////////////////////////////////////////
850

    
851
  public String getObjectName()
852
    {
853
    return "Crazy 3x3";
854
    }
855

    
856
///////////////////////////////////////////////////////////////////////////////////////////////////
857

    
858
  public String getInventor()
859
    {
860
    return "Aleh Hladzilin";
861
    }
862

    
863
///////////////////////////////////////////////////////////////////////////////////////////////////
864

    
865
  public int getYearOfInvention()
866
    {
867
    return 2008;
868
    }
869

    
870
///////////////////////////////////////////////////////////////////////////////////////////////////
871

    
872
  public int getComplexity()
873
    {
874
    return 2;
875
    }
876

    
877
///////////////////////////////////////////////////////////////////////////////////////////////////
878

    
879
  public String[][] getTutorials()
880
    {
881
    return new String[][]{
882
                          {"gb","7xUE8ond_Mg","Crazy 3x3x3 Cube Tutorial","SuperAntoniovivaldi"},
883
                         };
884
    }
885
}
(9-9/40)