Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyMirror.java @ 00f4980d

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.main.ObjectControl;
31
import org.distorted.objectlib.main.ObjectType;
32
import org.distorted.objectlib.helpers.ObjectShape;
33
import org.distorted.objectlib.helpers.ObjectSticker;
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 ObjectSticker[] mStickers;
58
  private float[][] mPositions;
59

    
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61

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

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

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

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

    
98
    return mStates;
99
    }
100

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

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

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

    
120
    return ret;
121
    }
122

    
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124

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

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

    
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
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
155
         };
156
    }
157

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

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

    
174
    return null;
175
    }
176

    
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178

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

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

    
186
  public ObjectShape getObjectShape(int variant)
187
    {
188
    int extraI, extraV, num, numL = getNumLayers()[0];
189
    float height;
190

    
191
    switch(numL)
192
      {
193
      case 2 : num = 6; extraI = 2; extraV = 2; height = 0.045f; break;
194
      case 3 : num = 5; extraI = 2; extraV = 2; height = 0.045f; break;
195
      case 4 : num = 5; extraI = 1; extraV = 1; height = 0.045f; break;
196
      default: num = 5; extraI = 0; extraV = 0; height = 0.045f; break;
197
      }
198

    
199
    int xrow = getRow(variant,numL,0);  // cubit == variant
200
    int yrow = getRow(variant,numL,1);
201
    int zrow = getRow(variant,numL,2);
202

    
203
    float XL = -0.5f + (xrow==     0 ? DX : 0);
204
    float XR = +0.5f + (xrow==numL-1 ? DX : 0);
205
    float YL = -0.5f - (yrow==     0 ? DY : 0);
206
    float YR = +0.5f - (yrow==numL-1 ? DY : 0);
207
    float ZL = -0.5f - (zrow==     0 ? DZ : 0);
208
    float ZR = +0.5f - (zrow==numL-1 ? DZ : 0);
209

    
210
    float[][] vertices = new float[][]
211
          {
212
              { XR, YR, ZR },
213
              { XR, YR, ZL },
214
              { XR, YL, ZR },
215
              { XR, YL, ZL },
216
              { XL, YR, ZR },
217
              { XL, YR, ZL },
218
              { XL, YL, ZR },
219
              { XL, YL, ZL },
220
          };
221

    
222
    int[][] vert_indices = new int[][]
223
          {
224
              {2,3,1,0},
225
              {7,6,4,5},
226
              {4,0,1,5},
227
              {7,3,2,6},
228
              {6,2,0,4},
229
              {3,7,5,1}
230
          };
231

    
232
    float[][] bands     = new float[][] { {height,35,0.5f,0.7f,num,extraI,extraV} };
233
    int[] bandIndices   = new int[] { 0,0,0,0,0,0};
234
    float[][] corners   = new float[][] { {0.036f,0.12f} };
235
    int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
236
    float[][] centers   = new float[][] { {0.0f, 0.0f, 0.0f} };
237
    int[] centerIndices = new int[] { 0,0,0,0,0,0,0,0 };
238

    
239
    return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null, 6);
240
    }
241

    
242
///////////////////////////////////////////////////////////////////////////////////////////////////
243

    
244
  public Static4D getQuat(int cubit, int[] numLayers)
245
    {
246
    if( mQuats ==null ) initializeQuats();
247
    return mQuats[0];
248
    }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
  public int getNumCubitVariants(int[] numLayers)
253
    {
254
    int numL = numLayers[0];
255
    return 6*numL*numL - 12*numL + 8;
256
    }
257

    
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259

    
260
  public int getCubitVariant(int cubit, int[] numLayers)
261
    {
262
    return cubit;
263
    }
264

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

    
267
  public int getColor(int face)
268
    {
269
    return FACE_COLORS[face];
270
    }
271

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

    
274
  public float[][] getCubitPositions(int[] numLayers)
275
    {
276
    if( mPositions==null )
277
      {
278
      int numL = numLayers[0];
279
      int numCubits = numL>1 ? 6*numL*numL - 12*numL + 8 : 1;
280
      mPositions = new float[numCubits][];
281

    
282
      float diff = 0.5f*(numL-1);
283
      int currentPosition = 0;
284

    
285
      for(int x = 0; x<numL; x++)
286
        for(int y = 0; y<numL; y++)
287
          for(int z = 0; z<numL; z++)
288
            if( x==0 || x==numL-1 || y==0 || y==numL-1 || z==0 || z==numL-1 )
289
              {
290
              mPositions[currentPosition++] = new float[] {x-diff,y-diff,z-diff};
291
              }
292
      }
293

    
294
    return mPositions;
295
    }
296

    
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298

    
299
  public Static4D[] getQuats()
300
    {
301
    if( mQuats ==null ) initializeQuats();
302
    return mQuats;
303
    }
304

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

    
307
  public int getNumFaceColors()
308
    {
309
    return 1;
310
    }
311

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

    
314
  public float[][] getCuts(int[] numLayers)
315
    {
316
    if( mCuts==null )
317
      {
318
      int numL = numLayers[0];
319
      mCuts = new float[3][numL-1];
320

    
321
      for(int i=0; i<numL-1; i++)
322
        {
323
        float cut = (2-numL)*0.5f + i;
324
        mCuts[0][i] = cut;
325
        mCuts[1][i] = cut;
326
        mCuts[2][i] = cut;
327
        }
328
      }
329

    
330
    return mCuts;
331
    }
332

    
333
///////////////////////////////////////////////////////////////////////////////////////////////////
334

    
335
  public boolean[][] getLayerRotatable(int[] numLayers)
336
    {
337
    int numAxis = ROT_AXIS.length;
338
    boolean[][] layerRotatable = new boolean[numAxis][];
339

    
340
    for(int i=0; i<numAxis; i++)
341
      {
342
      layerRotatable[i] = new boolean[numLayers[i]];
343
      for(int j=0; j<numLayers[i]; j++) layerRotatable[i][j] = true;
344
      }
345

    
346
    return layerRotatable;
347
    }
348

    
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350

    
351
  public int getTouchControlType()
352
    {
353
    return TC_CHANGING_MIRROR;
354
    }
355

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

    
358
  public int getTouchControlSplit()
359
    {
360
    return TYPE_NOT_SPLIT;
361
    }
362

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

    
365
  public int[][][] getEnabled()
366
    {
367
    return new int[][][]
368
      {
369
          {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}},
370
      };
371
    }
372

    
373
///////////////////////////////////////////////////////////////////////////////////////////////////
374

    
375
  public float[] getDist3D(int[] numLayers)
376
    {
377
    return null;
378
    }
379

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

    
382
  public int getSolvedFunctionIndex()
383
    {
384
    return 0;
385
    }
386

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

    
389
  public int getNumCubitFaces()
390
    {
391
    return 6;
392
    }
393

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

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

    
435
    return 0;
436
    }
437

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

    
440
  public int getVariantFaceColor(int variant, int face, int[] numLayers)
441
    {
442
    return face>=mStickerVariants[variant].length ? -1 : mStickerVariants[variant][face];
443
    }
444

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

    
447
  private float getRadius()
448
    {
449
    return 0.10f;
450
    }
451

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

    
454
  private float getStroke()
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
  private float[][] getAngles()
470
    {
471
    return null;
472
    }
473

    
474
///////////////////////////////////////////////////////////////////////////////////////////////////
475

    
476
  public ObjectSticker retSticker(int sticker)
477
    {
478
    if( mStickers==null )
479
      {
480
      float rad = getRadius();
481
      float str = getStroke();
482
      float[][] angles = getAngles();
483
      int numStickers = mStickerCoords.length;
484
      mStickers = new ObjectSticker[numStickers];
485

    
486
      for(int s=0; s<numStickers; s++)
487
        {
488
        float scale = mStickerScales[s];
489
        float radius = rad / scale;
490
        float stroke = str / scale;
491
        int len = mStickerCoords[s].length/2;
492
        float[] radii = new float[len];
493
        for(int r=0; r<len; r++) radii[r] = radius*computeRadiusCorrection(mStickerCoords[s],r,len);
494
        mStickers[s] = new ObjectSticker(mStickerCoords[s],angles==null ? null : angles[s],radii,stroke);
495
        }
496
      }
497

    
498
    return mStickers[sticker];
499
    }
500

    
501
///////////////////////////////////////////////////////////////////////////////////////////////////
502
// PUBLIC API
503

    
504
  public Static3D[] getRotationAxis()
505
    {
506
    return ROT_AXIS;
507
    }
508

    
509
///////////////////////////////////////////////////////////////////////////////////////////////////
510

    
511
  public int[] getBasicAngle()
512
    {
513
    if( mBasicAngle==null ) mBasicAngle = new int[] { 4,4,4 };
514
    return mBasicAngle;
515
    }
516

    
517
///////////////////////////////////////////////////////////////////////////////////////////////////
518

    
519
  public ObjectType intGetObjectType(int[] numLayers)
520
    {
521
    switch(numLayers[0])
522
      {
523
      case 2: return ObjectType.MIRR_2;
524
      case 3: return ObjectType.MIRR_3;
525
      }
526

    
527
    return ObjectType.MIRR_2;
528
    }
529

    
530
///////////////////////////////////////////////////////////////////////////////////////////////////
531

    
532
  public String getObjectName()
533
    {
534
    switch(getNumLayers()[0])
535
      {
536
      case 2: return "Pocket Mirror";
537
      case 3: return "Mirror Cube";
538
      }
539
    return "Pocket Mirror";
540
    }
541

    
542
///////////////////////////////////////////////////////////////////////////////////////////////////
543

    
544
  public String getInventor()
545
    {
546
    switch(getNumLayers()[0])
547
      {
548
      case 2: return "Thomas de Bruin";
549
      case 3: return "Hidetoshi Takeji";
550
      }
551
    return "Hidetoshi Takeji";
552
    }
553

    
554
///////////////////////////////////////////////////////////////////////////////////////////////////
555

    
556
  public int getYearOfInvention()
557
    {
558
    switch(getNumLayers()[0])
559
      {
560
      case 2: return 2007;
561
      case 3: return 2006;
562
      }
563
    return 2006;
564
    }
565

    
566
///////////////////////////////////////////////////////////////////////////////////////////////////
567

    
568
  public int getComplexity()
569
    {
570
    switch(getNumLayers()[0])
571
      {
572
      case 2: return 1;
573
      case 3: return 2;
574
      }
575
    return 7;
576
    }
577
}
(17-17/26)