Project

General

Profile

Download (18.2 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / objects / TwistyRex.java @ cb137f36

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 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.objects;
21

    
22
import android.content.res.Resources;
23
import android.graphics.Canvas;
24
import android.graphics.Paint;
25

    
26
import org.distorted.helpers.FactoryCubit;
27
import org.distorted.helpers.FactorySticker;
28
import org.distorted.library.effect.MatrixEffectQuaternion;
29
import org.distorted.library.main.DistortedEffects;
30
import org.distorted.library.main.DistortedTexture;
31
import org.distorted.library.mesh.MeshBase;
32
import org.distorted.library.mesh.MeshSquare;
33
import org.distorted.library.type.Static3D;
34
import org.distorted.library.type.Static4D;
35
import org.distorted.main.R;
36

    
37
import java.util.Random;
38

    
39
import static org.distorted.helpers.FactoryCubit.REX_D;
40

    
41
///////////////////////////////////////////////////////////////////////////////////////////////////
42

    
43
public class TwistyRex extends TwistyObject
44
{
45
  private static final int FACES_PER_CUBIT =6;
46

    
47
  // the four rotation axis of a RubikRex. Must be normalized.
48
  static final Static3D[] ROT_AXIS = new Static3D[]
49
         {
50
           new Static3D(+SQ3/3,+SQ3/3,+SQ3/3),
51
           new Static3D(+SQ3/3,+SQ3/3,-SQ3/3),
52
           new Static3D(+SQ3/3,-SQ3/3,+SQ3/3),
53
           new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)
54
         };
55

    
56
  private static final int[] FACE_COLORS = new int[]
57
         {
58
           COLOR_YELLOW, COLOR_WHITE,
59
           COLOR_BLUE  , COLOR_GREEN,
60
           COLOR_RED   , COLOR_ORANGE
61
         };
62

    
63
  // All legal rotation quats of a RubikRex
64
  private static final Static4D[] QUATS = new Static4D[]
65
         {
66
           new Static4D(  0.0f,  0.0f,  0.0f,  1.0f ),
67
           new Static4D(  1.0f,  0.0f,  0.0f,  0.0f ),
68
           new Static4D(  0.0f,  1.0f,  0.0f,  0.0f ),
69
           new Static4D(  0.0f,  0.0f,  1.0f,  0.0f ),
70

    
71
           new Static4D(  0.5f,  0.5f,  0.5f,  0.5f ),
72
           new Static4D(  0.5f,  0.5f,  0.5f, -0.5f ),
73
           new Static4D(  0.5f,  0.5f, -0.5f,  0.5f ),
74
           new Static4D(  0.5f,  0.5f, -0.5f, -0.5f ),
75
           new Static4D(  0.5f, -0.5f,  0.5f,  0.5f ),
76
           new Static4D(  0.5f, -0.5f,  0.5f, -0.5f ),
77
           new Static4D(  0.5f, -0.5f, -0.5f,  0.5f ),
78
           new Static4D(  0.5f, -0.5f, -0.5f, -0.5f )
79
         };
80

    
81
  private static final int[][] mFaceMap =
82
         {
83
           {  0, 18,18,18,18,18 },
84
           {  0, 18,18,18,18,18 },
85
           {  0, 18,18,18,18,18 },
86
           {  0, 18,18,18,18,18 },
87
           {  1, 18,18,18,18,18 },
88
           {  1, 18,18,18,18,18 },
89
           {  1, 18,18,18,18,18 },
90
           {  1, 18,18,18,18,18 },
91
           {  2, 18,18,18,18,18 },
92
           {  2, 18,18,18,18,18 },
93
           {  2, 18,18,18,18,18 },
94
           {  2, 18,18,18,18,18 },
95
           {  3, 18,18,18,18,18 },
96
           {  3, 18,18,18,18,18 },
97
           {  3, 18,18,18,18,18 },
98
           {  3, 18,18,18,18,18 },
99
           {  4, 18,18,18,18,18 },
100
           {  4, 18,18,18,18,18 },
101
           {  4, 18,18,18,18,18 },
102
           {  4, 18,18,18,18,18 },
103
           {  5, 18,18,18,18,18 },
104
           {  5, 18,18,18,18,18 },
105
           {  5, 18,18,18,18,18 },
106
           {  5, 18,18,18,18,18 },
107

    
108
           {  6, 18,18,18,18,18 },
109
           {  7, 18,18,18,18,18 },
110
           {  8, 18,18,18,18,18 },
111
           {  9, 18,18,18,18,18 },
112
           { 10, 18,18,18,18,18 },
113
           { 11, 18,18,18,18,18 },
114

    
115
           { 16,14, 18,18,18,18 },
116
           { 16,12, 18,18,18,18 },
117
           { 16,15, 18,18,18,18 },
118
           { 16,13, 18,18,18,18 },
119
           { 12,14, 18,18,18,18 },
120
           { 15,12, 18,18,18,18 },
121
           { 15,13, 18,18,18,18 },
122
           { 13,14, 18,18,18,18 },
123
           { 14,17, 18,18,18,18 },
124
           { 12,17, 18,18,18,18 },
125
           { 17,15, 18,18,18,18 },
126
           { 13,17, 18,18,18,18 },
127
         };
128

    
129
  private static MeshBase mCornerMesh, mFaceMesh, mEdgeMesh;
130

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

    
133
  TwistyRex(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
134
            DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
135
    {
136
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.REX, res, scrWidth);
137
    }
138

    
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140
// don't use this
141

    
142
  double[][] getVertices(int cubitType)
143
    {
144
    return null;
145
    }
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148
// don't use this
149

    
150
  int[][] getVertIndexes(int cubitType)
151
    {
152
    return null;
153
    }
154

    
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156

    
157
  int getNumCubitTypes(int numLayers)
158
    {
159
    return 2;
160
    }
161

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

    
164
  float getScreenRatio()
165
    {
166
    return 1.5f;
167
    }
168

    
169
///////////////////////////////////////////////////////////////////////////////////////////////////
170

    
171
  Static4D[] getQuats()
172
    {
173
    return QUATS;
174
    }
175

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

    
178
  int getNumFaces()
179
    {
180
    return FACE_COLORS.length;
181
    }
182

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

    
185
  boolean shouldResetTextureMaps()
186
    {
187
    return false;
188
    }
189

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191

    
192
  int getNumStickerTypes(int numLayers)
193
    {
194
    return 3;
195
    }
196

    
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198

    
199
  float[] getCuts(int numLayers)
200
    {
201
    float C = SQ3*0.15f;   // bit less than 1/6 of the length of the main diagonal
202

    
203
    return new float[] {-C,+C};
204
    }
205

    
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

    
208
  int getNumCubitFaces()
209
    {
210
    return FACES_PER_CUBIT;
211
    }
212

    
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214

    
215
  float[][] getCubitPositions(int numLayers)
216
    {
217
    final float DIST = 0.50f;
218
    final float DIST2= (1+2*REX_D)/6;
219

    
220
    final float[][] CENTERS = new float[42][];
221

    
222
    CENTERS[ 0] = new float[] { +DIST , +DIST2, +DIST2};
223
    CENTERS[ 1] = new float[] { +DIST , +DIST2, -DIST2};
224
    CENTERS[ 2] = new float[] { +DIST , -DIST2, -DIST2};
225
    CENTERS[ 3] = new float[] { +DIST , -DIST2, +DIST2};
226
    CENTERS[ 4] = new float[] { -DIST , +DIST2, +DIST2};
227
    CENTERS[ 5] = new float[] { -DIST , +DIST2, -DIST2};
228
    CENTERS[ 6] = new float[] { -DIST , -DIST2, -DIST2};
229
    CENTERS[ 7] = new float[] { -DIST , -DIST2, +DIST2};
230
    CENTERS[ 8] = new float[] { +DIST2, +DIST , +DIST2};
231
    CENTERS[ 9] = new float[] { +DIST2, +DIST , -DIST2};
232
    CENTERS[10] = new float[] { -DIST2, +DIST , -DIST2};
233
    CENTERS[11] = new float[] { -DIST2, +DIST , +DIST2};
234
    CENTERS[12] = new float[] { +DIST2, -DIST , +DIST2};
235
    CENTERS[13] = new float[] { +DIST2, -DIST , -DIST2};
236
    CENTERS[14] = new float[] { -DIST2, -DIST , -DIST2};
237
    CENTERS[15] = new float[] { -DIST2, -DIST , +DIST2};
238
    CENTERS[16] = new float[] { +DIST2, +DIST2, +DIST };
239
    CENTERS[17] = new float[] { +DIST2, -DIST2, +DIST };
240
    CENTERS[18] = new float[] { -DIST2, -DIST2, +DIST };
241
    CENTERS[19] = new float[] { -DIST2, +DIST2, +DIST };
242
    CENTERS[20] = new float[] { +DIST2, +DIST2, -DIST };
243
    CENTERS[21] = new float[] { +DIST2, -DIST2, -DIST };
244
    CENTERS[22] = new float[] { -DIST2, -DIST2, -DIST };
245
    CENTERS[23] = new float[] { -DIST2, +DIST2, -DIST };
246

    
247
    CENTERS[24] = new float[] { +DIST , +0.00f, +0.00f};
248
    CENTERS[25] = new float[] { -DIST , +0.00f, +0.00f};
249
    CENTERS[26] = new float[] { +0.00f, +DIST , +0.00f};
250
    CENTERS[27] = new float[] { +0.00f, -DIST , +0.00f};
251
    CENTERS[28] = new float[] { +0.00f, +0.00f, +DIST };
252
    CENTERS[29] = new float[] { +0.00f, +0.00f, -DIST };
253

    
254
    CENTERS[30] = new float[] { +0.00f, +DIST , +DIST };
255
    CENTERS[31] = new float[] { +DIST , +0.00f, +DIST };
256
    CENTERS[32] = new float[] { +0.00f, -DIST , +DIST };
257
    CENTERS[33] = new float[] { -DIST , +0.00f, +DIST };
258
    CENTERS[34] = new float[] { +DIST , +DIST , +0.00f};
259
    CENTERS[35] = new float[] { +DIST , -DIST , +0.00f};
260
    CENTERS[36] = new float[] { -DIST , -DIST , +0.00f};
261
    CENTERS[37] = new float[] { -DIST , +DIST , +0.00f};
262
    CENTERS[38] = new float[] { +0.00f, +DIST , -DIST };
263
    CENTERS[39] = new float[] { +DIST , +0.00f, -DIST };
264
    CENTERS[40] = new float[] { +0.00f, -DIST , -DIST };
265
    CENTERS[41] = new float[] { -DIST , +0.00f, -DIST };
266

    
267
    return CENTERS;
268
    }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271

    
272
  private Static4D getQuat(int cubit)
273
    {
274
    switch(cubit)
275
      {
276
      case  0: return new Static4D(+SQ2/2,     0,+SQ2/2,     0);
277
      case  1: return QUATS[5];
278
      case  2: return new Static4D(     0,-SQ2/2,     0, SQ2/2);
279
      case  3: return QUATS[8];
280
      case  4: return QUATS[6];
281
      case  5: return new Static4D(-SQ2/2,     0,+SQ2/2,     0);
282
      case  6: return QUATS[11];
283
      case  7: return new Static4D(     0,+SQ2/2,     0, SQ2/2);
284
      case  8: return new Static4D(+SQ2/2,     0,     0, SQ2/2);
285
      case  9: return QUATS[10];
286
      case 10: return new Static4D(     0,+SQ2/2,+SQ2/2,     0);
287
      case 11: return QUATS[4];
288
      case 12: return QUATS[9];
289
      case 13: return new Static4D(-SQ2/2,     0,     0, SQ2/2);
290
      case 14: return QUATS[7];
291
      case 15: return new Static4D(     0,-SQ2/2,+SQ2/2,     0);
292
      case 16: return new Static4D(     0,     0,-SQ2/2, SQ2/2);
293
      case 17: return QUATS[0];
294
      case 18: return new Static4D(     0,     0,+SQ2/2, SQ2/2);
295
      case 19: return QUATS[3];
296
      case 20: return QUATS[1];
297
      case 21: return new Static4D(+SQ2/2,-SQ2/2,     0,     0);
298
      case 22: return QUATS[2];
299
      case 23: return new Static4D(+SQ2/2,+SQ2/2,     0,     0);
300

    
301
      case 24: return new Static4D(     0,-SQ2/2,     0, SQ2/2);
302
      case 25: return new Static4D(     0,+SQ2/2,     0, SQ2/2);
303
      case 26: return new Static4D(+SQ2/2,     0,     0, SQ2/2);
304
      case 27: return new Static4D(-SQ2/2,     0,     0, SQ2/2);
305
      case 28: return QUATS[0];
306
      case 29: return QUATS[1];
307

    
308
      case 30: return QUATS[0];
309
      case 31: return new Static4D(     0,     0,+SQ2/2, SQ2/2);
310
      case 32: return QUATS[3];
311
      case 33: return new Static4D(     0,     0,-SQ2/2, SQ2/2);
312
      case 34: return new Static4D(     0,-SQ2/2,     0, SQ2/2);
313
      case 35: return QUATS[7];
314
      case 36: return QUATS[9];
315
      case 37: return new Static4D(     0,+SQ2/2,     0, SQ2/2);
316
      case 38: return new Static4D(+SQ2/2,     0,     0, SQ2/2);
317
      case 39: return QUATS[8];
318
      case 40: return QUATS[1];
319
      case 41: return QUATS[6];
320
      }
321

    
322
    return QUATS[0];
323
    }
324

    
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326

    
327
  MeshBase createCubitMesh(int cubit, int numLayers)
328
    {
329
    MeshBase mesh;
330

    
331
    if( cubit<24 )
332
      {
333
      if( mCornerMesh==null ) mCornerMesh = FactoryCubit.getInstance().createRexCornerMesh();
334
      mesh = mCornerMesh.copy(true);
335
      }
336
    else if( cubit<30 )
337
      {
338
      if( mFaceMesh==null ) mFaceMesh = FactoryCubit.getInstance().createRexFaceMesh();
339
      mesh = mFaceMesh.copy(true);
340
      }
341
    else
342
      {
343
      if( mEdgeMesh==null ) mEdgeMesh = FactoryCubit.getInstance().createRexEdgeMesh();
344
      mesh = mEdgeMesh.copy(true);
345
      }
346

    
347
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit), new Static3D(0,0,0) );
348
    mesh.apply(quat,0xffffffff,0);
349

    
350
    return mesh;
351
    }
352

    
353
///////////////////////////////////////////////////////////////////////////////////////////////////
354

    
355
  int getFaceColor(int cubit, int cubitface, int numLayers)
356
    {
357
    return mFaceMap[cubit][cubitface];
358
    }
359

    
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361

    
362
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
363
    {
364
    int COLORS = FACE_COLORS.length;
365
    FactorySticker factory = FactorySticker.getInstance();
366
    float S1 = 0.050f;
367
    float S2 = 0.051f;
368
    float R1 = 0.07f;
369
    float R2 = 0.02f;
370
    float R3 = 0.06f;
371
    float R4 = 0.04f;
372

    
373
    if( face<COLORS )
374
      {
375
      factory.drawRexCornerSticker(canvas, paint, left, top, FACE_COLORS[face%COLORS], S1, R2, R3);
376
      }
377
    else if( face<2*COLORS )
378
      {
379
      float[] vertices = { -REX_D,0.0f, 0.0f, -REX_D, +REX_D, 0.0f, 0.0f, +REX_D};
380
      factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S1, FACE_COLORS[face%COLORS], R4);
381
      }
382
    else
383
      {
384
      factory.drawRexEdgeSticker(canvas, paint, left, top, FACE_COLORS[face%COLORS], S2, R1);
385
      }
386
    }
387

    
388
///////////////////////////////////////////////////////////////////////////////////////////////////
389

    
390
  float returnMultiplier()
391
    {
392
    return 2.0f;
393
    }
394

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

    
397
  float[] getRowChances(int numLayers)
398
    {
399
    return new float[] { 0.5f, 0.5f, 1.0f };
400
    }
401

    
402
///////////////////////////////////////////////////////////////////////////////////////////////////
403
// PUBLIC API
404

    
405
  public Static3D[] getRotationAxis()
406
    {
407
    return ROT_AXIS;
408
    }
409

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

    
412
  public int getBasicAngle()
413
    {
414
    return 3;
415
    }
416

    
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418

    
419
  public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
420
    {
421
    if( num==0 )
422
      {
423
      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
424
      }
425
    else
426
      {
427
      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
428
      scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
429
      }
430

    
431
    float rowFloat = rnd.nextFloat();
432

    
433
    for(int row=0; row<mRowChances.length; row++)
434
      {
435
      if( rowFloat<=mRowChances[row] )
436
        {
437
        scramble[num][1] = row;
438
        break;
439
        }
440
      }
441

    
442
    switch( rnd.nextInt(2) )
443
      {
444
      case 0: scramble[num][2] = -1; break;
445
      case 1: scramble[num][2] =  1; break;
446
      }
447
    }
448

    
449
///////////////////////////////////////////////////////////////////////////////////////////////////
450
// The Rex is solved if and only if:
451
//
452
// 1) all 12 of its edge cubits are rotated with the same quat
453
// 2) all its face & corner cubits are rotated with the same quat like the edge ones,
454
//    and optionally they also might be upside down.
455
//
456
// i.e.
457
// corners ( 0, 1, 2, 3, 4, 5, 6, 7) and faces (24,25) - might be extra QUAT[1]
458
// corners ( 8, 9,10,11,12,13,14,15) and faces (26,27) - might be extra QUAT[2]
459
// corners (16,17,18,19,20,21,22,23) and faces (28,29) - might be extra QUAT[3]
460

    
461
  public boolean isSolved()
462
    {
463
    int q1,q = CUBITS[30].mQuatIndex;
464

    
465
    for(int i=31; i<42; i++)
466
      {
467
      if( CUBITS[i].mQuatIndex != q) return false;
468
      }
469

    
470
    q1 = mulQuat(q,1);
471

    
472
    for(int i=0; i<8; i++)
473
      {
474
      if( CUBITS[i].mQuatIndex != q && CUBITS[i].mQuatIndex != q1 ) return false;
475
      }
476

    
477
    if( CUBITS[24].mQuatIndex != q && CUBITS[24].mQuatIndex != q1 ) return false;
478
    if( CUBITS[25].mQuatIndex != q && CUBITS[25].mQuatIndex != q1 ) return false;
479

    
480
    q1 = mulQuat(q,2);
481

    
482
    for(int i=8; i<16; i++)
483
      {
484
      if( CUBITS[i].mQuatIndex != q && CUBITS[i].mQuatIndex != q1 ) return false;
485
      }
486

    
487
    if( CUBITS[26].mQuatIndex != q && CUBITS[26].mQuatIndex != q1 ) return false;
488
    if( CUBITS[27].mQuatIndex != q && CUBITS[27].mQuatIndex != q1 ) return false;
489

    
490
    q1 = mulQuat(q,3);
491

    
492
    for(int i=16; i<24; i++)
493
      {
494
      if( CUBITS[i].mQuatIndex != q && CUBITS[i].mQuatIndex != q1 ) return false;
495
      }
496

    
497
    if( CUBITS[28].mQuatIndex != q && CUBITS[28].mQuatIndex != q1 ) return false;
498
    if( CUBITS[29].mQuatIndex != q && CUBITS[29].mQuatIndex != q1 ) return false;
499

    
500
    return true;
501
    }
502

    
503
///////////////////////////////////////////////////////////////////////////////////////////////////
504
// only needed for solvers - there are no Rex solvers ATM
505

    
506
  public String retObjectString()
507
    {
508
    return "";
509
    }
510

    
511
///////////////////////////////////////////////////////////////////////////////////////////////////
512

    
513
  public int getObjectName(int numLayers)
514
    {
515
    return R.string.rex3;
516
    }
517

    
518
///////////////////////////////////////////////////////////////////////////////////////////////////
519

    
520
  public int getInventor(int numLayers)
521
    {
522
    return R.string.rex3_inventor;
523
    }
524

    
525
///////////////////////////////////////////////////////////////////////////////////////////////////
526

    
527
  public int getComplexity(int numLayers)
528
    {
529
    return 3;
530
    }
531
}
(32-32/33)