Project

General

Profile

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

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

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_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
import org.distorted.objectlib.metadata.Metadata;
22
import org.distorted.objectlib.helpers.ObjectVertexEffects;
23
import org.distorted.objectlib.main.InitAssets;
24
import org.distorted.objectlib.metadata.ListObjects;
25
import org.distorted.objectlib.scrambling.ScrambleEdgeGenerator;
26
import org.distorted.objectlib.shape.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
  private final int N = 6;  // has to be even
41
  private final float D1 = 0.67f;
42
  private final float D2 = 0.99f;
43
  private final float PX = 0.6f;
44
  private final float PY = 0.6f;
45
  private final float PZ = 0.6f;
46

    
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
  public TwistyO2(int iconMode, Static4D quat, Static3D move, float scale, Metadata meta, InitAssets asset)
57
    {
58
    super(iconMode, meta.getNumLayers()[0], quat, move, scale, meta, asset);
59
    }
60

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

    
63
  @Override
64
  public void adjustStickerCoords()
65
    {
66
    final float A = 0.50f;
67
    final float B = 0.5f*D1;
68
    final float C = 0.50f;
69

    
70
    // stickers with holes are not collapsed into one; we need to repeat this 6 times
71
    // 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
  }
76

    
77
///////////////////////////////////////////////////////////////////////////////////////////////////
78

    
79
  public float[][][] getStickerAngles()
80
    {
81
    float A = (float)(Math.PI*0.999f);
82
    float[][] t = new float[][] { {-A,-A},{0,0,0,0} };
83
    return new float[][][] { t,t,t,t,t,t,{{A,A}} };
84
    }
85

    
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87

    
88
  @Override
89
  public float getPillowCoeff()
90
    {
91
    return 1.2f;
92
    }
93

    
94
///////////////////////////////////////////////////////////////////////////////////////////////////
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
// 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

    
110
  public int[][] getScrambleEdges()
111
    {
112
    if( mEdges==null )
113
      {
114
      mEdges = new int[][]
115
              {
116
                      {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
              };
119
      }
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
  private void generateCirclePoint(int index, float[] output, float y, float z)
219
    {
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
    output[0] = y*sin;
225
    output[1] = y*cos;
226
    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
        for(int j=0; j<N; j++) generateCirclePoint(j,ret[index++],D1,1);
261

    
262
        ret[index][0] = D1;
263
        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
      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

    
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
      float h = 0.0001f;
375
      float[][] bands = { {h, 25,0.2f,0.5f,5,0,0} };
376
      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
      float[][] corners = { {0.02f,0.10f} };
397
      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

    
401
      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

    
410
      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
    return 0.15f;
442
    }
443

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

    
446
  public float getStickerStroke()
447
    {
448
    return isInIconMode() ? 0.20f : 0.15f;
449
    }
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
    return ListObjects.O2_2.name();
477
    }
478

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

    
481
  public String[][] getTutorials()
482
    {
483
    return new String[][] {
484
                    {"gb","m1nHBUnGsZc","1x1x1 O2 Cube","Richie's EZCubing"},
485
                    {"tw","mcgD9iN4NHU","一階方塊 介紹+教學","不正常魔術方塊研究中心"},
486
                 };
487
    }
488
}
(39-39/59)