Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyRedi.java @ 323b217c

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 TwistyRedi extends TwistyObject
43
{
44
  private static final int FACES_PER_CUBIT =6;
45

    
46
  // the four rotation axis of a RubikRedi. 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_ORANGE
60
         };
61

    
62
  // All legal rotation quats of a RubikRedi
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 float DIST_CORNER = 1.0f;
81
  private static final float DIST_EDGE   = 1.5f;
82

    
83
  // centers of the 8 corners + 12 edges ( i.e. of the all 20 cubits)
84
  private static final Static3D[] CENTERS = new Static3D[]
85
         {
86
           new Static3D( DIST_CORNER, DIST_CORNER, DIST_CORNER ),
87
           new Static3D( DIST_CORNER, DIST_CORNER,-DIST_CORNER ),
88
           new Static3D( DIST_CORNER,-DIST_CORNER, DIST_CORNER ),
89
           new Static3D( DIST_CORNER,-DIST_CORNER,-DIST_CORNER ),
90
           new Static3D(-DIST_CORNER, DIST_CORNER, DIST_CORNER ),
91
           new Static3D(-DIST_CORNER, DIST_CORNER,-DIST_CORNER ),
92
           new Static3D(-DIST_CORNER,-DIST_CORNER, DIST_CORNER ),
93
           new Static3D(-DIST_CORNER,-DIST_CORNER,-DIST_CORNER ),
94

    
95
           new Static3D(      0.0f, DIST_EDGE, DIST_EDGE ),
96
           new Static3D( DIST_EDGE,      0.0f, DIST_EDGE ),
97
           new Static3D(      0.0f,-DIST_EDGE, DIST_EDGE ),
98
           new Static3D(-DIST_EDGE,      0.0f, DIST_EDGE ),
99
           new Static3D( DIST_EDGE, DIST_EDGE,      0.0f ),
100
           new Static3D( DIST_EDGE,-DIST_EDGE,      0.0f ),
101
           new Static3D(-DIST_EDGE,-DIST_EDGE,      0.0f ),
102
           new Static3D(-DIST_EDGE, DIST_EDGE,      0.0f ),
103
           new Static3D(      0.0f, DIST_EDGE,-DIST_EDGE ),
104
           new Static3D( DIST_EDGE,      0.0f,-DIST_EDGE ),
105
           new Static3D(      0.0f,-DIST_EDGE,-DIST_EDGE ),
106
           new Static3D(-DIST_EDGE,      0.0f,-DIST_EDGE )
107
         };
108

    
109
  // Colors of the faces of cubits.
110
  // YELLOW 0 WHITE 1 BLUE 2 GREEN 3 RED 4  BROWN 5
111
  // YELLOW 6 WHITE 7 BLUE 8 GREEN 9 RED 10 BROWN 11
112
  private static final int[][] mFaceMap = new int[][]
113
         {
114
           {  4, 2, 0,12,12,12 },
115
           {  2, 5, 0,12,12,12 },
116
           {  3, 4, 0,12,12,12 },
117
           {  5, 3, 0,12,12,12 },
118
           {  1, 2, 4,12,12,12 },
119
           {  5, 2, 1,12,12,12 },
120
           {  4, 3, 1,12,12,12 },
121
           {  1, 3, 5,12,12,12 },
122

    
123
           { 10, 8,12,12,12,12 },
124
           {  6,10,12,12,12,12 },
125
           { 10, 9,12,12,12,12 },
126
           {  7,10,12,12,12,12 },
127
           {  8, 6,12,12,12,12 },
128
           {  9, 6,12,12,12,12 },
129
           {  9, 7,12,12,12,12 },
130
           {  8, 7,12,12,12,12 },
131
           { 11, 8,12,12,12,12 },
132
           {  6,11,12,12,12,12 },
133
           { 11, 9,12,12,12,12 },
134
           {  7,11,12,12,12,12 },
135
         };
136

    
137
  private static MeshBase mCornerMesh, mEdgeMesh;
138

    
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140

    
141
  TwistyRedi(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
142
             DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
143
    {
144
    super(size, size, 60, quat, texture, mesh, effects, moves, ObjectList.REDI, res, scrWidth);
145
    }
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148

    
149
  float getScreenRatio()
150
    {
151
    return 0.50f;
152
    }
153

    
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155

    
156
  Static4D[] getQuats()
157
    {
158
    return QUATS;
159
    }
160

    
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

    
163
  int getNumFaces()
164
    {
165
    return FACE_COLORS.length;
166
    }
167

    
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169

    
170
  boolean shouldResetTextureMaps()
171
    {
172
    return false;
173
    }
174

    
175
///////////////////////////////////////////////////////////////////////////////////////////////////
176

    
177
  int getNumStickerTypes()
178
    {
179
    return 2;
180
    }
181

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

    
184
  float[] getCuts(int size)
185
    {
186
    float[] cuts = new float[2];
187

    
188
    cuts[0] = -SQ3/3 -0.05f;
189
    cuts[1] = +SQ3/3 +0.05f;
190

    
191
    return cuts;
192
    }
193

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

    
196
  int getNumCubitFaces()
197
    {
198
    return FACES_PER_CUBIT;
199
    }
200

    
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202

    
203
  Static3D[] getCubitPositions(int size)
204
    {
205
    return CENTERS;
206
    }
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

    
210
  private Static4D getQuat(int cubit)
211
    {
212
    switch(cubit)
213
      {
214
      case  0: return QUATS[0];                          //  unit quat
215
      case  1: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
216
      case  2: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
217
      case  3: return QUATS[1];                          // 180 along X
218
      case  4: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
219
      case  5: return QUATS[2];                          // 180 along Y
220
      case  6: return QUATS[3];                          // 180 along Z
221
      case  7: return new Static4D(SQ2/2,0,-SQ2/2,0);    // 180 along (SQ2/2,0,-SQ2/2)
222

    
223
      case  8: return QUATS[0];
224
      case  9: return QUATS[5];
225
      case 10: return QUATS[3];
226
      case 11: return QUATS[11];
227
      case 12: return QUATS[4];
228
      case 13: return QUATS[7];
229
      case 14: return QUATS[9];
230
      case 15: return QUATS[10];
231
      case 16: return QUATS[2];
232
      case 17: return QUATS[8];
233
      case 18: return QUATS[1];
234
      case 19: return QUATS[6];
235
      }
236

    
237
    return null;
238
    }
239

    
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241

    
242
  MeshBase createCubitMesh(int cubit)
243
    {
244
    MeshBase mesh;
245

    
246
    if( cubit<8 )
247
      {
248
      if( mCornerMesh==null ) mCornerMesh = FactoryCubit.getInstance().createRediCornerMesh();
249
      mesh = mCornerMesh.copy(true);
250
      }
251
    else
252
      {
253
      if( mEdgeMesh==null ) mEdgeMesh = FactoryCubit.getInstance().createRediEdgeMesh();
254
      mesh = mEdgeMesh.copy(true);
255
      }
256

    
257
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit), new Static3D(0,0,0) );
258
    mesh.apply(quat,0xffffffff,0);
259

    
260
    return mesh;
261
    }
262

    
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264

    
265
  int getFaceColor(int cubit, int cubitface, int size)
266
    {
267
    return mFaceMap[cubit][cubitface];
268
    }
269

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

    
272
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
273
    {
274
    int COLORS = FACE_COLORS.length;
275
    FactorySticker factory = FactorySticker.getInstance();
276

    
277
    if( face<COLORS )
278
      {
279
      float F =  0.5f;
280
      float R = 0.10f;
281
      float S = 0.10f;
282
      float[] vertices = { -F,-F, +F,-F, +F,+F, -F,+F};
283

    
284
      factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face], R);
285
      }
286
    else
287
      {
288
      float F = 0.25f;
289
      float R = 0.05f;
290
      float S = 0.05f;
291
      float[] vertices = { -F,+F, -F,-F, 0, -2*F, +F,-F, +F,+F };
292

    
293
      factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face-COLORS], R);
294
      }
295
    }
296

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

    
299
  float returnMultiplier()
300
    {
301
    return 2.0f;
302
    }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

    
306
  float[] getRowChances()
307
    {
308
    float[] chances = new float[3];
309

    
310
    chances[0] = 0.5f;
311
    chances[1] = 0.5f;
312
    chances[2] = 1.0f;
313

    
314
    return chances;
315
    }
316

    
317
///////////////////////////////////////////////////////////////////////////////////////////////////
318
// PUBLIC API
319

    
320
  public Static3D[] getRotationAxis()
321
    {
322
    return ROT_AXIS;
323
    }
324

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

    
327
  public int getBasicAngle()
328
    {
329
    return 3;
330
    }
331

    
332
///////////////////////////////////////////////////////////////////////////////////////////////////
333

    
334
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
335
    {
336
    int numAxis = ROTATION_AXIS.length;
337

    
338
    if( oldRotAxis == START_AXIS )
339
      {
340
      return rnd.nextInt(numAxis);
341
      }
342
    else
343
      {
344
      int newVector = rnd.nextInt(numAxis-1);
345
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
346
      }
347
    }
348

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

    
351
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
352
    {
353
    return (oldRotAxis==START_AXIS) ? (rnd.nextFloat()<=0.5f ? 0:2) : (oldRotAxis+newRotAxis==3 ? 2-oldRow : oldRow);
354
    }
355

    
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357
// remember about the double cover or unit quaternions!
358

    
359
  private int mulQuat(int q1, int q2)
360
    {
361
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
362

    
363
    float rX = result.get0();
364
    float rY = result.get1();
365
    float rZ = result.get2();
366
    float rW = result.get3();
367

    
368
    final float MAX_ERROR = 0.1f;
369
    float dX,dY,dZ,dW;
370

    
371
    for(int i=0; i<QUATS.length; i++)
372
      {
373
      dX = QUATS[i].get0() - rX;
374
      dY = QUATS[i].get1() - rY;
375
      dZ = QUATS[i].get2() - rZ;
376
      dW = QUATS[i].get3() - rW;
377

    
378
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
379
          dY<MAX_ERROR && dY>-MAX_ERROR &&
380
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
381
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
382

    
383
      dX = QUATS[i].get0() + rX;
384
      dY = QUATS[i].get1() + rY;
385
      dZ = QUATS[i].get2() + rZ;
386
      dW = QUATS[i].get3() + rW;
387

    
388
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
389
          dY<MAX_ERROR && dY>-MAX_ERROR &&
390
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
391
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
392
      }
393

    
394
    return -1;
395
    }
396

    
397
///////////////////////////////////////////////////////////////////////////////////////////////////
398
// The Redi is solved if and only if:
399
//
400
// ??
401

    
402
  public boolean isSolved()
403
    {
404
    int q = CUBITS[0].mQuatIndex;
405

    
406
    return ( CUBITS[ 1].mQuatIndex == q &&
407
             CUBITS[ 2].mQuatIndex == q &&
408
             CUBITS[ 3].mQuatIndex == q &&
409
             CUBITS[ 4].mQuatIndex == q &&
410
             CUBITS[ 5].mQuatIndex == q &&
411
             CUBITS[ 6].mQuatIndex == q &&
412
             CUBITS[ 7].mQuatIndex == q &&
413
             CUBITS[ 8].mQuatIndex == q &&
414
             CUBITS[ 9].mQuatIndex == q &&
415
             CUBITS[10].mQuatIndex == q &&
416
             CUBITS[11].mQuatIndex == q &&
417
             CUBITS[12].mQuatIndex == q &&
418
             CUBITS[13].mQuatIndex == q &&
419
             CUBITS[14].mQuatIndex == q &&
420
             CUBITS[15].mQuatIndex == q &&
421
             CUBITS[16].mQuatIndex == q &&
422
             CUBITS[17].mQuatIndex == q &&
423
             CUBITS[18].mQuatIndex == q &&
424
             CUBITS[19].mQuatIndex == q  );
425
    }
426

    
427
///////////////////////////////////////////////////////////////////////////////////////////////////
428
// only needed for solvers - there are no Redi solvers ATM)
429

    
430
  public String retObjectString()
431
    {
432
    return "";
433
    }
434

    
435
///////////////////////////////////////////////////////////////////////////////////////////////////
436

    
437
  public int getObjectName(int numLayers)
438
    {
439
    return R.string.redi2;
440
    }
441

    
442
///////////////////////////////////////////////////////////////////////////////////////////////////
443

    
444
  public int getInventor(int numLayers)
445
    {
446
    return R.string.redi2_inventor;
447
    }
448

    
449
///////////////////////////////////////////////////////////////////////////////////////////////////
450

    
451
  public int getComplexity(int numLayers)
452
    {
453
    return 4;
454
    }
455
}
(26-26/28)