Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyRex.java @ 59b87d56

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.library.effect.MatrixEffectQuaternion;
27
import org.distorted.library.main.DistortedEffects;
28
import org.distorted.library.main.DistortedTexture;
29
import org.distorted.library.mesh.MeshBase;
30
import org.distorted.library.mesh.MeshSquare;
31
import org.distorted.library.type.Static3D;
32
import org.distorted.library.type.Static4D;
33
import org.distorted.main.R;
34
import org.distorted.main.RubikSurfaceView;
35

    
36
import java.util.Random;
37

    
38
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
39

    
40
///////////////////////////////////////////////////////////////////////////////////////////////////
41

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

    
46
  // the four rotation axis of a RubikRex. Must be normalized.
47
  static final Static3D[] ROT_AXIS = new Static3D[]
48
         {
49
           new Static3D(+SQ3/3,+SQ3/3,+SQ3/3),
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
         };
54

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

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

    
70
           new Static4D(  0.5f,  0.5f,  0.5f,  0.5f ),
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
         };
79

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

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

    
114
           {  4, 2, 18,18 },
115
           {  4, 0, 18,18 },
116
           {  4, 3, 18,18 },
117
           {  4, 1, 18,18 },
118
           {  0, 2, 18,18 },
119
           {  3, 0, 18,18 },
120
           {  1, 3, 18,18 },
121
           {  3, 2, 18,18 },
122
           {  5, 2, 18,18 },
123
           {  5, 0, 18,18 },
124
           {  5, 3, 18,18 },
125
           {  5, 1, 18,18 },
126
         };
127

    
128
  private static MeshBase mCornerMesh, mFaceMesh, mEdgeMesh;
129

    
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131

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

    
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139

    
140
  float getScreenRatio()
141
    {
142
    return 1.0f;
143
    }
144

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

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

    
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153

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

    
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160

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

    
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167

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

    
173
///////////////////////////////////////////////////////////////////////////////////////////////////
174

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

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

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183

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

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

    
191
  Static3D[] getCubitPositions(int numLayers)
192
    {
193
    final float DIST = 0.50f;
194
    final float E    = SQ3/3;
195

    
196
    final Static3D[] CENTERS = new Static3D[42];
197

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

    
223
    CENTERS[24] = new Static3D( +DIST  , +0.00f , +0.00f );
224
    CENTERS[25] = new Static3D( -DIST  , +0.00f , +0.00f );
225
    CENTERS[26] = new Static3D( +0.00f , +DIST  , +0.00f );
226
    CENTERS[27] = new Static3D( +0.00f , -DIST  , +0.00f );
227
    CENTERS[28] = new Static3D( +0.00f , +0.00f , +DIST  );
228
    CENTERS[29] = new Static3D( +0.00f , +0.00f , -DIST  );
229

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

    
243
    return CENTERS;
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247
// 1  +90 ( 1, 0, 0) = Static4D(+SQ2/2,     0,     0, SQ2/2);
248
// 2  -90 ( 1, 0, 0) = Static4D(-SQ2/2,     0,     0, SQ2/2);
249
// 3  +90 ( 0, 1, 0) = Static4D(     0,+SQ2/2,     0, SQ2/2);
250
// 4  -90 ( 0, 1, 0) = Static4D(     0,-SQ2/2,     0, SQ2/2);
251
// 5  +90 ( 0, 0, 1) = Static4D(     0,     0,+SQ2/2, SQ2/2);
252
// 6  -90 ( 0, 0, 1) = Static4D(     0,     0,-SQ2/2, SQ2/2);
253
// 7  180 ( 1, 0, 1) = Static4D(+SQ2/2,     0,+SQ2/2,     0);
254
// 8  180 (-1, 0, 1) = Static4D(-SQ2/2,     0,+SQ2/2,     0);
255
// 9  180 ( 0, 1, 1) = Static4D(     0,+SQ2/2,+SQ2/2,     0);
256
//10  180 ( 0,-1, 1) = Static4D(     0,-SQ2/2,+SQ2/2,     0);
257
//11  180 ( 1, 1, 0) = Static4D(+SQ2/2,+SQ2/2,     0,     0);
258
//12  180 ( 1,-1, 0) = Static4D(+SQ2/2,-SQ2/2,     0,     0);
259

    
260
  private Static4D getQuat(int cubit)
261
    {
262
    switch(cubit)
263
      {
264
      case  0: return QUATS[5];
265
      case  1: return new Static4D(     0,+SQ2/2,     0, SQ2/2);
266
      case  2: return QUATS[8];
267
      case  3: return new Static4D(+SQ2/2,     0,+SQ2/2,     0);
268
      case  4: return QUATS[6];
269
      case  5: return new Static4D(     0,     0,+SQ2/2, SQ2/2);
270
      case  6: return QUATS[11];
271
      case  7: return new Static4D(-SQ2/2,     0,+SQ2/2,     0);
272
      case  8: return QUATS[10];
273
      case  9: return new Static4D(+SQ2/2,     0,     0, SQ2/2);
274
      case 10: return new Static4D(     0,+SQ2/2,+SQ2/2,     0);
275
      case 11: return QUATS[4];
276
      case 12: return QUATS[9];
277
      case 13: return new Static4D(-SQ2/2,     0,     0, SQ2/2);
278
      case 14: return QUATS[7];
279
      case 15: return new Static4D(     0,-SQ2/2,+SQ2/2,     0);
280
      case 16: return new Static4D(     0,     0,-SQ2/2, SQ2/2);
281
      case 17: return QUATS[0];
282
      case 18: return new Static4D(     0,     0,+SQ2/2, SQ2/2);
283
      case 19: return QUATS[3];
284
      case 20: return new Static4D(+SQ2/2,+SQ2/2,     0,     0);
285
      case 21: return QUATS[2];
286
      case 22: return new Static4D(+SQ2/2,-SQ2/2,     0,     0);
287
      case 23: return QUATS[1];
288

    
289
      case 24: return new Static4D(     0,+SQ2/2,     0, SQ2/2);
290
      case 25: return new Static4D(     0,-SQ2/2,     0, SQ2/2);
291
      case 26: return new Static4D(+SQ2/2,     0,     0, SQ2/2);
292
      case 27: return new Static4D(-SQ2/2,     0,     0, SQ2/2);
293
      case 28: return QUATS[0];
294
      case 29: return QUATS[1];
295

    
296
      case 30: return QUATS[0];
297
      case 31: return new Static4D(     0,     0,+SQ2/2, SQ2/2);
298
      case 32: return QUATS[3];
299
      case 33: return new Static4D(     0,     0,-SQ2/2, SQ2/2);
300
      case 34: return new Static4D(     0,+SQ2/2,     0, SQ2/2);
301
      case 35: return QUATS[7];
302
      case 36: return QUATS[9];
303
      case 37: return new Static4D(     0,-SQ2/2,     0, SQ2/2);
304
      case 38: return new Static4D(+SQ2/2,     0,     0, SQ2/2);
305
      case 39: return QUATS[8];
306
      case 40: return QUATS[1];
307
      case 41: return QUATS[6];
308
      }
309

    
310
    return QUATS[0];
311
    }
312

    
313
///////////////////////////////////////////////////////////////////////////////////////////////////
314

    
315
  MeshBase createCubitMesh(int cubit)
316
    {
317
    MeshBase mesh;
318

    
319
    if( cubit<12 )
320
      {
321
      if( mCornerMesh==null ) mCornerMesh = FactoryCubit.getInstance().createRexCornerMesh();
322
      mesh = mCornerMesh.copy(true);
323
      }
324
    else if( cubit<18 )
325
      {
326
      if( mFaceMesh==null ) mFaceMesh = FactoryCubit.getInstance().createRexFaceMesh();
327
      mesh = mFaceMesh.copy(true);
328
      }
329
    else
330
      {
331
      if( mEdgeMesh==null ) mEdgeMesh = FactoryCubit.getInstance().createRexEdgeMesh();
332
      mesh = mEdgeMesh.copy(true);
333
      }
334

    
335
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit), new Static3D(0,0,0) );
336
    mesh.apply(quat,0xffffffff,0);
337

    
338
    return mesh;
339
    }
340

    
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342

    
343
  int getFaceColor(int cubit, int cubitface, int numLayers)
344
    {
345
    return mFaceMap[cubit][cubitface];
346
    }
347

    
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

    
350
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
351
    {
352
    int COLORS = FACE_COLORS.length;
353
    FactorySticker factory = FactorySticker.getInstance();
354
    float S = 0.08f;
355
    float R = 0.12f;
356

    
357
    if( face<COLORS )
358
      {
359
      factory.drawRexCornerSticker(canvas, paint, left, top, FACE_COLORS[face%COLORS], S, R);
360
      }
361
    else if( face<2*COLORS )
362
      {
363
      factory.drawRexFaceSticker(canvas, paint, left, top, FACE_COLORS[face%COLORS], S, R);
364
      }
365
    else
366
      {
367
      factory.drawRexEdgeSticker(canvas, paint, left, top, FACE_COLORS[face%COLORS], S, R);
368
      }
369
    }
370

    
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

    
373
  float returnMultiplier()
374
    {
375
    return 2.0f;
376
    }
377

    
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

    
380
  float[] getRowChances()
381
    {
382
    return new float[] { 0.5f, 0.5f, 1.0f };
383
    }
384

    
385
///////////////////////////////////////////////////////////////////////////////////////////////////
386
// PUBLIC API
387

    
388
  public Static3D[] getRotationAxis()
389
    {
390
    return ROT_AXIS;
391
    }
392

    
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394

    
395
  public int getBasicAngle()
396
    {
397
    return 3;
398
    }
399

    
400
///////////////////////////////////////////////////////////////////////////////////////////////////
401

    
402
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
403
    {
404
    int numAxis = ROTATION_AXIS.length;
405

    
406
    if( oldRotAxis == START_AXIS )
407
      {
408
      return rnd.nextInt(numAxis);
409
      }
410
    else
411
      {
412
      int newVector = rnd.nextInt(numAxis-1);
413
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
414
      }
415
    }
416

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

    
419
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
420
    {
421
    float rowFloat = rnd.nextFloat();
422

    
423
    for(int row=0; row<mRowChances.length; row++)
424
      {
425
      if( rowFloat<=mRowChances[row] ) return row;
426
      }
427

    
428
    return 0;
429
    }
430

    
431
///////////////////////////////////////////////////////////////////////////////////////////////////
432
// remember about the double cover or unit quaternions!
433

    
434
  private int mulQuat(int q1, int q2)
435
    {
436
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
437

    
438
    float rX = result.get0();
439
    float rY = result.get1();
440
    float rZ = result.get2();
441
    float rW = result.get3();
442

    
443
    final float MAX_ERROR = 0.1f;
444
    float dX,dY,dZ,dW;
445

    
446
    for(int i=0; i<QUATS.length; i++)
447
      {
448
      dX = QUATS[i].get0() - rX;
449
      dY = QUATS[i].get1() - rY;
450
      dZ = QUATS[i].get2() - rZ;
451
      dW = QUATS[i].get3() - rW;
452

    
453
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
454
          dY<MAX_ERROR && dY>-MAX_ERROR &&
455
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
456
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
457

    
458
      dX = QUATS[i].get0() + rX;
459
      dY = QUATS[i].get1() + rY;
460
      dZ = QUATS[i].get2() + rZ;
461
      dW = QUATS[i].get3() + rW;
462

    
463
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
464
          dY<MAX_ERROR && dY>-MAX_ERROR &&
465
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
466
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
467
      }
468

    
469
    return -1;
470
    }
471

    
472
///////////////////////////////////////////////////////////////////////////////////////////////////
473
// The Rex is solved if and only if:
474
//
475
// TODO
476

    
477
  public boolean isSolved()
478
    {
479
    int q = CUBITS[0].mQuatIndex;
480

    
481
    for(int i=1; i<42; i++)
482
      {
483
      if( CUBITS[i].mQuatIndex != q) return false;
484
      }
485

    
486
    return true;
487
    }
488

    
489
///////////////////////////////////////////////////////////////////////////////////////////////////
490
// only needed for solvers - there are no Rex solvers ATM)
491

    
492
  public String retObjectString()
493
    {
494
    return "";
495
    }
496

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

    
499
  public int getObjectName(int numLayers)
500
    {
501
    return R.string.rex3;
502
    }
503

    
504
///////////////////////////////////////////////////////////////////////////////////////////////////
505

    
506
  public int getInventor(int numLayers)
507
    {
508
    return R.string.rex3_inventor;
509
    }
510

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

    
513
  public int getComplexity(int numLayers)
514
    {
515
    return 3;
516
    }
517
}
(25-25/26)