Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyRedi.java @ 3f3ff476

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.RubikSurfaceView;
34

    
35
import java.util.Random;
36

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

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

    
41
public class TwistyRedi extends TwistyObject
42
{
43
  private static final int FACES_PER_CUBIT =6;
44

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

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

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

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

    
79
  private static final float DIST_CORNER = 1.0f;
80
  private static final float DIST_EDGE   = 1.5f;
81

    
82
  // centers of the 8 corners + 12 edges ( i.e. of the all 20 cubits)
83
  private static final Static3D[] CENTERS = new Static3D[]
84
         {
85
           new Static3D( DIST_CORNER, DIST_CORNER, DIST_CORNER ),
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

    
94
           new Static3D(      0.0f, DIST_EDGE, DIST_EDGE ),
95
           new Static3D( DIST_EDGE,      0.0f, DIST_EDGE ),
96
           new Static3D(      0.0f,-DIST_EDGE, DIST_EDGE ),
97
           new Static3D(-DIST_EDGE,      0.0f, DIST_EDGE ),
98
           new Static3D( DIST_EDGE, DIST_EDGE,      0.0f ),
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(      0.0f, DIST_EDGE,-DIST_EDGE ),
103
           new Static3D( DIST_EDGE,      0.0f,-DIST_EDGE ),
104
           new Static3D(      0.0f,-DIST_EDGE,-DIST_EDGE ),
105
           new Static3D(-DIST_EDGE,      0.0f,-DIST_EDGE )
106
         };
107

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

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

    
136
  private static MeshBase mCornerMesh, mEdgeMesh;
137

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

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

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

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

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

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

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

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

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

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

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

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

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

    
183
  float getBasicStep()
184
    {
185
    return SQ3;
186
    }
187

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

    
190
  int getNumCubitFaces()
191
    {
192
    return FACES_PER_CUBIT;
193
    }
194

    
195
///////////////////////////////////////////////////////////////////////////////////////////////////
196

    
197
  Static3D[] getCubitPositions(int size)
198
    {
199
    return CENTERS;
200
    }
201

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
  private Static4D getQuat(int cubit)
205
    {
206
    switch(cubit)
207
      {
208
      case  0: return QUATS[0];                          //  unit quat
209
      case  1: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
210
      case  2: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
211
      case  3: return QUATS[1];                          // 180 along X
212
      case  4: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
213
      case  5: return QUATS[2];                          // 180 along Y
214
      case  6: return QUATS[3];                          // 180 along Z
215
      case  7: return new Static4D(SQ2/2,0,-SQ2/2,0);    // 180 along (SQ2/2,0,-SQ2/2)
216

    
217
      case  8: return QUATS[0];
218
      case  9: return QUATS[5];
219
      case 10: return QUATS[3];
220
      case 11: return QUATS[11];
221
      case 12: return QUATS[4];
222
      case 13: return QUATS[7];
223
      case 14: return QUATS[9];
224
      case 15: return QUATS[10];
225
      case 16: return QUATS[2];
226
      case 17: return QUATS[8];
227
      case 18: return QUATS[1];
228
      case 19: return QUATS[6];
229
      }
230

    
231
    return null;
232
    }
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235

    
236
  MeshBase createCubitMesh(int cubit)
237
    {
238
    MeshBase mesh;
239

    
240
    if( cubit<8 )
241
      {
242
      if( mCornerMesh==null ) mCornerMesh = CubitFactory.getInstance().createRediCornerMesh();
243
      mesh = mCornerMesh.copy(true);
244
      }
245
    else
246
      {
247
      if( mEdgeMesh==null ) mEdgeMesh = CubitFactory.getInstance().createRediEdgeMesh();
248
      mesh = mEdgeMesh.copy(true);
249
      }
250

    
251
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit), new Static3D(0,0,0) );
252
    mesh.apply(quat,0xffffffff,0);
253

    
254
    return mesh;
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

    
259
  int getFaceColor(int cubit, int cubitface, int size)
260
    {
261
    return mFaceMap[cubit][cubitface];
262
    }
263

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

    
266
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left)
267
    {
268
    int COLORS = FACE_COLORS.length;
269

    
270
    if( face<COLORS )
271
      {
272
      float F =  0.5f;
273
      float R = 0.10f;
274
      float S = 0.10f;
275
      float[] vertices = { -F,-F, +F,-F, +F,+F, -F,+F};
276

    
277
      drawRoundedPolygon(canvas, paint, left, vertices, S, FACE_COLORS[face], R);
278
      }
279
    else
280
      {
281
      float F = 0.25f;
282
      float R = 0.05f;
283
      float S = 0.05f;
284
      float[] vertices = { -F,+F, -F,-F, 0, -2*F, +F,-F, +F,+F };
285

    
286
      drawRoundedPolygon(canvas, paint, left, vertices, S, FACE_COLORS[face-COLORS], R);
287
      }
288
    }
289

    
290
///////////////////////////////////////////////////////////////////////////////////////////////////
291

    
292
  float returnMultiplier()
293
    {
294
    return 2.0f;
295
    }
296

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

    
299
  float[] getRowChances()
300
    {
301
    float[] chances = new float[3];
302

    
303
    chances[0] = 0.5f;
304
    chances[1] = 0.5f;
305
    chances[2] = 1.0f;
306

    
307
    return chances;
308
    }
309

    
310
///////////////////////////////////////////////////////////////////////////////////////////////////
311
// PUBLIC API
312

    
313
  public Static3D[] getRotationAxis()
314
    {
315
    return ROT_AXIS;
316
    }
317

    
318
///////////////////////////////////////////////////////////////////////////////////////////////////
319

    
320
  public int getBasicAngle()
321
    {
322
    return 3;
323
    }
324

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

    
327
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
328
    {
329
    int numAxis = ROTATION_AXIS.length;
330

    
331
    if( oldRotAxis == START_AXIS )
332
      {
333
      return rnd.nextInt(numAxis);
334
      }
335
    else
336
      {
337
      int newVector = rnd.nextInt(numAxis-1);
338
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
339
      }
340
    }
341

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

    
344
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
345
    {
346
    return (oldRotAxis==START_AXIS) ? (rnd.nextFloat()<=0.5f ? 0:2) : (oldRotAxis+newRotAxis==3 ? 2-oldRow : oldRow);
347
    }
348

    
349
///////////////////////////////////////////////////////////////////////////////////////////////////
350
// remember about the double cover or unit quaternions!
351

    
352
  private int mulQuat(int q1, int q2)
353
    {
354
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
355

    
356
    float rX = result.get0();
357
    float rY = result.get1();
358
    float rZ = result.get2();
359
    float rW = result.get3();
360

    
361
    final float MAX_ERROR = 0.1f;
362
    float dX,dY,dZ,dW;
363

    
364
    for(int i=0; i<QUATS.length; i++)
365
      {
366
      dX = QUATS[i].get0() - rX;
367
      dY = QUATS[i].get1() - rY;
368
      dZ = QUATS[i].get2() - rZ;
369
      dW = QUATS[i].get3() - rW;
370

    
371
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
372
          dY<MAX_ERROR && dY>-MAX_ERROR &&
373
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
374
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
375

    
376
      dX = QUATS[i].get0() + rX;
377
      dY = QUATS[i].get1() + rY;
378
      dZ = QUATS[i].get2() + rZ;
379
      dW = QUATS[i].get3() + rW;
380

    
381
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
382
          dY<MAX_ERROR && dY>-MAX_ERROR &&
383
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
384
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
385
      }
386

    
387
    return -1;
388
    }
389

    
390
///////////////////////////////////////////////////////////////////////////////////////////////////
391
// The Redi is solved if and only if:
392
//
393
// ??
394

    
395
  public boolean isSolved()
396
    {
397
    int q = CUBITS[0].mQuatIndex;
398

    
399
    return ( CUBITS[ 1].mQuatIndex == q &&
400
             CUBITS[ 2].mQuatIndex == q &&
401
             CUBITS[ 3].mQuatIndex == q &&
402
             CUBITS[ 4].mQuatIndex == q &&
403
             CUBITS[ 5].mQuatIndex == q &&
404
             CUBITS[ 6].mQuatIndex == q &&
405
             CUBITS[ 7].mQuatIndex == q &&
406
             CUBITS[ 8].mQuatIndex == q &&
407
             CUBITS[ 9].mQuatIndex == q &&
408
             CUBITS[10].mQuatIndex == q &&
409
             CUBITS[11].mQuatIndex == q &&
410
             CUBITS[12].mQuatIndex == q &&
411
             CUBITS[13].mQuatIndex == q &&
412
             CUBITS[14].mQuatIndex == q &&
413
             CUBITS[15].mQuatIndex == q &&
414
             CUBITS[16].mQuatIndex == q &&
415
             CUBITS[17].mQuatIndex == q &&
416
             CUBITS[18].mQuatIndex == q &&
417
             CUBITS[19].mQuatIndex == q  );
418
    }
419

    
420
///////////////////////////////////////////////////////////////////////////////////////////////////
421
// only needed for solvers - there are no Redi solvers ATM)
422

    
423
  public String retObjectString()
424
    {
425
    return "";
426
    }
427
}
(20-20/21)