Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyBandagedMegaminx.java @ 3a0990b1

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.objects.TwistyMegaminx.MEGA_D;
13
import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.C2;
14
import static org.distorted.objectlib.touchcontrol.TouchControlDodecahedron.SIN54;
15

    
16
import org.distorted.library.main.DistortedLibrary;
17
import org.distorted.library.type.Static3D;
18
import org.distorted.library.type.Static4D;
19
import org.distorted.objectlib.bandaged.FactoryBandagedMegaminx;
20
import org.distorted.objectlib.helpers.ObjectFaceShape;
21
import org.distorted.objectlib.helpers.ObjectShape;
22
import org.distorted.objectlib.metadata.Metadata;
23
import org.distorted.objectlib.signature.ObjectSignature;
24
import org.distorted.objectlib.helpers.ObjectVertexEffects;
25
import org.distorted.objectlib.main.InitAssets;
26
import org.distorted.objectlib.scrambling.ObjectScrambler;
27
import org.distorted.objectlib.signature.ObjectSignatureMegaminx;
28

    
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30

    
31
public class TwistyBandagedMegaminx extends TwistyDodecahedron
32
{
33
  public static final int KILOMINX3 = 2; // don't change those values
34
  public static final int MEGAMINX3 = 3; // ( see ObjectSignature.areNeighboursMegaminx() )
35
  public static final int KILOMINX5 = 4; // ( and getShortName() here )
36
  public static final int MEGAMINX5 = 5;
37

    
38
  public static final String OBJECT_NAME_MEGAMINX = "LOCAL_MEGAMINX";
39
  public static final char MARKER = 'm'; // keep lowercase
40

    
41
  private static final Static4D QUAT = new Static4D(0,0,0,1);
42

    
43
  private static final float[] KILOMINX_CORNER = new float[] {0, 1.00f, 2*C2};
44
  private static final float[] MEGAMINX_CORNER = new float[] {0, 1.50f, 3*C2};
45
  private static final float[] MKILOMINX_CORNER= new float[] {0, 2.00f, 4*C2};
46
  private static final float[] GIGAMINX_CORNER = new float[] {0, 2.50f, 5*C2};
47
  private static final float[] MEGAMINX_EDGE   = new float[] {0, 0.00f, 3*C2};
48
  private static final float[] MKILOMINX_EDGE1 = new float[] {0, 1.00f, 4*C2};
49
  private static final float[] MKILOMINX_EDGE2 = new float[] {0,-1.00f, 4*C2};
50
  private static final float[] GIGAMINX_EDGE1  = new float[] {0, 0.00f, 5*C2};
51

    
52
  private static final float DB = (2.5f-MEGA_D)/10;
53
  private static final float XB = DB*5*SIN54;
54
  private static final float ZB = (1-DB)*5*C2 + DB*5*SIN54;
55
  private static final float[] GIGAMINX_EDGE2  = new float[] {XB, 0.00f, ZB };
56

    
57
  private static final float YC = (1.5f+6*C2+6*SIN54)/5;
58
  private static final float ZC = (3*C2+6*SIN54)/5;
59
  private static final float[] MEGAMINX_CENTER = new float[] {0, YC, ZC};
60
  private static final float[] MKILOMINX_CENTER= new float[] {0, 4*YC/3, 4*ZC/3};
61
  private static final float[] GIGAMINX_CENTER = new float[] {0, 5*YC/3, 5*ZC/3};
62

    
63
  private static final int KILO_CENT = 0;
64
  private static final int MEGA_CENT = 1;
65
  private static final int CORNER    = 2;
66
  private static final int KILO_EDGE1= 3;
67
  private static final int KILO_EDGE2= 4;
68
  private static final int MEGA_EDGE1= 5;
69
  private static final int MEGA_EDGE2= 6;
70
  private static final int OTHER     = 7;
71

    
72
  private static final int NUM_TYPES = 7;
73

    
74
  private int[] mCubitVariantMap;
75
  private int[] mTypeVariantMap;
76
  private boolean[] mIsNonStandard;
77
  private ObjectShape[] mTmpShapes;
78
  private int mNumVariants;
79
  private int[] mCorrectedNumLayers;
80
  private float[][] mPosition;
81
  private float[][] mOrigPosition;  // again problem with the (2,3,4,5) numLayersFormat vs the (3,3,5,5) format:
82
                                    // for FactoryBandagedMegaminx we have to keep the original, 'uncorrected' positions;
83
  private ObjectSignature mSignature;
84

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

    
87
  private float[][] correctPos(float corr, float[][] pos)
88
    {
89
    int numPos = pos.length;
90
    float[][] ret = new float[numPos][];
91

    
92
    for(int p=0; p<numPos; p++)
93
      {
94
      float[] po = pos[p];
95
      int len = po.length/3;
96
      ret[p] = new float[3*len];
97
      float[] re = ret[p];
98

    
99
      for(int i=0; i<len; i++)
100
        {
101
        re[3*i  ] = corr * po[3*i  ];
102
        re[3*i+1] = corr * po[3*i+1];
103
        re[3*i+2] = corr * po[3*i+2];
104
        }
105
      }
106

    
107
    return ret;
108
    }
109

    
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111

    
112
  private void correctVerts(float corr, float[][] verts)
113
    {
114
    for(float[] ve : verts)
115
      {
116
      ve[0] *= corr;
117
      ve[1] *= corr;
118
      ve[2] *= corr;
119
      }
120
    }
121

    
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

    
124
  private float[][] getPositions()
125
    {
126
    if( mPosition==null )
127
      {
128
      Metadata meta = getMetadata();
129
      mOrigPosition = meta.getPos();
130
      int param = meta.getParam();
131

    
132
      switch(param)
133
        {
134
        case KILOMINX3: mPosition = correctPos(1.50f,mOrigPosition); break;
135
        case KILOMINX5: mPosition = correctPos(1.25f,mOrigPosition); break;
136
        case MEGAMINX3:
137
        case MEGAMINX5: mPosition = mOrigPosition;
138
        }
139
      }
140

    
141
    return mPosition;
142
    }
143

    
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145
// numLayers that we get here from BandagedObjectMegaminx are in the format (3,3,5,5) - i.e. one
146
// that agrees with the format in the previous TwistyKilominx/TwistyMegaminx classes (and in
147
// TwistyDodecahedron!). But FactoryBandagedMegaminx requires the unified (2,3,4,5) format -
148
// translate here.
149

    
150
  private int[] correctNumLayers(int param)
151
    {
152
    switch(param)
153
      {
154
      case KILOMINX3: return new int[] {2,2,2,2,2,2};
155
      case MEGAMINX3: return new int[] {3,3,3,3,3,3};
156
      case KILOMINX5: return new int[] {4,4,4,4,4,4};
157
      case MEGAMINX5: return new int[] {5,5,5,5,5,5};
158
      }
159

    
160
    return null;
161
    }
162

    
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164

    
165
  private float[] figureOutCubitPos(int variant, int param)
166
    {
167
    if( mIsNonStandard[variant] )
168
      {
169
      int numCubits = mPosition.length;
170

    
171
      for(int cubit = 0; cubit<numCubits; cubit++)
172
        if( mCubitVariantMap[cubit]==variant ) return mOrigPosition[cubit];
173
      }
174
    else
175
      {
176
      // cubit is one of the 'standard' shapes. Here we have to statically return a position
177
      // because it may very well happen that a Kilominx' cubit 0 is not a CORNER but one of
178
      // the 'non-standard' shapes and the above procedure would return an improper pos!
179

    
180
      switch(param)
181
        {
182
        case KILOMINX3: return KILOMINX_CORNER;
183
        case MEGAMINX3: int type3 = getType(variant);
184

    
185
                        switch( type3 )
186
                          {
187
                          case  CORNER    : return MEGAMINX_CORNER;
188
                          case  MEGA_EDGE1: return MEGAMINX_EDGE;
189
                          case  MEGA_CENT : return MEGAMINX_CENTER;
190
                          default         : android.util.Log.e("D", "illegal type "+type3);
191
                          }
192
                        break;
193
        case KILOMINX5: int type4 = getType(variant);
194

    
195
                        switch( type4 )
196
                          {
197
                          case  CORNER    : return MKILOMINX_CORNER;
198
                          case  KILO_EDGE1: return MKILOMINX_EDGE1;
199
                          case  KILO_EDGE2: return MKILOMINX_EDGE2;
200
                          case  KILO_CENT : return MKILOMINX_CENTER;
201
                          default         : android.util.Log.e("D", "illegal type "+type4);
202
                          }
203
                        break;
204
        case MEGAMINX5: int type5 = getType(variant);
205

    
206
                        switch( type5 )
207
                          {
208
                          case  CORNER    : return GIGAMINX_CORNER;
209
                          case  MEGA_EDGE1: return GIGAMINX_EDGE1;
210
                          case  MEGA_EDGE2: return GIGAMINX_EDGE2;
211
                          case  MEGA_CENT : return GIGAMINX_CENTER;
212
                          default         : android.util.Log.e("D", "illegal type "+type5);
213
                          }
214
                        break;
215
        }
216
      }
217

    
218
    return null;
219
    }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

    
223
  private void produceTmpShape(int variant)
224
    {
225
    Metadata meta = getMetadata();
226
    int param = meta.getParam();
227
    float[] pos = figureOutCubitPos(variant,param);
228

    
229
    FactoryBandagedMegaminx factory = FactoryBandagedMegaminx.getInstance();
230
    mTmpShapes[variant] = factory.createIrregularShape(variant,pos);
231

    
232
    switch(param)
233
      {
234
      case KILOMINX3: correctVerts(1.50f,mTmpShapes[variant].getVertices()); break;
235
      case KILOMINX5: correctVerts(1.25f,mTmpShapes[variant].getVertices()); break;
236
      }
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240
// PUBLIC API
241

    
242
  public TwistyBandagedMegaminx(int iconMode, Static4D quat, Static3D move, float scale, Metadata meta, InitAssets asset)
243
    {
244
    super(iconMode, quat, move, scale, meta, asset);
245
    }
246

    
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248
// Computing scramble states of many a bandaged objects takes way too long time and too much space.
249
// Return null here and turn to construction of scramble tables just-in-time (scrambleType=2)
250

    
251
  public int[][] getScrambleEdges()
252
    {
253
    return null;
254
    }
255

    
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257

    
258
  @Override
259
  public int[][] getScrambleAlgorithms()
260
    {
261
    return null;
262
    }
263

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

    
266
  @Override
267
  public int getScrambleType()
268
    {
269
    return ObjectScrambler.SCRAMBLING_BANDAGED;
270
    }
271

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273

    
274
  public ObjectShape getObjectShape(int variant)
275
    {
276
    if( mTmpShapes==null ) mTmpShapes = new ObjectShape[mNumVariants];
277
    if( mTmpShapes[variant]==null ) produceTmpShape(variant);
278
    return mTmpShapes[variant];
279
    }
280

    
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

    
283
  public Static4D getCubitQuats(int cubit, int[] numLayers)
284
    {
285
    float[] pos = mOrigPosition[cubit];
286
    return pos.length>3 ? QUAT : FactoryBandagedMegaminx.getInstance().getCubitQuat(pos[0],pos[1],pos[2]);
287
    }
288

    
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290

    
291
  private int getType(int variant)
292
    {
293
    for(int t=0; t<NUM_TYPES; t++)
294
      if( mTypeVariantMap[t]==variant ) return t;
295

    
296
    return -1;
297
    }
298

    
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

    
301
  public ObjectVertexEffects getVertexEffects(int variant)
302
    {
303
    int[] numLayers = getNumLayers();
304
    int size = numLayers[0];
305
    boolean round = (DistortedLibrary.fastCompilationTF() && size<5 && !isInIconMode());
306

    
307
    FactoryBandagedMegaminx factory = FactoryBandagedMegaminx.getInstance();
308
    return factory.createVertexEffects(variant,round);
309
    }
310

    
311
///////////////////////////////////////////////////////////////////////////////////////////////////
312

    
313
  public ObjectFaceShape getObjectFaceShape(int variant)
314
    {
315
    FactoryBandagedMegaminx factory = FactoryBandagedMegaminx.getInstance();
316
    return factory.createIrregularFaceShape(variant, isInIconMode() );
317
    }
318

    
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320

    
321
  private int translateVariant(int size, int variant)
322
    {
323
    switch(size)
324
      {
325
      case 2: return KILO_CENT;
326
      case 3: return variant==0 ? CORNER : variant==1 ? MEGA_EDGE1 : MEGA_CENT;
327
      case 4: switch(variant)
328
                {
329
                case  0: return CORNER;
330
                case  1: return KILO_EDGE1;
331
                case  2: return KILO_EDGE2;
332
                default: return KILO_CENT;
333
                }
334
      case 5: switch(variant)
335
                {
336
                case  0: return CORNER;
337
                case  1: return MEGA_EDGE1;
338
                case  2: return MEGA_EDGE2;
339
                default: return MEGA_CENT;
340
                }
341
      }
342

    
343
    return -1;
344
    }
345

    
346
///////////////////////////////////////////////////////////////////////////////////////////////////
347

    
348
  public int getNumCubitVariants(int[] numLayers)
349
    {
350
    if( mNumVariants==0 )
351
      {
352
      int param = getMetadata().getParam();
353
      if( mCorrectedNumLayers==null ) mCorrectedNumLayers = correctNumLayers(param);
354
      int size = mCorrectedNumLayers==null ? -1 : mCorrectedNumLayers[0];
355
      float[][] positions = getPositions();
356
      boolean T0 = false;
357
      boolean T1 = false;
358
      boolean T2 = false;
359
      boolean T3 = false;
360
      boolean T4 = false;
361
      boolean T5 = false;
362
      boolean T6 = false;
363

    
364
      float corr=1.0f;
365
      if( size==2 ) corr=2.0f/3;
366
      else if( size==4 ) corr=4.0f/5;
367

    
368
      int numCubits = positions.length;
369
      mCubitVariantMap = new int[numCubits];
370
      mIsNonStandard = new boolean[numCubits];   // mNumVariants <= numCubits
371
      mTypeVariantMap = new int[NUM_TYPES];
372
      for(int i=0; i<NUM_TYPES; i++) mTypeVariantMap[i] = -1;
373

    
374
      FactoryBandagedMegaminx factory = FactoryBandagedMegaminx.getInstance();
375

    
376
      for (int cubit=0; cubit<numCubits; cubit++)
377
        {
378
        int type = OTHER;
379
        float[] pos = positions[cubit];
380

    
381
        if( pos.length==3 )
382
          {
383
          int variant = factory.getElementVariant(mCorrectedNumLayers, corr*pos[0], corr*pos[1], corr*pos[2]);
384
          type = translateVariant(size, variant);
385
          }
386

    
387
        switch (type)
388
          {
389
          case KILO_CENT : if (!T0) { T0 = true; mTypeVariantMap[type]=mNumVariants++; }
390
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
391
                           break;
392
          case MEGA_CENT : if (!T1) { T1 = true; mTypeVariantMap[type]=mNumVariants++; }
393
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
394
                           break;
395
          case CORNER    : if (!T2) { T2 = true; mTypeVariantMap[type]=mNumVariants++; }
396
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
397
                           break;
398
          case KILO_EDGE1: if (!T3) { T3 = true; mTypeVariantMap[type]=mNumVariants++; }
399
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
400
                           break;
401
          case KILO_EDGE2: if (!T4) { T4 = true; mTypeVariantMap[type]=mNumVariants++; }
402
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
403
                           break;
404
          case MEGA_EDGE1: if (!T5) { T5 = true; mTypeVariantMap[type]=mNumVariants++; }
405
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
406
                           break;
407
          case MEGA_EDGE2: if (!T6) { T6 = true; mTypeVariantMap[type]=mNumVariants++; }
408
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
409
                           break;
410
          default        : mIsNonStandard[mNumVariants] = true;
411
                           mCubitVariantMap[cubit] = mNumVariants++;
412
          }
413
        }
414

    
415
      factory.prepare(mNumVariants,mCorrectedNumLayers);
416
      }
417

    
418
    return mNumVariants;
419
    }
420

    
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422

    
423
  public float[][] getCubitPositions(int[] numLayers)
424
    {
425
    return getPositions();
426
    }
427

    
428
///////////////////////////////////////////////////////////////////////////////////////////////////
429

    
430
  public float[][] getCuts(int[] numLayers)
431
    {
432
    int param = getMetadata().getParam();
433
    int size = numLayers[0];
434
    float dist = (param==KILOMINX3 || param==KILOMINX5) ? 0.5f : 0.5f-MEGA_D;
435
    return genericGetCuts(size,dist);
436
    }
437

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

    
440
  public int getCubitVariant(int cubit, int[] numLayers)
441
    {
442
    return mCubitVariantMap[cubit];
443
    }
444

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

    
447
  public float getStickerRadius()
448
    {
449
    return 0.18f;
450
    }
451

    
452
///////////////////////////////////////////////////////////////////////////////////////////////////
453

    
454
  public float getStickerStroke()
455
    {
456
    int param = getMetadata().getParam();
457

    
458
    switch(param)
459
      {
460
      case KILOMINX3: return isInIconMode() ? 0.38f : 0.27f;
461
      case MEGAMINX3: return isInIconMode() ? 0.27f : 0.18f;
462
      case KILOMINX5: return isInIconMode() ? 0.38f : 0.26f;
463
      case MEGAMINX5: return isInIconMode() ? 0.40f : 0.18f;
464
      }
465

    
466
    return 0.0f;
467
    }
468

    
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470

    
471
  public float[][][] getStickerAngles()
472
    {
473
    return null;
474
    }
475

    
476
///////////////////////////////////////////////////////////////////////////////////////////////////
477

    
478
  public String getShortName()
479
    {
480
    if( mSignature==null ) mSignature = getSignature();
481
    int param = getMetadata().getParam();
482
    return MARKER+(param+"_"+mSignature.getString());
483
    }
484

    
485
///////////////////////////////////////////////////////////////////////////////////////////////////
486

    
487
  public ObjectSignature getSignature()
488
    {
489
    if( mSignature==null )
490
      {
491
      int param = getMetadata().getParam();
492
      mSignature = new ObjectSignatureMegaminx(param,mPosition);
493
      }
494
    return mSignature;
495
    }
496

    
497
///////////////////////////////////////////////////////////////////////////////////////////////////
498

    
499
  public String getObjectName()
500
    {
501
    return OBJECT_NAME_MEGAMINX;
502
    }
503

    
504
///////////////////////////////////////////////////////////////////////////////////////////////////
505

    
506
  public String getInventor()
507
    {
508
    return "??";
509
    }
510

    
511
///////////////////////////////////////////////////////////////////////////////////////////////////
512

    
513
  public int getYearOfInvention()
514
    {
515
    return 0;
516
    }
517

    
518
///////////////////////////////////////////////////////////////////////////////////////////////////
519

    
520
  public float getComplexity()
521
    {
522
    return 4;
523
    }
524

    
525
///////////////////////////////////////////////////////////////////////////////////////////////////
526

    
527
  public String[][] getTutorials()
528
    {
529
    return null;
530
    }
531
}
(5-5/59)