Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyO2.java @ 8f5116ec

1 ffd8c9e4 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
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_HEXAHEDRON;
13
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
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 ae9d9227 leszek
import org.distorted.objectlib.metadata.Metadata;
22 ffd8c9e4 leszek
import org.distorted.objectlib.helpers.ObjectVertexEffects;
23
import org.distorted.objectlib.main.InitAssets;
24 361fd0de leszek
import org.distorted.objectlib.metadata.ListObjects;
25 ffd8c9e4 leszek
import org.distorted.objectlib.scrambling.ScrambleEdgeGenerator;
26
import org.distorted.objectlib.shape.ShapeHexahedron;
27
import org.distorted.objectlib.touchcontrol.TouchControlHexahedron;
28
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30
31
public class TwistyO2 extends ShapeHexahedron
32
{
33
  static final Static3D[] ROT_AXIS = new Static3D[]
34
         {
35
                 new Static3D(1,0,0),
36
                 new Static3D(0,1,0),
37
                 new Static3D(0,0,1)
38
         };
39
40 341dfdd6 leszek
  private final int N = 6;  // has to be even
41 8de81d85 leszek
  private final float D1 = 0.67f;
42 341dfdd6 leszek
  private final float D2 = 0.99f;
43 8de81d85 leszek
  private final float PX = 0.6f;
44
  private final float PY = 0.6f;
45
  private final float PZ = 0.6f;
46 ffd8c9e4 leszek
47
  private int[][] mEdges;
48
  private int[][] mBasicAngle;
49
  private float[][] mCuts;
50
  private float[][] mPosition;
51
  private boolean[][] mRotatable;
52
  private int[] mQuatIndex;
53
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55
56 ae9d9227 leszek
  public TwistyO2(int iconMode, Static4D quat, Static3D move, float scale, Metadata meta, InitAssets asset)
57 ffd8c9e4 leszek
    {
58 ae9d9227 leszek
    super(iconMode, meta.getNumLayers()[0], quat, move, scale, meta, asset);
59 ffd8c9e4 leszek
    }
60
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62
63
  @Override
64
  public void adjustStickerCoords()
65
    {
66
    final float A = 0.50f;
67 8de81d85 leszek
    final float B = 0.5f*D1;
68 ffd8c9e4 leszek
    final float C = 0.50f;
69
70
    // stickers with holes are not collapsed into one; we need to repeat this 6 times
71 8f5116ec leszek
    // the hole loop needs to be first so that FactorySticker draws it first; otherwise there's a
72
    // slight artifact.
73
    float[][][] t = new float[][][] {  {{B,0},{-B,0}} , {{ A,-A},{A,A},{-A, A},{-A,-A}} };
74
    mStickerCoords = new float[][][][] { t,t,t,t,t,t, {{{ C,0},{-C,0}}} };
75 ffd8c9e4 leszek
  }
76
77
///////////////////////////////////////////////////////////////////////////////////////////////////
78
79
  public float[][][] getStickerAngles()
80
    {
81 8f5116ec leszek
    float A = (float)(Math.PI*0.999f);
82
    float[][] t = new float[][] { {-A,-A},{0,0,0,0} };
83 ffd8c9e4 leszek
    return new float[][][] { t,t,t,t,t,t,{{A,A}} };
84
    }
85
86 8de81d85 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
87
88
  @Override
89
  public float getPillowCoeff()
90
    {
91
    return 1.2f;
92
    }
93
94 ffd8c9e4 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
95
96
  @Override
97
  public float[][] returnRotationFactor()
98
    {
99
    float C = 1.5f;
100
    float[] f = new float[] { C,C };
101
    return new float[][] { f,f,f };
102
    }
103
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105 341dfdd6 leszek
// If the first move was a 180 deg rotation along any ax, we need to forbid the second move to
106
// also be a 180 deg rotation - because such a scramble can be solved with just one move.
107
// state 0: last move wasn't a 180 deg.
108
// state 1: last move was a 180 deg.
109 ffd8c9e4 leszek
110
  public int[][] getScrambleEdges()
111
    {
112
    if( mEdges==null )
113
      {
114 341dfdd6 leszek
      mEdges = new int[][]
115
              {
116 84e7e7c2 leszek
                      {0,0,1,0,2,1,3,0,4,0,5,1,6,0,7,0,8,1},
117
                      {0,0,1,0,    3,0,4,0,    6,0,7,0    }
118 341dfdd6 leszek
              };
119 ffd8c9e4 leszek
      }
120
121
    return mEdges;
122
    }
123
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125
126
  @Override
127
  public int[][] getScrambleAlgorithms()
128
    {
129
    setUpRotatable();
130
    return ScrambleEdgeGenerator.getScramblingAlgorithms(mBasicAngle, mRotatable);
131
    }
132
133
///////////////////////////////////////////////////////////////////////////////////////////////////
134
135
  public float[][] getCuts(int[] numLayers)
136
    {
137
    if( mCuts==null )
138
      {
139
      float[] cut = new float[] {0.5f};
140
      mCuts = new float[][] { cut,cut,cut };
141
      }
142
143
    return mCuts;
144
    }
145
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147
148
  private void setUpRotatable()
149
    {
150
    if( mRotatable==null )
151
      {
152
      boolean[] tmp = new boolean[] {true,false};
153
      mRotatable = new boolean[][] { tmp,tmp,tmp };
154
      }
155
    }
156
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158
159
  public boolean[][] getLayerRotatable(int[] numLayers)
160
    {
161
    setUpRotatable();
162
    return mRotatable;
163
    }
164
165
///////////////////////////////////////////////////////////////////////////////////////////////////
166
167
  public int getTouchControlType()
168
    {
169
    return TC_HEXAHEDRON;
170
    }
171
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173
174
  public int getTouchControlSplit()
175
    {
176
    return TYPE_NOT_SPLIT;
177
    }
178
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180
181
  public int[][][] getEnabled()
182
    {
183
    return new int[][][] { {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}} };
184
    }
185
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187
188
  public float[] getDist3D(int[] numLayers)
189
    {
190
    return TouchControlHexahedron.D3D;
191
    }
192
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194
195
  public Static3D[] getFaceAxis()
196
    {
197
    return TouchControlHexahedron.FACE_AXIS;
198
    }
199
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201
202
  public float[][] getCubitPositions(int[] numLayers)
203
    {
204
    if( mPosition==null ) mPosition = new float[][] { {PX,PY,PZ},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0} };
205
    return mPosition;
206
    }
207
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209
210
  public Static4D getCubitQuats(int cubit, int[] numLayers)
211
    {
212
    if( mQuatIndex==null ) mQuatIndex = new int[] { 0, 6,4,1,3,0,2 };
213
    return mObjectQuats[mQuatIndex[cubit]];
214
    }
215
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217
218 8de81d85 leszek
  private void generateCirclePoint(int index, float[] output, float y, float z)
219 ffd8c9e4 leszek
    {
220
    float alpha = (float)((Math.PI*index)/(2*N));
221
    float sin = (float)Math.sin(alpha);
222
    float cos = (float)Math.cos(alpha);
223
224 8de81d85 leszek
    output[0] = y*sin;
225
    output[1] = y*cos;
226 ffd8c9e4 leszek
    output[2] = z;
227
    }
228
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230
231
  private void rotateVertices(float[][] vertices, int start, int end, int quatIndex)
232
    {
233
    Static4D quat = mObjectQuats[quatIndex];
234
    float[] tmp = new float[4];
235
236
    for(int i=start; i<end; i++)
237
      {
238
      float[] v = vertices[i];
239
      QuatHelper.rotateVectorByQuat(tmp, v[0],v[1],v[2],1, quat);
240
241
      v[0] = tmp[0];
242
      v[1] = tmp[1];
243
      v[2] = tmp[2];
244
      }
245
    }
246
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248
249
  private float[][] getVertices(int variant)
250
    {
251
    if( variant==0 )
252
      {
253
      float[][] ret = new float[24*(N+4)][3];
254
      int index = 0;
255
256
      for(int i=0; i<24; i++)
257
        {
258
        int startIndex = index;
259
260 8de81d85 leszek
        for(int j=0; j<N; j++) generateCirclePoint(j,ret[index++],D1,1);
261 ffd8c9e4 leszek
262 8de81d85 leszek
        ret[index][0] = D1;
263 ffd8c9e4 leszek
        ret[index][1] = 0;
264
        ret[index][2] = 1;
265
        index++;
266
        ret[index][0] = 1;
267
        ret[index][1] = 0;
268
        ret[index][2] = 1;
269
        index++;
270
        ret[index][0] = 1;
271
        ret[index][1] = 1;
272
        ret[index][2] = 1;
273
        index++;
274
        ret[index][0] = 0;
275
        ret[index][1] = 1;
276
        ret[index][2] = 1;
277
        index++;
278
279
        rotateVertices(ret,startIndex,index,i);
280
281
        for(int j=0; j<N+4; j++)
282
          {
283
          float[] r = ret[startIndex+j];
284
          r[0] -= PX;
285
          r[1] -= PY;
286
          r[2] -= PZ;
287
          }
288
        }
289
290
      return ret;
291
      }
292
    else
293
      {
294
      float[][] ret = new float[8*N][3];
295
      int index = 0;
296
297 8de81d85 leszek
      for(int j=0; j<4*N; j++) generateCirclePoint(j,ret[index++],D1,1);
298
      for(int j=0; j<4*N; j++) generateCirclePoint(j,ret[index++],D2,0);
299 ffd8c9e4 leszek
300
      return ret;
301
      }
302
    }
303
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305
306
  public ObjectShape getObjectShape(int variant)
307
    {
308
    if( variant==0 )
309
      {
310
      int NUM = N/2 + 3;
311
312
      int[][][] indices = new int[6][8][NUM];
313
      int[][] quatIndices = new int[][] { {6,12,17,21}, {4,10,16,20}, {1,13,14,15}, {3,11,22,23}, {0,7,8,9}, {2,5,18,19} };
314
315
      for(int f=0; f<6; f++)
316
        for(int c=0; c<4; c++)
317
          {
318
          int index = quatIndices[f][c];
319
          int[] ind1 = indices[f][2*c];
320
          int[] ind2 = indices[f][2*c+1];
321
322
          for(int v=0; v<NUM-2; v++)
323
            {
324
            ind1[v] = index*(N+4) + v;
325
            ind2[v] = index*(N+4) + v + N/2;
326
            }
327
328
          ind1[NUM-2] = index*(N+4) + N+2;
329
          ind2[NUM-2] = index*(N+4) + N+1;
330
          ind1[NUM-1] = index*(N+4) + N+3;
331
          ind2[NUM-1] = index*(N+4) + N+2;
332
          }
333
334
      return new ObjectShape(getVertices(variant), indices);
335
      }
336
    else
337
      {
338
      int[][] indices = new int[4*N+2][];
339
      indices[0] = new int[4*N];
340
      indices[1] = new int[4*N];
341
342
      for(int i=0; i<4*N; i++)
343
        {
344
        indices[0][i] = 4*N-1-i;
345
        indices[1][i] = 4*N+i;
346
        }
347
348
      for(int i=2; i<4*N+1; i++)
349
        {
350
        indices[i] = new int[4];
351
352
        indices[i][0] = i-2;
353
        indices[i][1] = i-2 + 1;
354
        indices[i][2] = i-2 + 4*N+1;
355
        indices[i][3] = i-2 + 4*N;
356
        }
357
358
      indices[4*N+1] = new int[4];
359
      indices[4*N+1][0] = 4*N-1;
360
      indices[4*N+1][1] = 0;
361
      indices[4*N+1][2] = 4*N;
362
      indices[4*N+1][3] = 8*N-1;
363
364
      return new ObjectShape(getVertices(variant), indices);
365
      }
366
    }
367
368
///////////////////////////////////////////////////////////////////////////////////////////////////
369
370
  public ObjectFaceShape getObjectFaceShape(int variant)
371
    {
372
    if( variant==0 )
373
      {
374 8de81d85 leszek
      float h = 0.0001f;
375 341dfdd6 leszek
      float[][] bands = { {h, 25,0.2f,0.5f,5,0,0} };
376 ffd8c9e4 leszek
      int[] indices   = { 0,0,0,0,0,0 };
377
      return new ObjectFaceShape(bands,indices,null);
378
      }
379
    else
380
      {
381
      float h1 = isInIconMode() ? 0.001f : 0.038f;
382
      float h2 = 0.001f;
383
      float[][] bands = { {h2,35,0.3f,0.5f,2,0,0} , {h1,35,0.3f,0.3f,6,0,0} };
384
      int[] indices = new int[4*N+2];
385
      indices[0] = 1;
386
      return new ObjectFaceShape(bands,indices,null);
387
      }
388
    }
389
390
///////////////////////////////////////////////////////////////////////////////////////////////////
391
392
  public ObjectVertexEffects getVertexEffects(int variant)
393
    {
394
    if( variant==0 )
395
      {
396 8de81d85 leszek
      float[][] corners = { {0.02f,0.10f} };
397 ffd8c9e4 leszek
      float[][] centers = { { 0.0f, 0.0f, 0.0f} };
398
      int[] indices     = new int[24*(N+4)];
399
      for(int i=0; i<24*(N+4); i++) indices[i] = -1;
400 8de81d85 leszek
401 ffd8c9e4 leszek
      indices[          N+2] = 0;
402
      indices[   (N+4)+ N+2] = 0;
403
      indices[ 2*(N+4)+ N+2] = 0;
404
      indices[ 3*(N+4)+ N+2] = 0;
405
      indices[ 4*(N+4)+ N+2] = 0;
406
      indices[ 5*(N+4)+ N+2] = 0;
407
      indices[ 8*(N+4)+ N+2] = 0;
408
      indices[11*(N+4)+ N+2] = 0;
409 8de81d85 leszek
410 ffd8c9e4 leszek
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
411
      }
412
    else
413
      {
414
      float[][] corners = { {0.06f,0.20f} };
415
      float[][] centers = { { 0.0f,-0.75f,-0.75f} };
416
      int num = 8*N;
417
      int[] indices = new int[num];
418
      for(int i=0; i<num; i++) indices[i] = -1;
419
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
420
      }
421
    }
422
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424
425
  public int getNumCubitVariants(int[] numLayers)
426
    {
427
    return 2;
428
    }
429
430
///////////////////////////////////////////////////////////////////////////////////////////////////
431
432
  public int getCubitVariant(int cubit, int[] numLayers)
433
    {
434
    return cubit<1 ? 0:1;
435
    }
436
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438
439
  public float getStickerRadius()
440
    {
441 8de81d85 leszek
    return 0.15f;
442 ffd8c9e4 leszek
    }
443
444
///////////////////////////////////////////////////////////////////////////////////////////////////
445
446
  public float getStickerStroke()
447
    {
448 8de81d85 leszek
    return isInIconMode() ? 0.20f : 0.15f;
449 ffd8c9e4 leszek
    }
450
451
///////////////////////////////////////////////////////////////////////////////////////////////////
452
// PUBLIC API
453
454
  public Static3D[] getRotationAxis()
455
    {
456
    return ROT_AXIS;
457
    }
458
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460
461
  public int[][] getBasicAngles()
462
    {
463
    if( mBasicAngle ==null )
464
      {
465
      int[] tmp = new int[] {4,4};
466
      mBasicAngle = new int[][] { tmp,tmp,tmp };
467
      }
468
469
    return mBasicAngle;
470
    }
471
472
///////////////////////////////////////////////////////////////////////////////////////////////////
473
474
  public String getShortName()
475
    {
476 361fd0de leszek
    return ListObjects.O2_2.name();
477 ffd8c9e4 leszek
    }
478
479
///////////////////////////////////////////////////////////////////////////////////////////////////
480
481
  public String[][] getTutorials()
482
    {
483 2318a72a leszek
    return new String[][] {
484
                    {"gb","m1nHBUnGsZc","1x1x1 O2 Cube","Richie's EZCubing"},
485
                    {"tw","mcgD9iN4NHU","一階方塊 介紹+教學","不正常魔術方塊研究中心"},
486
                 };
487 ffd8c9e4 leszek
    }
488
}