Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyIvy.java @ a64e07d0

1 49cd8581 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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 6fd4a72c Leszek Koltunski
import org.distorted.main.R;
34 49cd8581 Leszek Koltunski
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 TwistyIvy extends TwistyObject
43
{
44 18a5f95f Leszek Koltunski
  private static final int FACES_PER_CUBIT =6;
45 49cd8581 Leszek Koltunski
46
  // the four rotation axis of a RubikIvy. 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 323b217c Leszek Koltunski
           COLOR_RED   , COLOR_ORANGE
60 49cd8581 Leszek Koltunski
         };
61
62
  // All legal rotation quats of a RubikIvy
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 18a5f95f Leszek Koltunski
  private static final int[][] mFaceMap =
81 49cd8581 Leszek Koltunski
         {
82 18a5f95f Leszek Koltunski
           {  4, 2, 0, 12,12,12 },
83
           {  5, 2, 1, 12,12,12 },
84
           {  4, 3, 1, 12,12,12 },
85
           {  5, 3, 0, 12,12,12 },
86
87
           {  6, 12,12,12,12,12 },
88
           {  7, 12,12,12,12,12 },
89
           {  8, 12,12,12,12,12 },
90
           {  9, 12,12,12,12,12 },
91
           { 10, 12,12,12,12,12 },
92
           { 11, 12,12,12,12,12 },
93 49cd8581 Leszek Koltunski
         };
94
95
  private static MeshBase mCornerMesh, mFaceMesh;
96
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98
99
  TwistyIvy(int size, Static4D quat, DistortedTexture texture,
100
            MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
101
    {
102
    super(size, size, 60, quat, texture, mesh, effects, moves, ObjectList.IVY, res, scrWidth);
103
    }
104
105
///////////////////////////////////////////////////////////////////////////////////////////////////
106
107
  float getScreenRatio()
108
    {
109
    return 1.0f;
110
    }
111
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113
114
  Static4D[] getQuats()
115
    {
116
    return QUATS;
117
    }
118
119
///////////////////////////////////////////////////////////////////////////////////////////////////
120
121
  int getNumFaces()
122
    {
123
    return FACE_COLORS.length;
124
    }
125
126
///////////////////////////////////////////////////////////////////////////////////////////////////
127
128
  boolean shouldResetTextureMaps()
129
    {
130
    return false;
131
    }
132
133
///////////////////////////////////////////////////////////////////////////////////////////////////
134
135 a64e07d0 Leszek Koltunski
  int getNumStickerTypes(int numLayers)
136 49cd8581 Leszek Koltunski
    {
137
    return 2;
138
    }
139
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141
142
  float[] getCuts(int numLayers)
143
    {
144
    float[] cuts = new float[1];
145
    cuts[0] = 0.0f;
146
147
    return cuts;
148
    }
149
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151
152
  int getNumCubitFaces()
153
    {
154
    return FACES_PER_CUBIT;
155
    }
156
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158
159
  Static3D[] getCubitPositions(int numLayers)
160
    {
161
    final float DIST_CORNER = (numLayers-1)*0.50f;
162
    final float DIST_CENTER = (numLayers-1)*0.50f;
163
164
    final Static3D[] CENTERS = new Static3D[10];
165
166
    CENTERS[0] = new Static3D( DIST_CORNER, DIST_CORNER, DIST_CORNER );
167
    CENTERS[1] = new Static3D(-DIST_CORNER, DIST_CORNER,-DIST_CORNER );
168
    CENTERS[2] = new Static3D(-DIST_CORNER,-DIST_CORNER, DIST_CORNER );
169
    CENTERS[3] = new Static3D( DIST_CORNER,-DIST_CORNER,-DIST_CORNER );
170
    CENTERS[4] = new Static3D( DIST_CENTER,           0,           0 );
171
    CENTERS[5] = new Static3D(-DIST_CENTER,           0,           0 );
172
    CENTERS[6] = new Static3D(           0, DIST_CENTER,           0 );
173
    CENTERS[7] = new Static3D(           0,-DIST_CENTER,           0 );
174
    CENTERS[8] = new Static3D(           0,           0, DIST_CENTER );
175
    CENTERS[9] = new Static3D(           0,           0,-DIST_CENTER );
176
177
    return CENTERS;
178
    }
179
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181
182
  private int getQuat(int cubit)
183
    {
184
    switch(cubit)
185
      {
186
      case  0: return 0;
187
      case  1: return 2;
188
      case  2: return 3;
189
      case  3: return 1;
190
191
      case  4: return 8;
192
      case  5: return 11;
193
      case  6: return 10;
194
      case  7: return 9;
195
      case  8: return 0;
196
      case  9: return 2;
197
      }
198
199
    return 0;
200
    }
201
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203
204 a64e07d0 Leszek Koltunski
  MeshBase createCubitMesh(int cubit, int numLayers)
205 49cd8581 Leszek Koltunski
    {
206
    MeshBase mesh;
207
208
    if( cubit<4 )
209
      {
210
      if( mCornerMesh==null ) mCornerMesh = FactoryCubit.getInstance().createIvyCornerMesh();
211
      mesh = mCornerMesh.copy(true);
212
      }
213
    else
214
      {
215
      if( mFaceMesh==null ) mFaceMesh = FactoryCubit.getInstance().createIvyFaceMesh();
216
      mesh = mFaceMesh.copy(true);
217
      }
218
219
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( QUATS[getQuat(cubit)], new Static3D(0,0,0) );
220
    mesh.apply(quat,0xffffffff,0);
221
222
    return mesh;
223
    }
224
225
///////////////////////////////////////////////////////////////////////////////////////////////////
226
227
  int getFaceColor(int cubit, int cubitface, int numLayers)
228
    {
229 18a5f95f Leszek Koltunski
    return mFaceMap[cubit][cubitface];
230 49cd8581 Leszek Koltunski
    }
231
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233
234
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
235
    {
236
    int COLORS = FACE_COLORS.length;
237
    FactorySticker factory = FactorySticker.getInstance();
238 9e5b990e Leszek Koltunski
    float S = 0.08f;
239 886d1ebb Leszek Koltunski
    float R = 0.12f;
240 49cd8581 Leszek Koltunski
241
    if( face<COLORS )
242
      {
243 9e5b990e Leszek Koltunski
      factory.drawIvyCornerSticker(canvas, paint, left, top, FACE_COLORS[face%COLORS], S, R);
244 49cd8581 Leszek Koltunski
      }
245
    else
246
      {
247 9e5b990e Leszek Koltunski
      factory.drawIvyCenterSticker(canvas, paint, left, top, FACE_COLORS[face%COLORS], S, R);
248 49cd8581 Leszek Koltunski
      }
249
    }
250
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252
253
  float returnMultiplier()
254
    {
255
    return 2.0f;
256
    }
257
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259
260 a64e07d0 Leszek Koltunski
  float[] getRowChances(int numLayers)
261 49cd8581 Leszek Koltunski
    {
262
    float[] chances = new float[2];
263
    chances[0] = 0.5f;
264
    chances[1] = 1.0f;
265
266
    return chances;
267
    }
268
269
///////////////////////////////////////////////////////////////////////////////////////////////////
270
// PUBLIC API
271
272
  public Static3D[] getRotationAxis()
273
    {
274
    return ROT_AXIS;
275
    }
276
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278
279
  public int getBasicAngle()
280
    {
281
    return 3;
282
    }
283
284
///////////////////////////////////////////////////////////////////////////////////////////////////
285
286
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
287
    {
288
    int numAxis = ROTATION_AXIS.length;
289
290
    if( oldRotAxis == START_AXIS )
291
      {
292
      return rnd.nextInt(numAxis);
293
      }
294
    else
295
      {
296
      int newVector = rnd.nextInt(numAxis-1);
297
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
298
      }
299
    }
300
301
///////////////////////////////////////////////////////////////////////////////////////////////////
302
303
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
304
    {
305
    float rowFloat = rnd.nextFloat();
306
307
    for(int row=0; row<mRowChances.length; row++)
308
      {
309
      if( rowFloat<=mRowChances[row] ) return row;
310
      }
311
312
    return 0;
313
    }
314
315
///////////////////////////////////////////////////////////////////////////////////////////////////
316
// remember about the double cover or unit quaternions!
317
318
  private int mulQuat(int q1, int q2)
319
    {
320
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
321
322
    float rX = result.get0();
323
    float rY = result.get1();
324
    float rZ = result.get2();
325
    float rW = result.get3();
326
327
    final float MAX_ERROR = 0.1f;
328
    float dX,dY,dZ,dW;
329
330
    for(int i=0; i<QUATS.length; i++)
331
      {
332
      dX = QUATS[i].get0() - rX;
333
      dY = QUATS[i].get1() - rY;
334
      dZ = QUATS[i].get2() - rZ;
335
      dW = QUATS[i].get3() - rW;
336
337
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
338
          dY<MAX_ERROR && dY>-MAX_ERROR &&
339
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
340
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
341
342
      dX = QUATS[i].get0() + rX;
343
      dY = QUATS[i].get1() + rY;
344
      dZ = QUATS[i].get2() + rZ;
345
      dW = QUATS[i].get3() + rW;
346
347
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
348
          dY<MAX_ERROR && dY>-MAX_ERROR &&
349
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
350
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
351
      }
352
353
    return -1;
354
    }
355
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357
// The Ivy is solved if and only if:
358
//
359
// 1) all 4 of its corner cubits are rotated with the same quat
360
// 2) all its face cubits are rotated with the same quat like the corner ones,
361
//    and optionally they also might be upside down.
362
//
363
// i.e.
364
// cubits [4] and [5] - might be extra QUAT[1]
365
// cubits [6] and [7] - might be extra QUAT[2]
366
// cubits [8] and [9] - might be extra QUAT[3]
367
368
  public boolean isSolved()
369
    {
370
    int q1,q = CUBITS[0].mQuatIndex;
371
372
    if( CUBITS[1].mQuatIndex == q &&
373
        CUBITS[2].mQuatIndex == q &&
374
        CUBITS[3].mQuatIndex == q  )
375
      {
376
      q1 = mulQuat(q,1);
377
      if( CUBITS[4].mQuatIndex != q && CUBITS[4].mQuatIndex != q1 ) return false;
378
      if( CUBITS[5].mQuatIndex != q && CUBITS[5].mQuatIndex != q1 ) return false;
379
380
      q1 = mulQuat(q,2);
381
      if( CUBITS[6].mQuatIndex != q && CUBITS[6].mQuatIndex != q1 ) return false;
382
      if( CUBITS[7].mQuatIndex != q && CUBITS[7].mQuatIndex != q1 ) return false;
383
384
      q1 = mulQuat(q,3);
385
      if( CUBITS[8].mQuatIndex != q && CUBITS[8].mQuatIndex != q1 ) return false;
386
      if( CUBITS[9].mQuatIndex != q && CUBITS[9].mQuatIndex != q1 ) return false;
387
388
      return true;
389
      }
390
391
    return false;
392
    }
393
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395
// only needed for solvers - there are no Ivy solvers ATM)
396
397
  public String retObjectString()
398
    {
399
    return "";
400
    }
401 6fd4a72c Leszek Koltunski
402
///////////////////////////////////////////////////////////////////////////////////////////////////
403
404
  public int getObjectName(int numLayers)
405
    {
406
    return R.string.ivy2;
407
    }
408
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410
411
  public int getInventor(int numLayers)
412
    {
413
    return R.string.ivy2_inventor;
414
    }
415
416
///////////////////////////////////////////////////////////////////////////////////////////////////
417
418
  public int getComplexity(int numLayers)
419
    {
420
    return 1;
421
    }
422 49cd8581 Leszek Koltunski
}