Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyRex.java @ 7d8cc029

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

    
141
  float getScreenRatio()
142
    {
143
    return 1.5f;
144
    }
145

    
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147

    
148
  Static4D[] getQuats()
149
    {
150
    return QUATS;
151
    }
152

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

    
155
  int getNumFaces()
156
    {
157
    return FACE_COLORS.length;
158
    }
159

    
160
///////////////////////////////////////////////////////////////////////////////////////////////////
161

    
162
  boolean shouldResetTextureMaps()
163
    {
164
    return false;
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  int getNumStickerTypes(int numLayers)
170
    {
171
    return 3;
172
    }
173

    
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175

    
176
  float[] getCuts(int numLayers)
177
    {
178
    float C = SQ3*0.15f;   // bit less than 1/6 of the length of the main diagonal
179

    
180
    return new float[] {-C,+C};
181
    }
182

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

    
185
  int getNumCubitFaces()
186
    {
187
    return FACES_PER_CUBIT;
188
    }
189

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

    
192
  float[][] getCubitPositions(int numLayers)
193
    {
194
    final float DIST = 0.50f;
195
    final float DIST2= (1+2*REX_D)/6;
196

    
197
    final float[][] CENTERS = new float[42][];
198

    
199
    CENTERS[ 0] = new float[] { +DIST , +DIST2, +DIST2};
200
    CENTERS[ 1] = new float[] { +DIST , +DIST2, -DIST2};
201
    CENTERS[ 2] = new float[] { +DIST , -DIST2, -DIST2};
202
    CENTERS[ 3] = new float[] { +DIST , -DIST2, +DIST2};
203
    CENTERS[ 4] = new float[] { -DIST , +DIST2, +DIST2};
204
    CENTERS[ 5] = new float[] { -DIST , +DIST2, -DIST2};
205
    CENTERS[ 6] = new float[] { -DIST , -DIST2, -DIST2};
206
    CENTERS[ 7] = new float[] { -DIST , -DIST2, +DIST2};
207
    CENTERS[ 8] = new float[] { +DIST2, +DIST , +DIST2};
208
    CENTERS[ 9] = new float[] { +DIST2, +DIST , -DIST2};
209
    CENTERS[10] = new float[] { -DIST2, +DIST , -DIST2};
210
    CENTERS[11] = new float[] { -DIST2, +DIST , +DIST2};
211
    CENTERS[12] = new float[] { +DIST2, -DIST , +DIST2};
212
    CENTERS[13] = new float[] { +DIST2, -DIST , -DIST2};
213
    CENTERS[14] = new float[] { -DIST2, -DIST , -DIST2};
214
    CENTERS[15] = new float[] { -DIST2, -DIST , +DIST2};
215
    CENTERS[16] = new float[] { +DIST2, +DIST2, +DIST };
216
    CENTERS[17] = new float[] { +DIST2, -DIST2, +DIST };
217
    CENTERS[18] = new float[] { -DIST2, -DIST2, +DIST };
218
    CENTERS[19] = new float[] { -DIST2, +DIST2, +DIST };
219
    CENTERS[20] = new float[] { +DIST2, +DIST2, -DIST };
220
    CENTERS[21] = new float[] { +DIST2, -DIST2, -DIST };
221
    CENTERS[22] = new float[] { -DIST2, -DIST2, -DIST };
222
    CENTERS[23] = new float[] { -DIST2, +DIST2, -DIST };
223

    
224
    CENTERS[24] = new float[] { +DIST , +0.00f, +0.00f};
225
    CENTERS[25] = new float[] { -DIST , +0.00f, +0.00f};
226
    CENTERS[26] = new float[] { +0.00f, +DIST , +0.00f};
227
    CENTERS[27] = new float[] { +0.00f, -DIST , +0.00f};
228
    CENTERS[28] = new float[] { +0.00f, +0.00f, +DIST };
229
    CENTERS[29] = new float[] { +0.00f, +0.00f, -DIST };
230

    
231
    CENTERS[30] = new float[] { +0.00f, +DIST , +DIST };
232
    CENTERS[31] = new float[] { +DIST , +0.00f, +DIST };
233
    CENTERS[32] = new float[] { +0.00f, -DIST , +DIST };
234
    CENTERS[33] = new float[] { -DIST , +0.00f, +DIST };
235
    CENTERS[34] = new float[] { +DIST , +DIST , +0.00f};
236
    CENTERS[35] = new float[] { +DIST , -DIST , +0.00f};
237
    CENTERS[36] = new float[] { -DIST , -DIST , +0.00f};
238
    CENTERS[37] = new float[] { -DIST , +DIST , +0.00f};
239
    CENTERS[38] = new float[] { +0.00f, +DIST , -DIST };
240
    CENTERS[39] = new float[] { +DIST , +0.00f, -DIST };
241
    CENTERS[40] = new float[] { +0.00f, -DIST , -DIST };
242
    CENTERS[41] = new float[] { -DIST , +0.00f, -DIST };
243

    
244
    return CENTERS;
245
    }
246

    
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248

    
249
  private Static4D getQuat(int cubit)
250
    {
251
    switch(cubit)
252
      {
253
      case  0: return new Static4D(+SQ2/2,     0,+SQ2/2,     0);
254
      case  1: return QUATS[5];
255
      case  2: return new Static4D(     0,-SQ2/2,     0, SQ2/2);
256
      case  3: return QUATS[8];
257
      case  4: return QUATS[6];
258
      case  5: return new Static4D(-SQ2/2,     0,+SQ2/2,     0);
259
      case  6: return QUATS[11];
260
      case  7: return new Static4D(     0,+SQ2/2,     0, SQ2/2);
261
      case  8: return new Static4D(+SQ2/2,     0,     0, SQ2/2);
262
      case  9: return QUATS[10];
263
      case 10: return new Static4D(     0,+SQ2/2,+SQ2/2,     0);
264
      case 11: return QUATS[4];
265
      case 12: return QUATS[9];
266
      case 13: return new Static4D(-SQ2/2,     0,     0, SQ2/2);
267
      case 14: return QUATS[7];
268
      case 15: return new Static4D(     0,-SQ2/2,+SQ2/2,     0);
269
      case 16: return new Static4D(     0,     0,-SQ2/2, SQ2/2);
270
      case 17: return QUATS[0];
271
      case 18: return new Static4D(     0,     0,+SQ2/2, SQ2/2);
272
      case 19: return QUATS[3];
273
      case 20: return QUATS[1];
274
      case 21: return new Static4D(+SQ2/2,-SQ2/2,     0,     0);
275
      case 22: return QUATS[2];
276
      case 23: return new Static4D(+SQ2/2,+SQ2/2,     0,     0);
277

    
278
      case 24: return new Static4D(     0,-SQ2/2,     0, SQ2/2);
279
      case 25: return new Static4D(     0,+SQ2/2,     0, SQ2/2);
280
      case 26: return new Static4D(+SQ2/2,     0,     0, SQ2/2);
281
      case 27: return new Static4D(-SQ2/2,     0,     0, SQ2/2);
282
      case 28: return QUATS[0];
283
      case 29: return QUATS[1];
284

    
285
      case 30: return QUATS[0];
286
      case 31: return new Static4D(     0,     0,+SQ2/2, SQ2/2);
287
      case 32: return QUATS[3];
288
      case 33: return new Static4D(     0,     0,-SQ2/2, SQ2/2);
289
      case 34: return new Static4D(     0,-SQ2/2,     0, SQ2/2);
290
      case 35: return QUATS[7];
291
      case 36: return QUATS[9];
292
      case 37: return new Static4D(     0,+SQ2/2,     0, SQ2/2);
293
      case 38: return new Static4D(+SQ2/2,     0,     0, SQ2/2);
294
      case 39: return QUATS[8];
295
      case 40: return QUATS[1];
296
      case 41: return QUATS[6];
297
      }
298

    
299
    return QUATS[0];
300
    }
301

    
302
///////////////////////////////////////////////////////////////////////////////////////////////////
303

    
304
  MeshBase createCubitMesh(int cubit, int numLayers)
305
    {
306
    MeshBase mesh;
307

    
308
    if( cubit<24 )
309
      {
310
      if( mCornerMesh==null ) mCornerMesh = FactoryCubit.getInstance().createRexCornerMesh();
311
      mesh = mCornerMesh.copy(true);
312
      }
313
    else if( cubit<30 )
314
      {
315
      if( mFaceMesh==null ) mFaceMesh = FactoryCubit.getInstance().createRexFaceMesh();
316
      mesh = mFaceMesh.copy(true);
317
      }
318
    else
319
      {
320
      if( mEdgeMesh==null ) mEdgeMesh = FactoryCubit.getInstance().createRexEdgeMesh();
321
      mesh = mEdgeMesh.copy(true);
322
      }
323

    
324
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit), new Static3D(0,0,0) );
325
    mesh.apply(quat,0xffffffff,0);
326

    
327
    return mesh;
328
    }
329

    
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331

    
332
  int getFaceColor(int cubit, int cubitface, int numLayers)
333
    {
334
    return mFaceMap[cubit][cubitface];
335
    }
336

    
337
///////////////////////////////////////////////////////////////////////////////////////////////////
338

    
339
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
340
    {
341
    int COLORS = FACE_COLORS.length;
342
    FactorySticker factory = FactorySticker.getInstance();
343
    float S1 = 0.050f;
344
    float S2 = 0.051f;
345
    float R1 = 0.07f;
346
    float R2 = 0.02f;
347
    float R3 = 0.06f;
348
    float R4 = 0.04f;
349

    
350
    if( face<COLORS )
351
      {
352
      factory.drawRexCornerSticker(canvas, paint, left, top, FACE_COLORS[face%COLORS], S1, R2, R3);
353
      }
354
    else if( face<2*COLORS )
355
      {
356
      float[] vertices = { -REX_D,0.0f, 0.0f, -REX_D, +REX_D, 0.0f, 0.0f, +REX_D};
357
      factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S1, FACE_COLORS[face%COLORS], R4);
358
      }
359
    else
360
      {
361
      factory.drawRexEdgeSticker(canvas, paint, left, top, FACE_COLORS[face%COLORS], S2, R1);
362
      }
363
    }
364

    
365
///////////////////////////////////////////////////////////////////////////////////////////////////
366

    
367
  float returnMultiplier()
368
    {
369
    return 2.0f;
370
    }
371

    
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373

    
374
  float[] getRowChances(int numLayers)
375
    {
376
    return new float[] { 0.5f, 0.5f, 1.0f };
377
    }
378

    
379
///////////////////////////////////////////////////////////////////////////////////////////////////
380
// PUBLIC API
381

    
382
  public Static3D[] getRotationAxis()
383
    {
384
    return ROT_AXIS;
385
    }
386

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

    
389
  public int getBasicAngle()
390
    {
391
    return 3;
392
    }
393

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

    
396
  public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
397
    {
398
    if( num==0 )
399
      {
400
      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
401
      }
402
    else
403
      {
404
      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
405
      scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
406
      }
407

    
408
    float rowFloat = rnd.nextFloat();
409

    
410
    for(int row=0; row<mRowChances.length; row++)
411
      {
412
      if( rowFloat<=mRowChances[row] )
413
        {
414
        scramble[num][1] = row;
415
        break;
416
        }
417
      }
418

    
419
    switch( rnd.nextInt(2) )
420
      {
421
      case 0: scramble[num][2] = -1; break;
422
      case 1: scramble[num][2] =  1; break;
423
      }
424
    }
425

    
426
///////////////////////////////////////////////////////////////////////////////////////////////////
427
// The Rex is solved if and only if:
428
//
429
// 1) all 12 of its edge cubits are rotated with the same quat
430
// 2) all its face & corner cubits are rotated with the same quat like the edge ones,
431
//    and optionally they also might be upside down.
432
//
433
// i.e.
434
// corners ( 0, 1, 2, 3, 4, 5, 6, 7) and faces (24,25) - might be extra QUAT[1]
435
// corners ( 8, 9,10,11,12,13,14,15) and faces (26,27) - might be extra QUAT[2]
436
// corners (16,17,18,19,20,21,22,23) and faces (28,29) - might be extra QUAT[3]
437

    
438
  public boolean isSolved()
439
    {
440
    int q1,q = CUBITS[30].mQuatIndex;
441

    
442
    for(int i=31; i<42; i++)
443
      {
444
      if( CUBITS[i].mQuatIndex != q) return false;
445
      }
446

    
447
    q1 = mulQuat(q,1);
448

    
449
    for(int i=0; i<8; i++)
450
      {
451
      if( CUBITS[i].mQuatIndex != q && CUBITS[i].mQuatIndex != q1 ) return false;
452
      }
453

    
454
    if( CUBITS[24].mQuatIndex != q && CUBITS[24].mQuatIndex != q1 ) return false;
455
    if( CUBITS[25].mQuatIndex != q && CUBITS[25].mQuatIndex != q1 ) return false;
456

    
457
    q1 = mulQuat(q,2);
458

    
459
    for(int i=8; i<16; i++)
460
      {
461
      if( CUBITS[i].mQuatIndex != q && CUBITS[i].mQuatIndex != q1 ) return false;
462
      }
463

    
464
    if( CUBITS[26].mQuatIndex != q && CUBITS[26].mQuatIndex != q1 ) return false;
465
    if( CUBITS[27].mQuatIndex != q && CUBITS[27].mQuatIndex != q1 ) return false;
466

    
467
    q1 = mulQuat(q,3);
468

    
469
    for(int i=16; i<24; i++)
470
      {
471
      if( CUBITS[i].mQuatIndex != q && CUBITS[i].mQuatIndex != q1 ) return false;
472
      }
473

    
474
    if( CUBITS[28].mQuatIndex != q && CUBITS[28].mQuatIndex != q1 ) return false;
475
    if( CUBITS[29].mQuatIndex != q && CUBITS[29].mQuatIndex != q1 ) return false;
476

    
477
    return true;
478
    }
479

    
480
///////////////////////////////////////////////////////////////////////////////////////////////////
481
// only needed for solvers - there are no Rex solvers ATM
482

    
483
  public String retObjectString()
484
    {
485
    return "";
486
    }
487

    
488
///////////////////////////////////////////////////////////////////////////////////////////////////
489

    
490
  public int getObjectName(int numLayers)
491
    {
492
    return R.string.rex3;
493
    }
494

    
495
///////////////////////////////////////////////////////////////////////////////////////////////////
496

    
497
  public int getInventor(int numLayers)
498
    {
499
    return R.string.rex3_inventor;
500
    }
501

    
502
///////////////////////////////////////////////////////////////////////////////////////////////////
503

    
504
  public int getComplexity(int numLayers)
505
    {
506
    return 3;
507
    }
508
}
(32-32/33)