Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyO2.java @ 074a0284

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
// ditto, manually provide the sticker coordinates.
63

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

    
71
    // stickers with holes are not collapsed into one; we need to repeat this 6 times
72
    float[][][] t = new float[][][] { { { A,-A},{A,A},{-A, A},{-A,-A} } , { {B,0},{-B,0} } };
73
    mStickerCoords = new float[][][][] { t,t,t,t,t,t, { { { C,0},{-C,0} } } };
74
  }
75

    
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77

    
78
  public float[][][] getStickerAngles()
79
    {
80
    float A = (float)(Math.PI/2);
81
    float[][] t = new float[][] { {0,0,0,0},{-A,-A} };
82
    return new float[][][] { t,t,t,t,t,t,{{A,A}} };
83
    }
84

    
85
///////////////////////////////////////////////////////////////////////////////////////////////////
86

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

    
93
///////////////////////////////////////////////////////////////////////////////////////////////////
94

    
95
  @Override
96
  public float[][] returnRotationFactor()
97
    {
98
    float C = 1.5f;
99
    float[] f = new float[] { C,C };
100
    return new float[][] { f,f,f };
101
    }
102

    
103
///////////////////////////////////////////////////////////////////////////////////////////////////
104
// If the first move was a 180 deg rotation along any ax, we need to forbid the second move to
105
// also be a 180 deg rotation - because such a scramble can be solved with just one move.
106
// state 0: last move wasn't a 180 deg.
107
// state 1: last move was a 180 deg.
108

    
109
  public int[][] getScrambleEdges()
110
    {
111
    if( mEdges==null )
112
      {
113
      mEdges = new int[][]
114
              {
115
                      {0,0,1,0,2,1,3,0,4,0,5,1,6,0,7,0,8,1},
116
                      {0,0,1,0,    3,0,4,0,    6,0,7,0    }
117
              };
118
      }
119

    
120
    return mEdges;
121
    }
122

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

    
125
  @Override
126
  public int[][] getScrambleAlgorithms()
127
    {
128
    setUpRotatable();
129
    return ScrambleEdgeGenerator.getScramblingAlgorithms(mBasicAngle, mRotatable);
130
    }
131

    
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133

    
134
  public float[][] getCuts(int[] numLayers)
135
    {
136
    if( mCuts==null )
137
      {
138
      float[] cut = new float[] {0.5f};
139
      mCuts = new float[][] { cut,cut,cut };
140
      }
141

    
142
    return mCuts;
143
    }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146

    
147
  private void setUpRotatable()
148
    {
149
    if( mRotatable==null )
150
      {
151
      boolean[] tmp = new boolean[] {true,false};
152
      mRotatable = new boolean[][] { tmp,tmp,tmp };
153
      }
154
    }
155

    
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157

    
158
  public boolean[][] getLayerRotatable(int[] numLayers)
159
    {
160
    setUpRotatable();
161
    return mRotatable;
162
    }
163

    
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165

    
166
  public int getTouchControlType()
167
    {
168
    return TC_HEXAHEDRON;
169
    }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172

    
173
  public int getTouchControlSplit()
174
    {
175
    return TYPE_NOT_SPLIT;
176
    }
177

    
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

    
180
  public int[][][] getEnabled()
181
    {
182
    return new int[][][] { {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}} };
183
    }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186

    
187
  public float[] getDist3D(int[] numLayers)
188
    {
189
    return TouchControlHexahedron.D3D;
190
    }
191

    
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

    
194
  public Static3D[] getFaceAxis()
195
    {
196
    return TouchControlHexahedron.FACE_AXIS;
197
    }
198

    
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

    
201
  public float[][] getCubitPositions(int[] numLayers)
202
    {
203
    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} };
204
    return mPosition;
205
    }
206

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

    
209
  public Static4D getCubitQuats(int cubit, int[] numLayers)
210
    {
211
    if( mQuatIndex==null ) mQuatIndex = new int[] { 0, 6,4,1,3,0,2 };
212
    return mObjectQuats[mQuatIndex[cubit]];
213
    }
214

    
215
///////////////////////////////////////////////////////////////////////////////////////////////////
216

    
217
  private void generateCirclePoint(int index, float[] output, float y, float z)
218
    {
219
    float alpha = (float)((Math.PI*index)/(2*N));
220
    float sin = (float)Math.sin(alpha);
221
    float cos = (float)Math.cos(alpha);
222

    
223
    output[0] = y*sin;
224
    output[1] = y*cos;
225
    output[2] = z;
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  private void rotateVertices(float[][] vertices, int start, int end, int quatIndex)
231
    {
232
    Static4D quat = mObjectQuats[quatIndex];
233
    float[] tmp = new float[4];
234

    
235
    for(int i=start; i<end; i++)
236
      {
237
      float[] v = vertices[i];
238
      QuatHelper.rotateVectorByQuat(tmp, v[0],v[1],v[2],1, quat);
239

    
240
      v[0] = tmp[0];
241
      v[1] = tmp[1];
242
      v[2] = tmp[2];
243
      }
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247

    
248
  private float[][] getVertices(int variant)
249
    {
250
    if( variant==0 )
251
      {
252
      float[][] ret = new float[24*(N+4)][3];
253
      int index = 0;
254

    
255
      for(int i=0; i<24; i++)
256
        {
257
        int startIndex = index;
258

    
259
        for(int j=0; j<N; j++) generateCirclePoint(j,ret[index++],D1,1);
260

    
261
        ret[index][0] = D1;
262
        ret[index][1] = 0;
263
        ret[index][2] = 1;
264
        index++;
265
        ret[index][0] = 1;
266
        ret[index][1] = 0;
267
        ret[index][2] = 1;
268
        index++;
269
        ret[index][0] = 1;
270
        ret[index][1] = 1;
271
        ret[index][2] = 1;
272
        index++;
273
        ret[index][0] = 0;
274
        ret[index][1] = 1;
275
        ret[index][2] = 1;
276
        index++;
277

    
278
        rotateVertices(ret,startIndex,index,i);
279

    
280
        for(int j=0; j<N+4; j++)
281
          {
282
          float[] r = ret[startIndex+j];
283
          r[0] -= PX;
284
          r[1] -= PY;
285
          r[2] -= PZ;
286
          }
287
        }
288

    
289
      return ret;
290
      }
291
    else
292
      {
293
      float[][] ret = new float[8*N][3];
294
      int index = 0;
295

    
296
      for(int j=0; j<4*N; j++) generateCirclePoint(j,ret[index++],D1,1);
297
      for(int j=0; j<4*N; j++) generateCirclePoint(j,ret[index++],D2,0);
298

    
299
      return ret;
300
      }
301
    }
302

    
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304

    
305
  public ObjectShape getObjectShape(int variant)
306
    {
307
    if( variant==0 )
308
      {
309
      int NUM = N/2 + 3;
310

    
311
      int[][][] indices = new int[6][8][NUM];
312
      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} };
313

    
314
      for(int f=0; f<6; f++)
315
        for(int c=0; c<4; c++)
316
          {
317
          int index = quatIndices[f][c];
318
          int[] ind1 = indices[f][2*c];
319
          int[] ind2 = indices[f][2*c+1];
320

    
321
          for(int v=0; v<NUM-2; v++)
322
            {
323
            ind1[v] = index*(N+4) + v;
324
            ind2[v] = index*(N+4) + v + N/2;
325
            }
326

    
327
          ind1[NUM-2] = index*(N+4) + N+2;
328
          ind2[NUM-2] = index*(N+4) + N+1;
329
          ind1[NUM-1] = index*(N+4) + N+3;
330
          ind2[NUM-1] = index*(N+4) + N+2;
331
          }
332

    
333
      return new ObjectShape(getVertices(variant), indices);
334
      }
335
    else
336
      {
337
      int[][] indices = new int[4*N+2][];
338
      indices[0] = new int[4*N];
339
      indices[1] = new int[4*N];
340

    
341
      for(int i=0; i<4*N; i++)
342
        {
343
        indices[0][i] = 4*N-1-i;
344
        indices[1][i] = 4*N+i;
345
        }
346

    
347
      for(int i=2; i<4*N+1; i++)
348
        {
349
        indices[i] = new int[4];
350

    
351
        indices[i][0] = i-2;
352
        indices[i][1] = i-2 + 1;
353
        indices[i][2] = i-2 + 4*N+1;
354
        indices[i][3] = i-2 + 4*N;
355
        }
356

    
357
      indices[4*N+1] = new int[4];
358
      indices[4*N+1][0] = 4*N-1;
359
      indices[4*N+1][1] = 0;
360
      indices[4*N+1][2] = 4*N;
361
      indices[4*N+1][3] = 8*N-1;
362

    
363
      return new ObjectShape(getVertices(variant), indices);
364
      }
365
    }
366

    
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368

    
369
  public ObjectFaceShape getObjectFaceShape(int variant)
370
    {
371
    if( variant==0 )
372
      {
373
      float h = 0.0001f;
374
      float[][] bands = { {h, 25,0.2f,0.5f,5,0,0} };
375
      int[] indices   = { 0,0,0,0,0,0 };
376
      return new ObjectFaceShape(bands,indices,null);
377
      }
378
    else
379
      {
380
      float h1 = isInIconMode() ? 0.001f : 0.038f;
381
      float h2 = 0.001f;
382
      float[][] bands = { {h2,35,0.3f,0.5f,2,0,0} , {h1,35,0.3f,0.3f,6,0,0} };
383
      int[] indices = new int[4*N+2];
384
      indices[0] = 1;
385
      return new ObjectFaceShape(bands,indices,null);
386
      }
387
    }
388

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
  public ObjectVertexEffects getVertexEffects(int variant)
392
    {
393
    if( variant==0 )
394
      {
395
      float[][] corners = { {0.02f,0.10f} };
396
      float[][] centers = { { 0.0f, 0.0f, 0.0f} };
397
      int[] indices     = new int[24*(N+4)];
398
      for(int i=0; i<24*(N+4); i++) indices[i] = -1;
399

    
400
      indices[          N+2] = 0;
401
      indices[   (N+4)+ N+2] = 0;
402
      indices[ 2*(N+4)+ N+2] = 0;
403
      indices[ 3*(N+4)+ N+2] = 0;
404
      indices[ 4*(N+4)+ N+2] = 0;
405
      indices[ 5*(N+4)+ N+2] = 0;
406
      indices[ 8*(N+4)+ N+2] = 0;
407
      indices[11*(N+4)+ N+2] = 0;
408

    
409
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
410
      }
411
    else
412
      {
413
      float[][] corners = { {0.06f,0.20f} };
414
      float[][] centers = { { 0.0f,-0.75f,-0.75f} };
415
      int num = 8*N;
416
      int[] indices = new int[num];
417
      for(int i=0; i<num; i++) indices[i] = -1;
418
      return FactoryCubit.generateVertexEffect(getVertices(variant),corners,indices,centers,indices);
419
      }
420
    }
421

    
422
///////////////////////////////////////////////////////////////////////////////////////////////////
423

    
424
  public int getNumCubitVariants(int[] numLayers)
425
    {
426
    return 2;
427
    }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430

    
431
  public int getCubitVariant(int cubit, int[] numLayers)
432
    {
433
    return cubit<1 ? 0:1;
434
    }
435

    
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437

    
438
  public float getStickerRadius()
439
    {
440
    return 0.15f;
441
    }
442

    
443
///////////////////////////////////////////////////////////////////////////////////////////////////
444

    
445
  public float getStickerStroke()
446
    {
447
    return isInIconMode() ? 0.20f : 0.15f;
448
    }
449

    
450
///////////////////////////////////////////////////////////////////////////////////////////////////
451
// PUBLIC API
452

    
453
  public Static3D[] getRotationAxis()
454
    {
455
    return ROT_AXIS;
456
    }
457

    
458
///////////////////////////////////////////////////////////////////////////////////////////////////
459

    
460
  public int[][] getBasicAngles()
461
    {
462
    if( mBasicAngle ==null )
463
      {
464
      int[] tmp = new int[] {4,4};
465
      mBasicAngle = new int[][] { tmp,tmp,tmp };
466
      }
467

    
468
    return mBasicAngle;
469
    }
470

    
471
///////////////////////////////////////////////////////////////////////////////////////////////////
472

    
473
  public String getShortName()
474
    {
475
    return ListObjects.O2_2.name();
476
    }
477

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

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