Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyMirrorPyraminx.java @ 962b8ff6

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_CHANGING_MIRROR;
13
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
14

    
15
import org.distorted.library.type.Static3D;
16
import org.distorted.library.type.Static4D;
17
import org.distorted.objectlib.helpers.FactoryCubit;
18
import org.distorted.objectlib.helpers.FactoryShape;
19
import org.distorted.objectlib.helpers.ObjectFaceShape;
20
import org.distorted.objectlib.helpers.ObjectShape;
21
import org.distorted.objectlib.helpers.ObjectVertexEffects;
22
import org.distorted.objectlib.main.InitAssets;
23
import org.distorted.objectlib.metadata.ListObjects;
24
import org.distorted.objectlib.metadata.Metadata;
25
import org.distorted.objectlib.shape.ShapeTetrahedron;
26
import org.distorted.objectlib.touchcontrol.TouchControlTetrahedron;
27

    
28
///////////////////////////////////////////////////////////////////////////////////////////////////
29

    
30
public class TwistyMirrorPyraminx extends ShapeTetrahedron
31
{
32
  static final Static3D[] ROT_AXIS = new Static3D[]
33
    {
34
      new Static3D(     0,-SQ3/3,-SQ6/3),
35
      new Static3D(     0,-SQ3/3, SQ6/3),
36
      new Static3D( SQ6/3, SQ3/3,     0),
37
      new Static3D(-SQ6/3, SQ3/3,     0),
38
    };
39

    
40
  private static final int[] FACE_COLORS = new int[] { COLOR_WHITE };
41
  private static final float[] MIRROR_VEC = { 0.06f, 0.15f, 0.02f };
42

    
43
  private int[][] mEdges;
44
  private int[][] mBasicAngle;
45
  private float[][] mCuts;
46
  private float[][] mPositions;
47
  private ObjectShape[] mShapes;
48
  private float[][] mCutPlanes;
49
  private float[] mDist3D, mDist;
50
  private float[][] mPotentialVertices;
51

    
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53

    
54
  public TwistyMirrorPyraminx(int iconMode, Static4D quat, Static3D move, float scale, Metadata meta, InitAssets asset)
55
    {
56
    super(iconMode, meta.getNumLayers()[0], quat, move, scale, meta, asset);
57
    }
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60
// here we cannot automatically detect the outer monochromatic walls -> use the old way.
61

    
62
  @Override
63
  public int getSolvedFunctionIndex()
64
    {
65
    return 0;
66
    }
67

    
68
///////////////////////////////////////////////////////////////////////////////////////////////////
69

    
70
  @Override
71
  public int[][] getSolvedQuats()
72
    {
73
    return getOldSolvedQuats();
74
    }
75

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

    
78
  @Override
79
  public int getInternalColor()
80
    {
81
    return 0xff333333;
82
    }
83

    
84
///////////////////////////////////////////////////////////////////////////////////////////////////
85

    
86
  @Override
87
  public int[] getColorTable()
88
    {
89
    return FACE_COLORS;
90
    }
91

    
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93

    
94
  @Override
95
  public float[][] returnRotationFactor()
96
    {
97
    float[] f = { 1.4f, 1.8f, 2.5f };
98
    return new float[][] {f,f,f,f};
99
    }
100

    
101
///////////////////////////////////////////////////////////////////////////////////////////////////
102

    
103
  public int[][] getScrambleEdges()
104
    {
105
    if( mEdges==null )
106
      {
107
      int nL = getNumLayers()[0];
108
      mEdges = new int[nL][];
109

    
110
      for(int i=0; i<nL; i++)
111
        {
112
        int numEnabledMoves = 2*(nL-i);
113
        mEdges[i] = new int[4*2*numEnabledMoves];
114

    
115
        int index = 0;
116
        int startMove= 0;
117
        int offset = (i==nL-1 ? 2:0);  // if the last move was a tip, the only possible
118
                                       // next move is the second-to-largest layer.
119
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
120
        index += (2*numEnabledMoves);
121
        startMove += (2*nL);
122
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
123
        index += (2*numEnabledMoves);
124
        startMove += (2*nL);
125
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
126
        index += (2*numEnabledMoves);
127
        startMove += (2*nL);
128
        fillEdge(mEdges[i],index,startMove,offset,numEnabledMoves);
129
        }
130
      }
131

    
132
    return mEdges;
133
    }
134

    
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

    
137
  private void fillEdge(int[] edge, int index, int move, int offset, int num)
138
    {
139
    for(int i=0; i<num; i++)
140
      {
141
      edge[index+2*i  ] = (move+offset);
142
      edge[index+2*i+1] = (i+offset)/2;
143
      move++;
144
      }
145
    }
146

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

    
149
  public float[][] getCuts(int[] numLayers)
150
    {
151
    if( mCuts==null )
152
      {
153
      float[] c = { SQ6/12, 5*SQ6/12 };
154
      mCuts = new float[][] {c,c,c,c};
155
      }
156

    
157
    return mCuts;
158
    }
159

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

    
162
  public boolean[][] getLayerRotatable(int[] numLayers)
163
    {
164
    boolean[] tmp = {true,true,true};
165
    return new boolean[][] { tmp,tmp,tmp,tmp };
166
    }
167

    
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169

    
170
  public int getTouchControlType()
171
    {
172
    return TC_CHANGING_MIRROR;
173
    }
174

    
175
///////////////////////////////////////////////////////////////////////////////////////////////////
176

    
177
  public int getTouchControlSplit()
178
    {
179
    return TYPE_NOT_SPLIT;
180
    }
181

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183

    
184
  public int[][][] getEnabled()
185
    {
186
    return null;
187
    }
188

    
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190
// 'full' dists (not divided by numLayers)
191

    
192
  private float[] getDist()
193
    {
194
    if( mDist==null )
195
      {
196
      float DX = MIRROR_VEC[0];
197
      float DY = MIRROR_VEC[1];
198
      float DZ = MIRROR_VEC[2];
199
      Static3D[] axis = getFaceAxis();
200
      mDist = new float[4];
201

    
202
      for( int a=0; a<4; a++ )
203
        {
204
        Static3D ax = axis[a];
205
        float d = ax.get0()*DX + ax.get1()*DY + ax.get2()*DZ;
206
        mDist[a] = SQ6/4 + d;
207
        }
208
      }
209

    
210
    return mDist;
211
    }
212

    
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214
// 'regular' dists for the touchControl (have to be divided by numLayers)
215

    
216
  public float[] getDist3D(int[] numLayers)
217
    {
218
    if( mDist3D==null )
219
      {
220
      float[] d = getDist();
221
      mDist3D = new float[] { d[0]/3, d[1]/3, d[2]/3, d[3]/3 };
222
      }
223

    
224
    return mDist3D;
225
    }
226

    
227
///////////////////////////////////////////////////////////////////////////////////////////////////
228

    
229
  public Static3D[] getFaceAxis()
230
    {
231
    return TouchControlTetrahedron.FACE_AXIS;
232
    }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235

    
236
  private void addTetrahedralLattice(int size, int index, float[][] pos)
237
    {
238
    final float DX = 1.0f;
239
    final float DY = SQ2/2;
240
    final float DZ = 1.0f;
241

    
242
    float startX = 0.0f;
243
    float startY =-DY*(size-1)/2;
244
    float startZ = DZ*(size-1)/2;
245

    
246
    for(int layer=0; layer<size; layer++)
247
      {
248
      float currX = startX;
249
      float currY = startY;
250

    
251
      for(int x=0; x<layer+1; x++)
252
        {
253
        float currZ = startZ;
254

    
255
        for(int z=0; z<size-layer; z++)
256
          {
257
          pos[index] = new float[] {currX,currY,currZ};
258
          index++;
259
          currZ -= DZ;
260
          }
261

    
262
        currX += DX;
263
        }
264

    
265
      startX-=DX/2;
266
      startY+=DY;
267
      startZ-=DZ/2;
268
      }
269
    }
270

    
271
///////////////////////////////////////////////////////////////////////////////////////////////////
272

    
273
  private float[][] getPositions()
274
    {
275
    if( mPositions==null )
276
      {
277
      final float X = MIRROR_VEC[0];
278
      final float Y = MIRROR_VEC[1];
279
      final float Z = MIRROR_VEC[2];
280

    
281
      mPositions = new float[14][];
282

    
283
      addTetrahedralLattice(3, 0,mPositions);
284
      addTetrahedralLattice(2,10,mPositions);
285

    
286
      for( float[] pos : mPositions )
287
        {
288
        pos[0] += X;
289
        pos[1] += Y;
290
        pos[2] += Z;
291
        }
292
      }
293

    
294
    return mPositions;
295
    }
296

    
297

    
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299

    
300
  public float[][] getCubitPositions(int[] numLayers)
301
    {
302
    return getPositions();
303
    }
304

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

    
307
  public Static4D getCubitQuats(int cubit, int[] numLayers)
308
    {
309
    return mObjectQuats[0];
310
    }
311

    
312
///////////////////////////////////////////////////////////////////////////////////////////////////
313

    
314
  private void createCutPlanes()
315
    {
316
    int numPlanes = 3*4;
317
    mCutPlanes = new float[numPlanes][];
318
    Static3D[] faceAxis = getFaceAxis();
319
    float[] dist = getDist();
320
    int[] numLayers = getNumLayers();
321
    float[][] cuts = getCuts(numLayers);
322
    float cut0 = cuts[0][0];
323
    float cut1 = cuts[0][1];
324

    
325
    for(int p=0; p<4; p++)
326
      {
327
      Static3D ax = faceAxis[p];
328
      mCutPlanes[p] = new float[] { ax.get0(), ax.get1(), ax.get2(), dist[p] };
329
      }
330

    
331
    for(int p=4; p<8; p++)
332
      {
333
      Static3D ax = ROT_AXIS[p-4];
334
      mCutPlanes[p] = new float[] { ax.get0(), ax.get1(), ax.get2(), cut0 };
335
      }
336
    for(int p=8; p<12; p++)
337
      {
338
      Static3D ax = ROT_AXIS[p-8];
339
      mCutPlanes[p] = new float[] { ax.get0(), ax.get1(), ax.get2(), cut1 };
340
      }
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

    
345
  private float[] internalPoint(int variant)
346
    {
347
    float[][] pos = getPositions();
348
    float[] p = pos[variant];
349
    return new float[] { p[0],p[1],p[2] };
350
    }
351

    
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353

    
354
  public ObjectShape getObjectShape(int variant)
355
    {
356
    if( mShapes==null )
357
      {
358
      int[] numLayers = getNumLayers();
359
      int numV = getNumCubitVariants(numLayers);
360
      mShapes = new ObjectShape[numV];
361
      createCutPlanes();
362
      mPotentialVertices = FactoryShape.computePotentialVertices(mCutPlanes);
363
      }
364

    
365
    if( mShapes[variant]==null )
366
      {
367
      float[][] pos = getPositions();
368
      float[] point = internalPoint(variant);
369
      mShapes[variant] = FactoryShape.createShape(mCutPlanes,mPotentialVertices,pos[variant],point);
370
      }
371

    
372
    return mShapes[variant];
373
    }
374

    
375
///////////////////////////////////////////////////////////////////////////////////////////////////
376

    
377
  public ObjectFaceShape getObjectFaceShape(int variant)
378
    {
379
    ObjectShape shape = getObjectShape(variant);
380
    int[][] ind    = shape.getVertIndices();
381
    float[][] vert = shape.getVertices();
382
    float[][] pos  = getPositions();
383
    int[] indices  = FactoryShape.produceBandIndices(vert, pos[variant], ind, getFaceAxis(), getDist() );
384

    
385
    if( variant<10 )
386
      {
387
      int N = 5;
388
      int E = 0;
389
      float height = isInIconMode() ? 0.001f : 0.04f;
390
      float[][] bands = { {height,35,0.3f,0.5f,N,E,E}, {0.001f,35,0.3f,0.5f,N,E,E} };
391
      return new ObjectFaceShape(bands,indices,null);
392
      }
393
    else
394
      {
395
      int N = 5;
396
      int E = 0;
397
      float height = isInIconMode() ? 0.001f : 0.05f;
398
      float[][] bands = { {height,35,0.3f,0.5f,N,E,E}, {0.001f,35,0.3f,0.5f,N,E,E} };
399
      return new ObjectFaceShape(bands,indices,null);
400
      }
401
    }
402

    
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404

    
405
  private float[][] computeVertexEffectCenter(int variant)
406
    {
407
    float A = variant<4 ? -0.5f : -1.0f;
408

    
409
    float[][] positions = getPositions();
410
    float[] p = positions[variant];
411

    
412
    return new float[][] {{ A*p[0], A*p[1], A*p[2] }};
413
    }
414

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416

    
417
  public ObjectVertexEffects getVertexEffects(int variant)
418
    {
419
    ObjectShape shape  = getObjectShape(variant);
420
    float[][] vertices = shape.getVertices();
421
    float[][] centers  = computeVertexEffectCenter(variant);
422
    float[][] pos      = getPositions();
423
    int[] indices      = FactoryShape.computeVertexEffectsIndices(vertices, pos[variant], getFaceAxis(), getDist() );
424
    float[][] corners  = variant<10 ? new float[][]{{0.03f, 0.20f}} : new float[][]{{0.03f, 0.15f}};
425

    
426
    return FactoryCubit.generateVertexEffect(vertices,corners,indices,centers,indices);
427
    }
428

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

    
431
  public int getNumCubitVariants(int[] numLayers)
432
    {
433
    return 14;
434
    }
435

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

    
438
  public int getCubitVariant(int cubit, int[] numLayers)
439
    {
440
    return cubit;
441
    }
442

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

    
445
  public float getStickerRadius()
446
    {
447
    return 0.08f;
448
    }
449

    
450
///////////////////////////////////////////////////////////////////////////////////////////////////
451

    
452
  public float getStickerStroke()
453
    {
454
    return isInIconMode() ? 0.12f : 0.08f;
455
    }
456

    
457
///////////////////////////////////////////////////////////////////////////////////////////////////
458

    
459
  public float[][][] getStickerAngles()
460
    {
461
    return null;
462
    }
463

    
464
///////////////////////////////////////////////////////////////////////////////////////////////////
465
// PUBLIC API
466

    
467
  public Static3D[] getRotationAxis()
468
    {
469
    return ROT_AXIS;
470
    }
471

    
472
///////////////////////////////////////////////////////////////////////////////////////////////////
473

    
474
  public int[][] getBasicAngles()
475
    {
476
    if( mBasicAngle ==null )
477
      {
478
      int num = getNumLayers()[0];
479
      int[] tmp = new int[num];
480
      for(int i=0; i<num; i++) tmp[i] = 3;
481
      mBasicAngle = new int[][] { tmp,tmp,tmp,tmp };
482
      }
483

    
484
    return mBasicAngle;
485
    }
486

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

    
489
  public String getShortName()
490
    {
491
    return ListObjects.MPYR_3.name();
492
    }
493

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

    
496
  public String[][] getTutorials()
497
    {
498
    return null;
499
    }
500
}
(33-33/59)