Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / objects / TwistyCube.java @ 8da6b1c9

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.main.Movement.TYPE_NOT_SPLIT;
23

    
24
import android.content.res.Resources;
25

    
26
import org.distorted.library.main.DistortedEffects;
27
import org.distorted.library.main.DistortedTexture;
28
import org.distorted.library.mesh.MeshSquare;
29
import org.distorted.library.type.Static3D;
30
import org.distorted.library.type.Static4D;
31

    
32
import org.distorted.objectlib.R;
33
import org.distorted.objectlib.main.Movement;
34
import org.distorted.objectlib.main.Movement6;
35
import org.distorted.objectlib.main.ObjectControl;
36
import org.distorted.objectlib.main.ObjectType;
37
import org.distorted.objectlib.helpers.ObjectShape;
38
import org.distorted.objectlib.helpers.ObjectSticker;
39
import org.distorted.objectlib.helpers.ScrambleState;
40
import org.distorted.objectlib.main.Twisty6;
41

    
42
///////////////////////////////////////////////////////////////////////////////////////////////////
43

    
44
public class TwistyCube extends Twisty6
45
{
46
  static final Static3D[] ROT_AXIS = new Static3D[]
47
         {
48
           new Static3D(1,0,0),
49
           new Static3D(0,1,0),
50
           new Static3D(0,0,1)
51
         };
52

    
53
  private static final int[][][] ENABLED = new int[][][]
54
      {
55
          {{1,2}},{{1,2}},{{0,2}},{{0,2}},{{0,1}},{{0,1}},
56
      };
57

    
58
  private ScrambleState[] mStates;
59
  private Static4D[] mQuats;
60
  private float[][] mCuts;
61
  private boolean[][] mLayerRotatable;
62
  private int[] mBasicAngle;
63
  private ObjectSticker[] mStickers;
64
  private Movement mMovement;
65

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

    
68
  public TwistyCube(int size, Static4D quat, Static3D move, DistortedTexture texture,
69
                    MeshSquare mesh, DistortedEffects effects, Resources res, int scrWidth)
70
    {
71
    super(size, size, quat, move, texture, mesh, effects, res, scrWidth);
72
    }
73

    
74
///////////////////////////////////////////////////////////////////////////////////////////////////
75

    
76
  protected ScrambleState[] getScrambleStates()
77
    {
78
    if( mStates==null )
79
      {
80
      int size = getNumLayers();
81
      int[][] m = new int[16][];
82
      for(int i=1; i<16; i++) m[i] = createEdges(size,i);
83

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

    
105
    return mStates;
106
    }
107

    
108
///////////////////////////////////////////////////////////////////////////////////////////////////
109

    
110
  protected int getResource(int numLayers)
111
    {
112
    switch(numLayers)
113
      {
114
      case 2: return R.raw.cube2;
115
      case 3: return R.raw.cube3;
116
      case 4: return R.raw.cube4;
117
      case 5: return R.raw.cube5;
118
      }
119

    
120
    return 0;
121
    }
122

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

    
125
  private int[] createEdges(int size, int vertex)
126
    {
127
    int[] ret = new int[9*size];
128

    
129
    for(int l=0; l<size; l++)
130
      {
131
      ret[9*l  ] = l;
132
      ret[9*l+1] =-1;
133
      ret[9*l+2] = vertex;
134
      ret[9*l+3] = l;
135
      ret[9*l+4] = 1;
136
      ret[9*l+5] = vertex;
137
      ret[9*l+6] = l;
138
      ret[9*l+7] = 2;
139
      ret[9*l+8] = vertex;
140
      }
141

    
142
    return ret;
143
    }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146

    
147
  private void initializeQuats()
148
    {
149
    mQuats = new Static4D[]
150
         {
151
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
152
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
153
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
154
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
155

    
156
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
157
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
158
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
159
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
160
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
161
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
162
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
163
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
164
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
165
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
166
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
167
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
168

    
169
         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
170
         new Static4D(  0.5f,   0.5f,  -0.5f,   0.5f),
171
         new Static4D(  0.5f,   0.5f,  -0.5f,  -0.5f),
172
         new Static4D(  0.5f,  -0.5f,   0.5f,  -0.5f),
173
         new Static4D( -0.5f,  -0.5f,  -0.5f,   0.5f),
174
         new Static4D( -0.5f,   0.5f,  -0.5f,  -0.5f),
175
         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
176
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
177
         };
178
    }
179

    
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181

    
182
  protected int[] getSolvedQuats(int cubit, int numLayers)
183
    {
184
    if( mQuats ==null ) initializeQuats();
185
    int status = retCubitSolvedStatus(cubit,numLayers);
186
    return status<0 ? null : buildSolvedQuats(Movement6.FACE_AXIS[status], mQuats);
187
    }
188

    
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190

    
191
  private int getNumCornersAndEdges(int numLayers)
192
    {
193
    return numLayers==1 ? 1 : 12*(numLayers-2) + 8;
194
    }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

    
198
  protected ObjectShape getObjectShape(int cubit, int numLayers)
199
    {
200
    int extraI, extraV, num;
201
    float height;
202

    
203
    switch(numLayers)
204
      {
205
      case 2 : num = 6; extraI = 2; extraV = 2; height = 0.045f; break;
206
      case 3 : num = 5; extraI = 2; extraV = 2; height = 0.045f; break;
207
      case 4 : num = 5; extraI = 1; extraV = 1; height = 0.045f; break;
208
      default: num = 5; extraI = 0; extraV = 0; height = 0.045f; break;
209
      }
210

    
211
    double[][] vertices = new double[][]
212
          {
213
              { 0.5, 0.5, 0.5 },
214
              { 0.5, 0.5,-0.5 },
215
              { 0.5,-0.5, 0.5 },
216
              { 0.5,-0.5,-0.5 },
217
              {-0.5, 0.5, 0.5 },
218
              {-0.5, 0.5,-0.5 },
219
              {-0.5,-0.5, 0.5 },
220
              {-0.5,-0.5,-0.5 },
221
          };
222

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

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

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

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244

    
245
  protected float[][] getCubitPositions(int numLayers)
246
    {
247
    if( numLayers==1 ) return new float[][] {{ 0.0f, 0.0f, 0.0f }};
248

    
249
    int numCubits = getNumCornersAndEdges(numLayers) + 6*(numLayers-2)*(numLayers-2);
250
    float[][] tmp = new float[numCubits][];
251

    
252
    final float LEN = 0.5f*(numLayers-1);
253
    int currentPosition = 0;
254

    
255
    tmp[currentPosition++] = new float[] {-LEN,-LEN,-LEN};
256
    tmp[currentPosition++] = new float[] {-LEN,-LEN,+LEN};
257
    tmp[currentPosition++] = new float[] {-LEN,+LEN,-LEN};
258
    tmp[currentPosition++] = new float[] {-LEN,+LEN,+LEN};
259
    tmp[currentPosition++] = new float[] {+LEN,-LEN,-LEN};
260
    tmp[currentPosition++] = new float[] {+LEN,-LEN,+LEN};
261
    tmp[currentPosition++] = new float[] {+LEN,+LEN,-LEN};
262
    tmp[currentPosition++] = new float[] {+LEN,+LEN,+LEN};
263

    
264
    for(int i=1; i<numLayers-1; i++)
265
      tmp[currentPosition++] = new float[] { i-LEN,  -LEN,  -LEN };
266
    for(int i=1; i<numLayers-1; i++)
267
      tmp[currentPosition++] = new float[] { i-LEN,  -LEN,  +LEN };
268
    for(int i=1; i<numLayers-1; i++)
269
      tmp[currentPosition++] = new float[] { i-LEN,  +LEN,  -LEN };
270
    for(int i=1; i<numLayers-1; i++)
271
      tmp[currentPosition++] = new float[] { i-LEN,  +LEN,  +LEN };
272
    for(int i=1; i<numLayers-1; i++)
273
      tmp[currentPosition++] = new float[] {  -LEN, i-LEN,  -LEN };
274
    for(int i=1; i<numLayers-1; i++)
275
      tmp[currentPosition++] = new float[] {  -LEN, i-LEN,  +LEN };
276
    for(int i=1; i<numLayers-1; i++)
277
      tmp[currentPosition++] = new float[] {  +LEN, i-LEN,  -LEN };
278
    for(int i=1; i<numLayers-1; i++)
279
      tmp[currentPosition++] = new float[] {  +LEN, i-LEN,  +LEN };
280
    for(int i=1; i<numLayers-1; i++)
281
      tmp[currentPosition++] = new float[] {  -LEN,  -LEN, i-LEN };
282
    for(int i=1; i<numLayers-1; i++)
283
      tmp[currentPosition++] = new float[] {  -LEN,  +LEN, i-LEN };
284
    for(int i=1; i<numLayers-1; i++)
285
      tmp[currentPosition++] = new float[] {  +LEN,  -LEN, i-LEN };
286
    for(int i=1; i<numLayers-1; i++)
287
      tmp[currentPosition++] = new float[] {  +LEN,  +LEN, i-LEN };
288

    
289
    for(int y=1; y<numLayers-1; y++)
290
      for(int z=1; z<numLayers-1; z++)
291
        tmp[currentPosition++] = new float[] {+LEN,y-LEN,z-LEN};
292

    
293
    for(int y=1; y<numLayers-1; y++)
294
      for(int z=1; z<numLayers-1; z++)
295
        tmp[currentPosition++] = new float[] {-LEN,y-LEN,z-LEN};
296

    
297
    for(int x=1; x<numLayers-1; x++)
298
      for(int z=1; z<numLayers-1; z++)
299
        tmp[currentPosition++] = new float[] {x-LEN,+LEN,z-LEN};
300

    
301
    for(int x=1; x<numLayers-1; x++)
302
      for(int z=1; z<numLayers-1; z++)
303
        tmp[currentPosition++] = new float[] {x-LEN,-LEN,z-LEN};
304

    
305
    for(int x=1; x<numLayers-1; x++)
306
      for(int y=1; y<numLayers-1; y++)
307
        tmp[currentPosition++] = new float[] {x-LEN,y-LEN,+LEN};
308

    
309
    for(int x=1; x<numLayers-1; x++)
310
      for(int y=1; y<numLayers-1; y++)
311
        tmp[currentPosition++] = new float[] {x-LEN,y-LEN,-LEN};
312

    
313
    return tmp;
314
    }
315

    
316
///////////////////////////////////////////////////////////////////////////////////////////////////
317

    
318
  protected Static4D getQuat(int cubit, int numLayers)
319
    {
320
    if( mQuats ==null ) initializeQuats();
321

    
322
    int num = cubit - getNumCornersAndEdges(numLayers);
323

    
324
    if( num>=0 )
325
      {
326
      int face = num/((numLayers-2)*(numLayers-2));
327

    
328
      switch(face)
329
        {
330
        case 0: return mQuats[13];
331
        case 1: return mQuats[12];
332
        case 2: return mQuats[ 8];
333
        case 3: return mQuats[ 9];
334
        case 4: return mQuats[ 0];
335
        case 5: return mQuats[ 1];
336
        }
337
      }
338

    
339
    return mQuats[0];
340
    }
341

    
342
///////////////////////////////////////////////////////////////////////////////////////////////////
343

    
344
  protected int getNumCubitVariants(int numLayers)
345
    {
346
    return numLayers>2 ? 2:1;
347
    }
348

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

    
351
  protected int getCubitVariant(int cubit, int numLayers)
352
    {
353
    return cubit < getNumCornersAndEdges(numLayers) ? 0 : 1;
354
    }
355

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

    
358
  protected int getFaceColor(int cubit, int cubitface, int numLayers)
359
    {
360
    int cornersAndEdges = getNumCornersAndEdges(numLayers);
361

    
362
    if( cubit<cornersAndEdges )
363
      {
364
      return CUBITS[cubit].getRotRow(cubitface/2) == (cubitface%2==0 ? (1<<(numLayers-1)):1) ? cubitface : NUM_TEXTURES;
365
      }
366
    else
367
      {
368
      int numCentersPerFace = (numLayers-2)*(numLayers-2);
369
      return cubitface == 4 ? (cubit-cornersAndEdges)/numCentersPerFace : NUM_TEXTURES;
370
      }
371
    }
372

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

    
375
  protected ObjectSticker retSticker(int face)
376
    {
377
    if( mStickers==null )
378
      {
379
      final float[][] STICKERS = new float[][]  { { -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f } };
380
      final float radius = 0.10f;
381
      final float[] radii = {radius,radius,radius,radius};
382
      mStickers = new ObjectSticker[STICKERS.length];
383
      float stroke = 0.08f;
384

    
385
      if( ObjectControl.isInIconMode() )
386
        {
387
        switch(getNumLayers())
388
          {
389
          case 2: stroke*=1.8f; break;
390
          case 3: stroke*=2.0f; break;
391
          case 4: stroke*=2.1f; break;
392
          default:stroke*=2.2f; break;
393
          }
394
        }
395

    
396
      mStickers[0] = new ObjectSticker(STICKERS[0],null,radii,stroke );
397
      }
398

    
399
    return mStickers[face/NUM_FACE_COLORS];
400
    }
401

    
402
///////////////////////////////////////////////////////////////////////////////////////////////////
403

    
404
  protected Static4D[] getQuats()
405
    {
406
    if( mQuats ==null ) initializeQuats();
407
    return mQuats;
408
    }
409

    
410
///////////////////////////////////////////////////////////////////////////////////////////////////
411

    
412
  protected float[][] getCuts(int numLayers)
413
    {
414
    if( numLayers<2 ) return null;
415

    
416
    if( mCuts==null )
417
      {
418
      mCuts = new float[3][numLayers-1];
419

    
420
      for(int i=0; i<numLayers-1; i++)
421
        {
422
        float cut = (2-numLayers)*0.5f + i;
423
        mCuts[0][i] = cut;
424
        mCuts[1][i] = cut;
425
        mCuts[2][i] = cut;
426
        }
427
      }
428

    
429
    return mCuts;
430
    }
431

    
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433

    
434
  private void getLayerRotatable(int numLayers)
435
    {
436
    if( mLayerRotatable==null )
437
      {
438
      int numAxis = ROT_AXIS.length;
439
      boolean[] tmp = new boolean[numLayers];
440
      for(int i=0; i<numLayers; i++) tmp[i] = true;
441
      mLayerRotatable = new boolean[numAxis][];
442
      for(int i=0; i<numAxis; i++) mLayerRotatable[i] = tmp;
443
      }
444
    }
445

    
446
///////////////////////////////////////////////////////////////////////////////////////////////////
447

    
448
  protected int getSolvedFunctionIndex()
449
    {
450
    return 0;
451
    }
452

    
453
///////////////////////////////////////////////////////////////////////////////////////////////////
454

    
455
  protected int getNumStickerTypes(int numLayers)
456
    {
457
    return 1;
458
    }
459

    
460
///////////////////////////////////////////////////////////////////////////////////////////////////
461

    
462
  protected int getNumCubitFaces()
463
    {
464
    return 6;
465
    }
466

    
467
///////////////////////////////////////////////////////////////////////////////////////////////////
468
// PUBLIC API
469

    
470
  public Static3D[] getRotationAxis()
471
    {
472
    return ROT_AXIS;
473
    }
474

    
475
///////////////////////////////////////////////////////////////////////////////////////////////////
476

    
477
  public Movement getMovement()
478
    {
479
    if( mMovement==null )
480
      {
481
      int numLayers = getNumLayers();
482
      if( mCuts==null ) getCuts(numLayers);
483
      getLayerRotatable(numLayers);
484
      mMovement = new Movement6(ROT_AXIS,mCuts,mLayerRotatable,numLayers,TYPE_NOT_SPLIT,ENABLED);
485
      }
486
    return mMovement;
487
    }
488

    
489
///////////////////////////////////////////////////////////////////////////////////////////////////
490

    
491
  public int[] getBasicAngle()
492
    {
493
    if( mBasicAngle==null ) mBasicAngle = new int[] { 4,4,4 };
494
    return mBasicAngle;
495
    }
496

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

    
499
  public ObjectType intGetObjectType(int numLayers)
500
    {
501
    switch(numLayers)
502
      {
503
      case 2: return ObjectType.CUBE_2;
504
      case 3: return ObjectType.CUBE_3;
505
      case 4: return ObjectType.CUBE_4;
506
      case 5: return ObjectType.CUBE_5;
507
      }
508

    
509
    return ObjectType.CUBE_3;
510
    }
511

    
512
///////////////////////////////////////////////////////////////////////////////////////////////////
513

    
514
  public int getObjectName(int numLayers)
515
    {
516
    switch(numLayers)
517
      {
518
      case 2: return R.string.cube2;
519
      case 3: return R.string.cube3;
520
      case 4: return R.string.cube4;
521
      case 5: return R.string.cube5;
522
      }
523
    return R.string.cube3;
524
    }
525

    
526
///////////////////////////////////////////////////////////////////////////////////////////////////
527

    
528
  public int getInventor(int numLayers)
529
    {
530
    switch(numLayers)
531
      {
532
      case 2: return R.string.cube2_inventor;
533
      case 3: return R.string.cube3_inventor;
534
      case 4: return R.string.cube4_inventor;
535
      case 5: return R.string.cube5_inventor;
536
      }
537
    return R.string.cube3_inventor;
538
    }
539

    
540
///////////////////////////////////////////////////////////////////////////////////////////////////
541

    
542
  public int getComplexity(int numLayers)
543
    {
544
    switch(numLayers)
545
      {
546
      case 2: return 4;
547
      case 3: return 6;
548
      case 4: return 8;
549
      case 5: return 10;
550
      }
551
    return 6;
552
    }
553
}
(6-6/25)