Project

General

Profile

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

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

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.helpers.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

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

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

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

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

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

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

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

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

    
71
  private static final int NUM_TYPES = 7;
72

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

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

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

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

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

    
106
    return ret;
107
    }
108

    
109
///////////////////////////////////////////////////////////////////////////////////////////////////
110

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

    
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

    
123
  private float[][] getPositions()
124
    {
125
    if( mPosition==null )
126
      {
127
      InitData data = getInitData();
128
      mOrigPosition = data.getPos();
129
      int param = data.getParam();
130

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

    
140
    return mPosition;
141
    }
142

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

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

    
159
    return null;
160
    }
161

    
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163

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

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

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

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

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

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

    
217
    return null;
218
    }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221

    
222
  private void produceTmpShape(int variant)
223
    {
224
    InitData data = getInitData();
225
    int param = data.getParam();
226
    float[] pos = figureOutCubitPos(variant,param);
227

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

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

    
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239
// PUBLIC API
240

    
241
  public TwistyBandagedMegaminx(int meshState, int iconMode, Static4D quat, Static3D move, float scale, InitData data, InitAssets asset)
242
    {
243
    super(meshState, iconMode, quat, move, scale, data, asset);
244
    }
245

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

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

    
255
///////////////////////////////////////////////////////////////////////////////////////////////////
256

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

    
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264

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

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

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

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

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

    
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289

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

    
295
    return -1;
296
    }
297

    
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299
/*
300
  private float[][] getVertices(int variant)
301
    {
302
    if( mTmpShapes==null ) mTmpShapes = new ObjectShape[mNumVariants];
303
    if( mTmpShapes[variant]==null ) produceTmpShape(variant);
304
    return mTmpShapes[variant].getVertices();
305
    }
306
*/
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308

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

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

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

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

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

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

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

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

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

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

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

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

    
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396

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

    
419
    return -1;
420
    }
421

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

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

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

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

    
450
      FactoryBandagedMegaminx factory = FactoryBandagedMegaminx.getInstance();
451

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

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

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

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

    
494
    return mNumVariants;
495
    }
496

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

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

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

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

    
514
///////////////////////////////////////////////////////////////////////////////////////////////////
515

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

    
521
///////////////////////////////////////////////////////////////////////////////////////////////////
522

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

    
528
///////////////////////////////////////////////////////////////////////////////////////////////////
529

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

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

    
542
    return 0.0f;
543
    }
544

    
545
///////////////////////////////////////////////////////////////////////////////////////////////////
546

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

    
552
///////////////////////////////////////////////////////////////////////////////////////////////////
553

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

    
561
///////////////////////////////////////////////////////////////////////////////////////////////////
562

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

    
573
///////////////////////////////////////////////////////////////////////////////////////////////////
574

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

    
580
///////////////////////////////////////////////////////////////////////////////////////////////////
581

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

    
587
///////////////////////////////////////////////////////////////////////////////////////////////////
588

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

    
594
///////////////////////////////////////////////////////////////////////////////////////////////////
595

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

    
601
///////////////////////////////////////////////////////////////////////////////////////////////////
602

    
603
  public String[][] getTutorials()
604
    {
605
    return null;
606
    }
607
}
(4-4/50)