Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyBandagedMegaminx.java @ 97a75106

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.signature.ObjectSignature;
23
import org.distorted.objectlib.helpers.ObjectVertexEffects;
24
import org.distorted.objectlib.main.InitAssets;
25
import org.distorted.objectlib.main.InitData;
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
      InitData data = getInitData();
129
      mOrigPosition = data.getPos();
130
      int param = data.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
    InitData data = getInitData();
226
    int param = data.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 meshState, int iconMode, Static4D quat, Static3D move, float scale, InitData data, InitAssets asset)
243
    {
244
    super(meshState, iconMode, quat, move, scale, data, 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
  private float[][] getVertices(int variant)
302
    {
303
    if( mTmpShapes==null ) mTmpShapes = new ObjectShape[mNumVariants];
304
    if( mTmpShapes[variant]==null ) produceTmpShape(variant);
305
    return mTmpShapes[variant].getVertices();
306
    }
307
*/
308
///////////////////////////////////////////////////////////////////////////////////////////////////
309

    
310
  public ObjectVertexEffects getVertexEffects(int variant)
311
    {
312
    int[] numLayers = getNumLayers();
313
    int size = numLayers[0];
314
    boolean round = (DistortedLibrary.fastCompilationTF() && size<5 && !isInIconMode());
315
/*
316
    int type = getType(variant);
317

    
318
    if( type>=0 )
319
      {
320
      float[][] vertices = getVertices(variant);
321
      int numV = vertices.length;
322
      float S = -0.04f;
323

    
324
      String name = EffectName.DEFORM.name();
325
      float[] reg = {0,0,0,0.15f};
326

    
327
      float[][] variables = new float[numV][];
328
      String[] names      = new String[numV];
329
      float[][] regions   = new float[numV][];
330
      boolean[] uses      = new boolean[numV];
331

    
332
      for(int i=0; i<numV; i++)
333
        {
334
        float[] v    = vertices[i];
335
        variables[i] = new float[] { 0, S*v[0], S*v[1], S*v[2], 1 };
336
        names[i]     = name;
337
        regions[i]   = reg;
338
        uses[i]      = round;
339
        }
340

    
341
      return new ObjectVertexEffects(names,variables,vertices,regions,uses);
342
      }
343
   */
344
    FactoryBandagedMegaminx factory = FactoryBandagedMegaminx.getInstance();
345
    return factory.createVertexEffects(variant,round);
346
    }
347

    
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349
/*
350
  private int[] createBandIndices(int type)
351
    {
352
    int[] bandIndices = null;
353

    
354
    switch(type)
355
      {
356
      case MEGA_CENT : bandIndices = new int[] {1,0,0,0,0,0};
357
                       break;
358
      case KILO_EDGE1:
359
      case KILO_EDGE2:
360
      case MEGA_EDGE1:
361
      case MEGA_EDGE2: bandIndices = new int[] {1,1,0,0,0,0};
362
                       break;
363
      case KILO_CENT :
364
      case CORNER    : bandIndices = new int[] {1,1,1,0,0,0};
365
                       break;
366
      }
367

    
368
    return new int[] {0,0,0,0,0,0};//bandIndices;
369
    }
370
*/
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

    
373
  public ObjectFaceShape getObjectFaceShape(int variant)
374
    {
375
    FactoryBandagedMegaminx factory = FactoryBandagedMegaminx.getInstance();
376
/*
377
    int type = getType(variant);
378

    
379
    if( type>=0 )
380
      {
381
      int param = getInitData().getParam();
382
      int[] numLayers = correctNumLayers(param);
383

    
384
      if( numLayers!=null )
385
        {
386
        boolean iconMode = isInIconMode();
387
        float[][] bands = factory.getBands(iconMode,numLayers);
388
        int[] bandIndices = createBandIndices(type);
389
        return new ObjectFaceShape(bands, bandIndices, null);
390
        }
391
      }
392
*/
393
    return factory.createIrregularFaceShape(variant, isInIconMode() );
394
    }
395

    
396
///////////////////////////////////////////////////////////////////////////////////////////////////
397

    
398
  private int translateVariant(int size, int variant)
399
    {
400
    switch(size)
401
      {
402
      case 2: return KILO_CENT;
403
      case 3: return variant==0 ? CORNER : variant==1 ? MEGA_EDGE1 : MEGA_CENT;
404
      case 4: switch(variant)
405
                {
406
                case  0: return CORNER;
407
                case  1: return KILO_EDGE1;
408
                case  2: return KILO_EDGE2;
409
                default: return KILO_CENT;
410
                }
411
      case 5: switch(variant)
412
                {
413
                case  0: return CORNER;
414
                case  1: return MEGA_EDGE1;
415
                case  2: return MEGA_EDGE2;
416
                default: return MEGA_CENT;
417
                }
418
      }
419

    
420
    return -1;
421
    }
422

    
423
///////////////////////////////////////////////////////////////////////////////////////////////////
424

    
425
  public int getNumCubitVariants(int[] numLayers)
426
    {
427
    if( mNumVariants==0 )
428
      {
429
      int param = getInitData().getParam();
430
      if( mCorrectedNumLayers==null ) mCorrectedNumLayers = correctNumLayers(param);
431
      int size = mCorrectedNumLayers==null ? -1 : mCorrectedNumLayers[0];
432
      float[][] positions = getPositions();
433
      boolean T0 = false;
434
      boolean T1 = false;
435
      boolean T2 = false;
436
      boolean T3 = false;
437
      boolean T4 = false;
438
      boolean T5 = false;
439
      boolean T6 = false;
440

    
441
      float corr=1.0f;
442
      if( size==2 ) corr=2.0f/3;
443
      else if( size==4 ) corr=4.0f/5;
444

    
445
      int numCubits = positions.length;
446
      mCubitVariantMap = new int[numCubits];
447
      mIsNonStandard = new boolean[numCubits];   // mNumVariants <= numCubits
448
      mTypeVariantMap = new int[NUM_TYPES];
449
      for(int i=0; i<NUM_TYPES; i++) mTypeVariantMap[i] = -1;
450

    
451
      FactoryBandagedMegaminx factory = FactoryBandagedMegaminx.getInstance();
452

    
453
      for (int cubit=0; cubit<numCubits; cubit++)
454
        {
455
        int type = OTHER;
456
        float[] pos = positions[cubit];
457

    
458
        if( pos.length==3 )
459
          {
460
          int variant = factory.getElementVariant(mCorrectedNumLayers, corr*pos[0], corr*pos[1], corr*pos[2]);
461
          type = translateVariant(size, variant);
462
          }
463

    
464
        switch (type)
465
          {
466
          case KILO_CENT : if (!T0) { T0 = true; mTypeVariantMap[type]=mNumVariants++; }
467
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
468
                           break;
469
          case MEGA_CENT : if (!T1) { T1 = true; mTypeVariantMap[type]=mNumVariants++; }
470
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
471
                           break;
472
          case CORNER    : if (!T2) { T2 = true; mTypeVariantMap[type]=mNumVariants++; }
473
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
474
                           break;
475
          case KILO_EDGE1: if (!T3) { T3 = true; mTypeVariantMap[type]=mNumVariants++; }
476
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
477
                           break;
478
          case KILO_EDGE2: if (!T4) { T4 = true; mTypeVariantMap[type]=mNumVariants++; }
479
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
480
                           break;
481
          case MEGA_EDGE1: if (!T5) { T5 = true; mTypeVariantMap[type]=mNumVariants++; }
482
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
483
                           break;
484
          case MEGA_EDGE2: if (!T6) { T6 = true; mTypeVariantMap[type]=mNumVariants++; }
485
                           mCubitVariantMap[cubit] = mTypeVariantMap[type];
486
                           break;
487
          default        : mIsNonStandard[mNumVariants] = true;
488
                           mCubitVariantMap[cubit] = mNumVariants++;
489
          }
490
        }
491

    
492
      factory.prepare(mNumVariants,mCorrectedNumLayers);
493
      }
494

    
495
    return mNumVariants;
496
    }
497

    
498
///////////////////////////////////////////////////////////////////////////////////////////////////
499

    
500
  public float[][] getCubitPositions(int[] numLayers)
501
    {
502
    return getPositions();
503
    }
504

    
505
///////////////////////////////////////////////////////////////////////////////////////////////////
506

    
507
  public float[][] getCuts(int[] numLayers)
508
    {
509
    int param = getInitData().getParam();
510
    int size = numLayers[0];
511
    float dist = (param==KILOMINX3 || param==KILOMINX5) ? 0.5f : 0.5f-MEGA_D;
512
    return genericGetCuts(size,dist);
513
    }
514

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

    
517
  public int getCubitVariant(int cubit, int[] numLayers)
518
    {
519
    return mCubitVariantMap[cubit];
520
    }
521

    
522
///////////////////////////////////////////////////////////////////////////////////////////////////
523

    
524
  public float getStickerRadius()
525
    {
526
    return 0.18f;
527
    }
528

    
529
///////////////////////////////////////////////////////////////////////////////////////////////////
530

    
531
  public float getStickerStroke()
532
    {
533
    int param = getInitData().getParam();
534

    
535
    switch(param)
536
      {
537
      case KILOMINX3: return isInIconMode() ? 0.38f : 0.27f;
538
      case MEGAMINX3: return isInIconMode() ? 0.27f : 0.18f;
539
      case KILOMINX5: return isInIconMode() ? 0.38f : 0.26f;
540
      case MEGAMINX5: return isInIconMode() ? 0.40f : 0.18f;
541
      }
542

    
543
    return 0.0f;
544
    }
545

    
546
///////////////////////////////////////////////////////////////////////////////////////////////////
547

    
548
  public float[][][] getStickerAngles()
549
    {
550
    return null;
551
    }
552

    
553
///////////////////////////////////////////////////////////////////////////////////////////////////
554

    
555
  public String getShortName()
556
    {
557
    if( mSignature==null ) mSignature = getSignature();
558
    int param = getInitData().getParam();
559
    return MARKER+(param+"_"+mSignature.getString());
560
    }
561

    
562
///////////////////////////////////////////////////////////////////////////////////////////////////
563

    
564
  public ObjectSignature getSignature()
565
    {
566
    if( mSignature==null )
567
      {
568
      int param = getInitData().getParam();
569
      mSignature = new ObjectSignatureMegaminx(param,mPosition);
570
      }
571
    return mSignature;
572
    }
573

    
574
///////////////////////////////////////////////////////////////////////////////////////////////////
575

    
576
  public String getObjectName()
577
    {
578
    return OBJECT_NAME_MEGAMINX;
579
    }
580

    
581
///////////////////////////////////////////////////////////////////////////////////////////////////
582

    
583
  public String getInventor()
584
    {
585
    return "??";
586
    }
587

    
588
///////////////////////////////////////////////////////////////////////////////////////////////////
589

    
590
  public int getYearOfInvention()
591
    {
592
    return 0;
593
    }
594

    
595
///////////////////////////////////////////////////////////////////////////////////////////////////
596

    
597
  public int getComplexity()
598
    {
599
    return 4;
600
    }
601

    
602
///////////////////////////////////////////////////////////////////////////////////////////////////
603

    
604
  public String[][] getTutorials()
605
    {
606
    return null;
607
    }
608
}
(5-5/51)