Project

General

Profile

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

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

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.signature.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.signature.ObjectConstants;
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.TouchControlHexahedron;
30

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

    
33
public class TwistyO2 extends ShapeHexahedron
34
{
35
  static final Static3D[] ROT_AXIS = new Static3D[]
36
         {
37
                 new Static3D(1,0,0),
38
                 new Static3D(0,1,0),
39
                 new Static3D(0,0,1)
40
         };
41

    
42
  private final int N = 6;  // has to be even
43
  private final float D1 = 0.67f;
44
  private final float D2 = 0.99f;
45
  private final float PX = 0.6f;
46
  private final float PY = 0.6f;
47
  private final float PZ = 0.6f;
48

    
49
  private int[][] mEdges;
50
  private int[][] mBasicAngle;
51
  private float[][] mCuts;
52
  private float[][] mPosition;
53
  private boolean[][] mRotatable;
54
  private int[] mQuatIndex;
55

    
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57

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

    
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64
// ditto, manually provide the sticker coordinates.
65

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

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

    
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

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

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

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

    
95
///////////////////////////////////////////////////////////////////////////////////////////////////
96

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

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

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

    
122
    return mEdges;
123
    }
124

    
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126

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

    
134
///////////////////////////////////////////////////////////////////////////////////////////////////
135

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

    
144
    return mCuts;
145
    }
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148

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

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159

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

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

    
168
  public int getTouchControlType()
169
    {
170
    return TC_HEXAHEDRON;
171
    }
172

    
173
///////////////////////////////////////////////////////////////////////////////////////////////////
174

    
175
  public int getTouchControlSplit()
176
    {
177
    return TYPE_NOT_SPLIT;
178
    }
179

    
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181

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

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

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

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

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

    
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202

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

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

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

    
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218

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

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

    
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231

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

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

    
242
      v[0] = tmp[0];
243
      v[1] = tmp[1];
244
      v[2] = tmp[2];
245
      }
246
    }
247

    
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249

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

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

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

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

    
280
        rotateVertices(ret,startIndex,index,i);
281

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

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

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

    
301
      return ret;
302
      }
303
    }
304

    
305
///////////////////////////////////////////////////////////////////////////////////////////////////
306

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

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

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

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

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

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

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

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

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

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

    
365
      return new ObjectShape(getVertices(variant), indices);
366
      }
367
    }
368

    
369
///////////////////////////////////////////////////////////////////////////////////////////////////
370

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

    
391
///////////////////////////////////////////////////////////////////////////////////////////////////
392

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

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

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

    
424
///////////////////////////////////////////////////////////////////////////////////////////////////
425

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

    
431
///////////////////////////////////////////////////////////////////////////////////////////////////
432

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

    
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439

    
440
  public float getStickerRadius()
441
    {
442
    return 0.15f;
443
    }
444

    
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446

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

    
452
///////////////////////////////////////////////////////////////////////////////////////////////////
453
// PUBLIC API
454

    
455
  public Static3D[] getRotationAxis()
456
    {
457
    return ROT_AXIS;
458
    }
459

    
460
///////////////////////////////////////////////////////////////////////////////////////////////////
461

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

    
470
    return mBasicAngle;
471
    }
472

    
473
///////////////////////////////////////////////////////////////////////////////////////////////////
474

    
475
  public String getShortName()
476
    {
477
    return ObjectType.O2_2.name();
478
    }
479

    
480
///////////////////////////////////////////////////////////////////////////////////////////////////
481

    
482
  public ObjectSignature getSignature()
483
    {
484
    return new ObjectSignature(ObjectConstants.O2_2);
485
    }
486

    
487
///////////////////////////////////////////////////////////////////////////////////////////////////
488

    
489
  public String getObjectName()
490
    {
491
    return "O2 Cube";
492
    }
493

    
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495

    
496
  public String getInventor()
497
    {
498
    return "Alexander Sosnovsky";
499
    }
500

    
501
///////////////////////////////////////////////////////////////////////////////////////////////////
502

    
503
  public int getYearOfInvention()
504
    {
505
    return 2019;
506
    }
507

    
508
///////////////////////////////////////////////////////////////////////////////////////////////////
509

    
510
  public float getComplexity()
511
    {
512
    return 0.1f;
513
    }
514

    
515
///////////////////////////////////////////////////////////////////////////////////////////////////
516

    
517
  public String[][] getTutorials()
518
    {
519
    return new String[][] {
520
                    {"gb","m1nHBUnGsZc","1x1x1 O2 Cube","Richie's EZCubing"},
521
                    {"tw","mcgD9iN4NHU","一階方塊 介紹+教學","不正常魔術方塊研究中心"},
522
                 };
523
    }
524
}
(39-39/57)