Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyMirror.java @ 3ee1d662

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objectlib.objects;
21

    
22
import static org.distorted.objectlib.touchcontrol.TouchControl.TC_CHANGING_MIRROR;
23
import static org.distorted.objectlib.touchcontrol.TouchControl.TYPE_NOT_SPLIT;
24

    
25
import java.io.InputStream;
26

    
27
import org.distorted.library.type.Static3D;
28
import org.distorted.library.type.Static4D;
29

    
30
import org.distorted.objectlib.helpers.ObjectFaceShape;
31
import org.distorted.objectlib.main.ObjectControl;
32
import org.distorted.objectlib.main.ObjectType;
33
import org.distorted.objectlib.helpers.ObjectShape;
34
import org.distorted.objectlib.helpers.ScrambleState;
35
import org.distorted.objectlib.main.ShapeHexahedron;
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

    
39
public class TwistyMirror extends ShapeHexahedron
40
{
41
  static final Static3D[] ROT_AXIS = new Static3D[]
42
         {
43
           new Static3D(1,0,0),
44
           new Static3D(0,1,0),
45
           new Static3D(0,0,1)
46
         };
47

    
48
  private static final int[] FACE_COLORS = new int[] { COLOR_WHITE };
49
  private static final float DX = 0.10f;
50
  private static final float DY = 0.25f;
51
  private static final float DZ = 0.40f;
52

    
53
  private ScrambleState[] mStates;
54
  private Static4D[] mQuats;
55
  private float[][] mCuts;
56
  private int[] mBasicAngle;
57
  private float[][] mPositions;
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

    
61
  public TwistyMirror(int[] numL, int meshState, Static4D quat, Static3D move, float scale, InputStream stream)
62
    {
63
    super(numL, meshState, numL[0], quat, move, scale, stream);
64
    }
65

    
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67

    
68
  public ScrambleState[] getScrambleStates()
69
    {
70
    if( mStates==null )
71
      {
72
      int[] numLayers = getNumLayers();
73
      int[][] m = new int[16][];
74
      for(int i=1; i<16; i++) m[i] = createEdges(numLayers[0],i);
75

    
76
      mStates = new ScrambleState[]
77
        {
78
        new ScrambleState( new int[][] { m[ 1], m[ 2], m[ 3] } ),  // 0
79
        new ScrambleState( new int[][] {  null, m[ 4], m[ 5] } ),  // x
80
        new ScrambleState( new int[][] { m[ 6],  null, m[ 7] } ),  // y
81
        new ScrambleState( new int[][] { m[ 8], m[ 8],  null } ),  // z
82
        new ScrambleState( new int[][] { m[10],  null, m[ 7] } ),  // xy
83
        new ScrambleState( new int[][] { m[11], m[ 9],  null } ),  // xz
84
        new ScrambleState( new int[][] {  null, m[12], m[ 5] } ),  // yx
85
        new ScrambleState( new int[][] { m[ 8], m[13],  null } ),  // yz
86
        new ScrambleState( new int[][] {  null, m[ 4], m[14] } ),  // zx
87
        new ScrambleState( new int[][] { m[ 6],  null, m[15] } ),  // zy
88
        new ScrambleState( new int[][] {  null,  null, m[ 5] } ),  // xyx
89
        new ScrambleState( new int[][] {  null, m[ 4],  null } ),  // xzx
90
        new ScrambleState( new int[][] {  null,  null, m[ 7] } ),  // yxy
91
        new ScrambleState( new int[][] { m[ 6],  null,  null } ),  // yzy
92
        new ScrambleState( new int[][] {  null, m[ 9],  null } ),  // zxz
93
        new ScrambleState( new int[][] { m[ 8],  null,  null } ),  // zyz
94
        };
95
      }
96

    
97
    return mStates;
98
    }
99

    
100
///////////////////////////////////////////////////////////////////////////////////////////////////
101

    
102
  private int[] createEdges(int size, int vertex)
103
    {
104
    int[] ret = new int[9*size];
105

    
106
    for(int l=0; l<size; l++)
107
      {
108
      ret[9*l  ] = l;
109
      ret[9*l+1] =-1;
110
      ret[9*l+2] = vertex;
111
      ret[9*l+3] = l;
112
      ret[9*l+4] = 1;
113
      ret[9*l+5] = vertex;
114
      ret[9*l+6] = l;
115
      ret[9*l+7] = 2;
116
      ret[9*l+8] = vertex;
117
      }
118

    
119
    return ret;
120
    }
121

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

    
124
  private void initializeQuats()
125
    {
126
    mQuats = new Static4D[]
127
         {
128
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
129
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
130
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
131
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
132

    
133
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
134
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
135
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
136
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
137
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
138
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
139
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
140
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
141
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
142
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
143
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
144
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
145

    
146
         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
147
         new Static4D(  0.5f,   0.5f,  -0.5f,   0.5f),
148
         new Static4D(  0.5f,   0.5f,  -0.5f,  -0.5f),
149
         new Static4D(  0.5f,  -0.5f,   0.5f,  -0.5f),
150
         new Static4D( -0.5f,  -0.5f,  -0.5f,   0.5f),
151
         new Static4D( -0.5f,   0.5f,  -0.5f,  -0.5f),
152
         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
153
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
154
         };
155
    }
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158
// we cannot do this the standard, automatic way because there's only 1 color in the FACE_COLORS
159
// table and retCubitSolvedStatus() always returns -1,-1 or 0.
160

    
161
  public int[] getSolvedQuats(int cubit, int[] numLayers)
162
    {
163
    if( numLayers[0]==3 )
164
      {
165
      switch(cubit)
166
        {
167
        case  4: case 21: return new int[] {1, 8, 9};
168
        case 10: case 15: return new int[] {2,12,13};
169
        case 12: case 13: return new int[] {3,14,15};
170
        }
171
      }
172

    
173
    return null;
174
    }
175

    
176
///////////////////////////////////////////////////////////////////////////////////////////////////
177

    
178
  private int getRow(int cubit, int numLayers, int dim)
179
    {
180
    return (int)(mPositions[cubit][dim] + 0.5f*(numLayers-1));
181
    }
182

    
183
///////////////////////////////////////////////////////////////////////////////////////////////////
184

    
185
  public ObjectShape getObjectShape(int variant)
186
    {
187
    int numL = getNumLayers()[0];
188
    int xrow = getRow(variant,numL,0);  // cubit == variant
189
    int yrow = getRow(variant,numL,1);
190
    int zrow = getRow(variant,numL,2);
191

    
192
    float XL = -0.5f + (xrow==     0 ? DX : 0);
193
    float XR = +0.5f + (xrow==numL-1 ? DX : 0);
194
    float YL = -0.5f - (yrow==     0 ? DY : 0);
195
    float YR = +0.5f - (yrow==numL-1 ? DY : 0);
196
    float ZL = -0.5f - (zrow==     0 ? DZ : 0);
197
    float ZR = +0.5f - (zrow==numL-1 ? DZ : 0);
198

    
199
    float[][] vertices = new float[][]
200
          {
201
              { XR, YR, ZR },
202
              { XR, YR, ZL },
203
              { XR, YL, ZR },
204
              { XR, YL, ZL },
205
              { XL, YR, ZR },
206
              { XL, YR, ZL },
207
              { XL, YL, ZR },
208
              { XL, YL, ZL },
209
          };
210

    
211
    int[][] vert_indices = new int[][]
212
          {
213
              {2,3,1,0},
214
              {7,6,4,5},
215
              {4,0,1,5},
216
              {7,3,2,6},
217
              {6,2,0,4},
218
              {3,7,5,1}
219
          };
220

    
221
    return new ObjectShape(vertices,vert_indices,getNumCubitFaces(),6);
222
    }
223

    
224
///////////////////////////////////////////////////////////////////////////////////////////////////
225

    
226
  public ObjectFaceShape getObjectFaceShape(int variant)
227
    {
228
    int extraI, extraV, num, numL = getNumLayers()[0];
229
    float height;
230

    
231
    switch(numL)
232
      {
233
      case 2 : num = 6; extraI = 2; extraV = 2; height = 0.045f; break;
234
      case 3 : num = 5; extraI = 2; extraV = 2; height = 0.045f; break;
235
      case 4 : num = 5; extraI = 1; extraV = 1; height = 0.045f; break;
236
      default: num = 5; extraI = 0; extraV = 0; height = 0.045f; break;
237
      }
238

    
239
    float[][] bands     = { {height,35,0.5f,0.7f,num,extraI,extraV} };
240
    int[] bandIndices   = { 0,0,0,0,0,0};
241
    float[][] corners   = { {0.036f,0.12f} };
242
    int[] cornerIndices = { 0,0,0,0,0,0,0,0 };
243
    float[][] centers   = { {0.0f, 0.0f, 0.0f} };
244
    int[] centerIndices = { 0,0,0,0,0,0,0,0 };
245

    
246
    return new ObjectFaceShape(bands,bandIndices,corners,cornerIndices,centers,centerIndices,null);
247
    }
248

    
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250

    
251
  public Static4D getQuat(int cubit, int[] numLayers)
252
    {
253
    if( mQuats ==null ) initializeQuats();
254
    return mQuats[0];
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

    
259
  public int getNumCubitVariants(int[] numLayers)
260
    {
261
    int numL = numLayers[0];
262
    return 6*numL*numL - 12*numL + 8;
263
    }
264

    
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266

    
267
  public int getCubitVariant(int cubit, int[] numLayers)
268
    {
269
    return cubit;
270
    }
271

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

    
274
  public int getColor(int face)
275
    {
276
    return FACE_COLORS[face];
277
    }
278

    
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280

    
281
  public float[][] getCubitPositions(int[] numLayers)
282
    {
283
    if( mPositions==null )
284
      {
285
      int numL = numLayers[0];
286
      int numCubits = numL>1 ? 6*numL*numL - 12*numL + 8 : 1;
287
      mPositions = new float[numCubits][];
288

    
289
      float diff = 0.5f*(numL-1);
290
      int currentPosition = 0;
291

    
292
      for(int x = 0; x<numL; x++)
293
        for(int y = 0; y<numL; y++)
294
          for(int z = 0; z<numL; z++)
295
            if( x==0 || x==numL-1 || y==0 || y==numL-1 || z==0 || z==numL-1 )
296
              {
297
              mPositions[currentPosition++] = new float[] {x-diff,y-diff,z-diff};
298
              }
299
      }
300

    
301
    return mPositions;
302
    }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

    
306
  public Static4D[] getQuats()
307
    {
308
    if( mQuats ==null ) initializeQuats();
309
    return mQuats;
310
    }
311

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

    
314
  public int getNumFaceColors()
315
    {
316
    return 1;
317
    }
318

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

    
321
  public float[][] getCuts(int[] numLayers)
322
    {
323
    if( mCuts==null )
324
      {
325
      int numL = numLayers[0];
326
      mCuts = new float[3][numL-1];
327

    
328
      for(int i=0; i<numL-1; i++)
329
        {
330
        float cut = (2-numL)*0.5f + i;
331
        mCuts[0][i] = cut;
332
        mCuts[1][i] = cut;
333
        mCuts[2][i] = cut;
334
        }
335
      }
336

    
337
    return mCuts;
338
    }
339

    
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341

    
342
  public boolean[][] getLayerRotatable(int[] numLayers)
343
    {
344
    int numAxis = ROT_AXIS.length;
345
    boolean[][] layerRotatable = new boolean[numAxis][];
346

    
347
    for(int i=0; i<numAxis; i++)
348
      {
349
      layerRotatable[i] = new boolean[numLayers[i]];
350
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
351
      }
352

    
353
    return layerRotatable;
354
    }
355

    
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357

    
358
  public int getTouchControlType()
359
    {
360
    return TC_CHANGING_MIRROR;
361
    }
362

    
363
///////////////////////////////////////////////////////////////////////////////////////////////////
364

    
365
  public int getTouchControlSplit()
366
    {
367
    return TYPE_NOT_SPLIT;
368
    }
369

    
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371

    
372
  public int[][][] getEnabled()
373
    {
374
    return new int[][][]
375
      {
376
          {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}},
377
      };
378
    }
379

    
380
///////////////////////////////////////////////////////////////////////////////////////////////////
381

    
382
  public float[] getDist3D(int[] numLayers)
383
    {
384
    return null;
385
    }
386

    
387
///////////////////////////////////////////////////////////////////////////////////////////////////
388

    
389
  public int getSolvedFunctionIndex()
390
    {
391
    return 0;
392
    }
393

    
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395

    
396
  public int getNumCubitFaces()
397
    {
398
    return 6;
399
    }
400

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

    
403
  public int getCubitFaceColor(int cubit, int face, int[] numLayers)
404
    {
405
    if( numLayers[0]==2 )
406
      {
407
      switch(face)
408
        {
409
        case 0: return (cubit==4 || cubit==5 || cubit==6 || cubit==7 ) ? 0:-1;
410
        case 1: return (cubit==0 || cubit==1 || cubit==2 || cubit==3 ) ? 0:-1;
411
        case 2: return (cubit==3 || cubit==7 || cubit==2 || cubit==6 ) ? 0:-1;
412
        case 3: return (cubit==1 || cubit==5 || cubit==0 || cubit==4 ) ? 0:-1;
413
        case 4: return (cubit==3 || cubit==7 || cubit==1 || cubit==5 ) ? 0:-1;
414
        case 5: return (cubit==2 || cubit==6 || cubit==0 || cubit==4 ) ? 0:-1;
415
        }
416
      }
417
    else if( numLayers[0]==3 )
418
      {
419
      switch(face)
420
        {
421
        case 0: return (cubit==17 || cubit==18 || cubit==19 ||
422
                        cubit==20 || cubit==21 || cubit==22 ||
423
                        cubit==23 || cubit==24 || cubit==25 ) ? 0:-1;
424
        case 1: return (cubit== 0 || cubit== 1 || cubit== 2 ||
425
                        cubit== 3 || cubit== 4 || cubit== 5 ||
426
                        cubit== 6 || cubit== 7 || cubit== 8 ) ? 0:-1;
427
        case 2: return (cubit== 6 || cubit==14 || cubit==23 ||
428
                        cubit== 7 || cubit==15 || cubit==24 ||
429
                        cubit== 8 || cubit==16 || cubit==25 ) ? 0:-1;
430
        case 3: return (cubit== 0 || cubit== 9 || cubit==17 ||
431
                        cubit== 1 || cubit==10 || cubit==18 ||
432
                        cubit== 2 || cubit==11 || cubit==19 ) ? 0:-1;
433
        case 4: return (cubit== 8 || cubit==16 || cubit==25 ||
434
                        cubit== 5 || cubit==13 || cubit==22 ||
435
                        cubit== 2 || cubit==11 || cubit==19 ) ? 0:-1;
436
        case 5: return (cubit== 6 || cubit==14 || cubit==23 ||
437
                        cubit== 3 || cubit==12 || cubit==20 ||
438
                        cubit== 0 || cubit== 9 || cubit==17 ) ? 0:-1;
439
        }
440
      }
441

    
442
    return 0;
443
    }
444

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

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

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

    
454
  public float getStickerStroke()
455
    {
456
    float stroke = 0.08f;
457

    
458
    if( ObjectControl.isInIconMode() )
459
      {
460
      int[] numLayers = getNumLayers();
461
      stroke*= ( numLayers[0]==2 ? 1.8f : 2.0f );
462
      }
463

    
464
    return stroke;
465
    }
466

    
467
///////////////////////////////////////////////////////////////////////////////////////////////////
468

    
469
  public float[][] getStickerAngles()
470
    {
471
    return null;
472
    }
473

    
474
///////////////////////////////////////////////////////////////////////////////////////////////////
475
// PUBLIC API
476

    
477
  public Static3D[] getRotationAxis()
478
    {
479
    return ROT_AXIS;
480
    }
481

    
482
///////////////////////////////////////////////////////////////////////////////////////////////////
483

    
484
  public int[] getBasicAngle()
485
    {
486
    if( mBasicAngle==null ) mBasicAngle = new int[] { 4,4,4 };
487
    return mBasicAngle;
488
    }
489

    
490
///////////////////////////////////////////////////////////////////////////////////////////////////
491

    
492
  public ObjectType intGetObjectType(int[] numLayers)
493
    {
494
    switch(numLayers[0])
495
      {
496
      case 2: return ObjectType.MIRR_2;
497
      case 3: return ObjectType.MIRR_3;
498
      }
499

    
500
    return ObjectType.MIRR_2;
501
    }
502

    
503
///////////////////////////////////////////////////////////////////////////////////////////////////
504

    
505
  public String getObjectName()
506
    {
507
    switch(getNumLayers()[0])
508
      {
509
      case 2: return "Pocket Mirror";
510
      case 3: return "Mirror Cube";
511
      }
512
    return "Pocket Mirror";
513
    }
514

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

    
517
  public String getInventor()
518
    {
519
    switch(getNumLayers()[0])
520
      {
521
      case 2: return "Thomas de Bruin";
522
      case 3: return "Hidetoshi Takeji";
523
      }
524
    return "Hidetoshi Takeji";
525
    }
526

    
527
///////////////////////////////////////////////////////////////////////////////////////////////////
528

    
529
  public int getYearOfInvention()
530
    {
531
    switch(getNumLayers()[0])
532
      {
533
      case 2: return 2007;
534
      case 3: return 2006;
535
      }
536
    return 2006;
537
    }
538

    
539
///////////////////////////////////////////////////////////////////////////////////////////////////
540

    
541
  public int getComplexity()
542
    {
543
    switch(getNumLayers()[0])
544
      {
545
      case 2: return 1;
546
      case 3: return 2;
547
      }
548
    return 7;
549
    }
550
}
(17-17/26)