Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyDiamond.java @ 5043d5d0

1 ece1b58d 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 ad6f6f03 Leszek Koltunski
import org.distorted.main.RubikSurfaceView;
35 ece1b58d Leszek Koltunski
36
import java.util.Random;
37
38
///////////////////////////////////////////////////////////////////////////////////////////////////
39
40 9c2f0c91 Leszek Koltunski
public class TwistyDiamond extends TwistyObject
41 ece1b58d Leszek Koltunski
{
42
  private static final int FACES_PER_CUBIT =8;
43
44
  // the four rotation axis of a Diamond. Must be normalized.
45
  static final Static3D[] ROT_AXIS = new Static3D[]
46
         {
47
           new Static3D(+SQ6/3,+SQ3/3,     0),
48
           new Static3D(-SQ6/3,+SQ3/3,     0),
49 cc99cf91 Leszek Koltunski
           new Static3D(     0,-SQ3/3,-SQ6/3),
50
           new Static3D(     0,-SQ3/3,+SQ6/3)
51 ece1b58d Leszek Koltunski
         };
52
53
  private static final int[] FACE_COLORS = new int[]
54
         {
55 33b4138b Leszek Koltunski
           COLOR_GREY  , COLOR_VIOLET,
56 5581ba2b Leszek Koltunski
           COLOR_YELLOW, COLOR_WHITE ,
57 33b4138b Leszek Koltunski
           COLOR_BLUE  , COLOR_RED   ,
58
           COLOR_ORANGE, COLOR_GREEN
59 ece1b58d Leszek Koltunski
         };
60
61 ab0c28f0 Leszek Koltunski
  // All legal rotation quats of a Diamond: unit + three 180 deg turns + 8 generators
62 ece1b58d Leszek Koltunski
  private static final Static4D[] QUATS = new Static4D[]
63
         {
64
           new Static4D(  0.0f,  0.0f,   0.0f,  1.0f ),
65
           new Static4D(  0.0f,  1.0f,   0.0f,  0.0f ),
66 ab0c28f0 Leszek Koltunski
           new Static4D(+SQ2/2,  0.0f, -SQ2/2,  0.0f ),
67
           new Static4D(-SQ2/2,  0.0f, -SQ2/2,  0.0f ),
68
69 ece1b58d Leszek Koltunski
           new Static4D(+SQ2/2,  0.5f,   0.0f,  0.5f ),
70
           new Static4D(-SQ2/2,  0.5f,   0.0f,  0.5f ),
71
           new Static4D(  0.0f,  0.5f, +SQ2/2,  0.5f ),
72
           new Static4D(  0.0f,  0.5f, -SQ2/2,  0.5f ),
73
           new Static4D(+SQ2/2,  0.5f,   0.0f, -0.5f ),
74
           new Static4D(-SQ2/2,  0.5f,   0.0f, -0.5f ),
75
           new Static4D(  0.0f,  0.5f, +SQ2/2, -0.5f ),
76 ab0c28f0 Leszek Koltunski
           new Static4D(  0.0f,  0.5f, -SQ2/2, -0.5f )
77 ece1b58d Leszek Koltunski
         };
78
79
  private static final float DIST = 0.50f;
80
81
  // centers of the 6 octahedrons + 8 tetrahedrons ( i.e. of the all 14 cubits)
82 e6cf7283 Leszek Koltunski
  private static final float[][] CENTERS = new float[][]
83 ece1b58d Leszek Koltunski
         {
84 e6cf7283 Leszek Koltunski
             { DIST,          0, DIST },
85
             { DIST,          0,-DIST },
86
             {-DIST,          0,-DIST },
87
             {-DIST,          0, DIST },
88
             {    0, DIST*SQ2  ,    0 },
89
             {    0,-DIST*SQ2  ,    0 },
90
91
             {    0, DIST*SQ2/2, DIST },
92
             { DIST, DIST*SQ2/2,    0 },
93
             {    0, DIST*SQ2/2,-DIST },
94
             {-DIST, DIST*SQ2/2,    0 },
95
             {    0,-DIST*SQ2/2, DIST },
96
             { DIST,-DIST*SQ2/2,    0 },
97
             {    0,-DIST*SQ2/2,-DIST },
98
             {-DIST,-DIST*SQ2/2,    0 }
99 ece1b58d Leszek Koltunski
         };
100
101
  // Colors of the faces of cubits. Each cubit has 8 faces
102
  private static final int[][] mFaceMap = new int[][]
103
         {
104
           { 6,1,8,8, 2,5,8,8 },
105
           { 8,1,3,8, 8,5,7,8 },
106
           { 8,8,3,4, 8,8,7,0 },
107
           { 6,8,8,4, 2,8,8,0 },
108
           { 6,1,3,4, 8,8,8,8 },
109
           { 8,8,8,8, 2,5,7,0 },
110
111
           { 6,8,8,8, 8,8,8,8 },
112
           { 1,8,8,8, 8,8,8,8 },
113
           { 3,8,8,8, 8,8,8,8 },
114
           { 4,8,8,8, 8,8,8,8 },
115
           { 2,8,8,8, 8,8,8,8 },
116
           { 5,8,8,8, 8,8,8,8 },
117
           { 7,8,8,8, 8,8,8,8 },
118
           { 0,8,8,8, 8,8,8,8 }
119
         };
120
121
  private static MeshBase mOctaMesh, mTetraMesh;
122
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124
125 9c2f0c91 Leszek Koltunski
  TwistyDiamond(int size, Static4D quat, DistortedTexture texture,
126
                MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
127 ece1b58d Leszek Koltunski
    {
128 db875721 Leszek Koltunski
    super(size, size, quat, texture, mesh, effects, moves, ObjectList.DIAM, res, scrWidth);
129 ece1b58d Leszek Koltunski
    }
130
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132
133
  float getScreenRatio()
134
    {
135 ab0c28f0 Leszek Koltunski
    return 0.65f;
136 ece1b58d Leszek Koltunski
    }
137
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139
140
  Static4D[] getQuats()
141
    {
142
    return QUATS;
143
    }
144
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146
147
  int getNumFaces()
148
    {
149
    return FACE_COLORS.length;
150
    }
151
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153
154
  boolean shouldResetTextureMaps()
155
    {
156
    return false;
157
    }
158
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160
161 a64e07d0 Leszek Koltunski
  int getNumStickerTypes(int numLayers)
162 ece1b58d Leszek Koltunski
    {
163
    return 1;
164
    }
165
166
///////////////////////////////////////////////////////////////////////////////////////////////////
167
168 a97e02b7 Leszek Koltunski
  float[] getCuts(int size)
169 ece1b58d Leszek Koltunski
    {
170 a97e02b7 Leszek Koltunski
    float[] cuts = new float[1];
171
    cuts[0] = 0.0f;
172
    return cuts;
173 ece1b58d Leszek Koltunski
    }
174
175
///////////////////////////////////////////////////////////////////////////////////////////////////
176
177
  int getNumCubitFaces()
178
    {
179
    return FACES_PER_CUBIT;
180
    }
181
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183
184 e6cf7283 Leszek Koltunski
  float[][] getCubitPositions(int size)
185 ece1b58d Leszek Koltunski
    {
186
    return CENTERS;
187
    }
188
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190
191
  private Static4D getQuat(int cubit)
192
    {
193
    switch(cubit)
194
      {
195
      case  0:
196
      case  1:
197
      case  2:
198
      case  3:
199
      case  4:
200
      case  5:
201
      case  6: return QUATS[0];                          // unit quat
202 ab0c28f0 Leszek Koltunski
      case  7: return new Static4D(0,-SQ2/2,0,SQ2/2);    //  90 along Y
203 ece1b58d Leszek Koltunski
      case  8: return QUATS[1];                          // 180 along Y
204 ab0c28f0 Leszek Koltunski
      case  9: return new Static4D(0,+SQ2/2,0,SQ2/2);    //  90 along Y
205
      case 10: return new Static4D(0,     0,1,    0);    // 180 along Z
206
      case 11: return new Static4D(SQ2/2, 0,SQ2/2,0);    //
207 ece1b58d Leszek Koltunski
      case 12: return new Static4D(     1,0,0,    0);    // 180 along X
208 ab0c28f0 Leszek Koltunski
      case 13: return new Static4D(-SQ2/2,0,SQ2/2,0);    //
209 ece1b58d Leszek Koltunski
      }
210
211
    return null;
212
    }
213
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215
216 a64e07d0 Leszek Koltunski
  MeshBase createCubitMesh(int cubit, int numLayers)
217 ece1b58d Leszek Koltunski
    {
218
    MeshBase mesh;
219
220
    if( cubit<6 )
221
      {
222 b89898c5 Leszek Koltunski
      if( mOctaMesh==null ) mOctaMesh = FactoryCubit.getInstance().createOctaMesh();
223 ece1b58d Leszek Koltunski
      mesh = mOctaMesh.copy(true);
224
      }
225
    else
226
      {
227 b89898c5 Leszek Koltunski
      if( mTetraMesh==null ) mTetraMesh = FactoryCubit.getInstance().createTetraMesh();
228 ece1b58d Leszek Koltunski
      mesh = mTetraMesh.copy(true);
229
      }
230
231
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit), new Static3D(0,0,0) );
232
    mesh.apply(quat,0xffffffff,0);
233
234
    return mesh;
235
    }
236
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238
239
  int getFaceColor(int cubit, int cubitface, int size)
240
    {
241
    return mFaceMap[cubit][cubitface];
242
    }
243
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245
246 ae755eda Leszek Koltunski
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
247 ece1b58d Leszek Koltunski
    {
248 ae755eda Leszek Koltunski
    float E = 0.75f;
249
    float F = 0.50f;
250 76c2bd07 Leszek Koltunski
    float R = 0.06f;
251
    float S = 0.07f;
252
    float[] vertices = { -F,-E/3, +F,-E/3, 0.0f,2*E/3};
253
254 b89898c5 Leszek Koltunski
    FactorySticker factory = FactorySticker.getInstance();
255 ae755eda Leszek Koltunski
    factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face], R);
256 ece1b58d Leszek Koltunski
    }
257
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259
260
  float returnMultiplier()
261
    {
262 cc99cf91 Leszek Koltunski
    return 1.5f;
263 ece1b58d Leszek Koltunski
    }
264
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266
267 a64e07d0 Leszek Koltunski
  float[] getRowChances(int numLayers)
268 ece1b58d Leszek Koltunski
    {
269
    float[] chances = new float[2];
270
271
    chances[0] = 0.5f;
272
    chances[1] = 1.0f;
273
274
    return chances;
275
    }
276
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278
// PUBLIC API
279
280
  public Static3D[] getRotationAxis()
281
    {
282
    return ROT_AXIS;
283
    }
284
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286
287
  public int getBasicAngle()
288
    {
289
    return 3;
290
    }
291
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293
294 5043d5d0 Leszek Koltunski
  public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
295 ece1b58d Leszek Koltunski
    {
296 5043d5d0 Leszek Koltunski
    if( num==0 )
297 ece1b58d Leszek Koltunski
      {
298 5043d5d0 Leszek Koltunski
      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
299 ece1b58d Leszek Koltunski
      }
300
    else
301
      {
302 bbc6471c Leszek Koltunski
      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
303 5043d5d0 Leszek Koltunski
      scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
304 ece1b58d Leszek Koltunski
      }
305
306
    float rowFloat = rnd.nextFloat();
307
308
    for(int row=0; row<mRowChances.length; row++)
309
      {
310 bbc6471c Leszek Koltunski
      if( rowFloat<=mRowChances[row] )
311
        {
312 5043d5d0 Leszek Koltunski
        scramble[num][1] = row;
313 bbc6471c Leszek Koltunski
        break;
314
        }
315 ece1b58d Leszek Koltunski
      }
316
317 5043d5d0 Leszek Koltunski
    switch( rnd.nextInt(2) )
318
      {
319
      case 0: scramble[num][2] = -1; break;
320
      case 1: scramble[num][2] =  1; break;
321
      }
322 ece1b58d Leszek Koltunski
    }
323
324 ad6f6f03 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
325
326
  int mulQuat(int q1, int q2)
327
    {
328
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
329
330
    float rX = result.get0();
331
    float rY = result.get1();
332
    float rZ = result.get2();
333
    float rW = result.get3();
334
335
    final float MAX_ERROR = 0.1f;
336
    float dX,dY,dZ,dW;
337
338
    for(int i=0; i<QUATS.length; i++)
339
      {
340
      dX = QUATS[i].get0() - rX;
341
      dY = QUATS[i].get1() - rY;
342
      dZ = QUATS[i].get2() - rZ;
343
      dW = QUATS[i].get3() - rW;
344
345
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
346
          dY<MAX_ERROR && dY>-MAX_ERROR &&
347
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
348
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
349
350
      dX = QUATS[i].get0() + rX;
351
      dY = QUATS[i].get1() + rY;
352
      dZ = QUATS[i].get2() + rZ;
353
      dW = QUATS[i].get3() + rW;
354
355
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
356
          dY<MAX_ERROR && dY>-MAX_ERROR &&
357
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
358
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
359
      }
360
361
    return -1;
362
    }
363
364 ece1b58d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
365
// The Diamond is solved if and only if:
366
//
367 3f3ff476 Leszek Koltunski
// 1) all 6 octahedrons are rotated with the same quat
368 ad6f6f03 Leszek Koltunski
// 2) the 8 tetrahedrons are rotated with the quat and, optionally, the can also be rotated
369
//    by multitudes of 120 degrees along the face they are the center of.
370
//
371
// so:
372
// 1) cubits 6,12: can also be QUAT 6,10
373
// 2) cubits 7,13: can also be QUAT 4,8
374
// 3) cubits 8,10: can also be QUAT 7,11
375
// 4) cubits 9,11: can also be QUAT 5,9
376 ece1b58d Leszek Koltunski
377
  public boolean isSolved()
378
    {
379 ab0c28f0 Leszek Koltunski
    int q = CUBITS[0].mQuatIndex;
380
381 ad6f6f03 Leszek Koltunski
    if ( CUBITS[ 1].mQuatIndex == q &&
382
         CUBITS[ 2].mQuatIndex == q &&
383
         CUBITS[ 3].mQuatIndex == q &&
384
         CUBITS[ 4].mQuatIndex == q &&
385
         CUBITS[ 5].mQuatIndex == q  )
386
      {
387
      int q1 = mulQuat(q,5);
388
      int q2 = mulQuat(q,9);
389
390
      if( CUBITS[ 9].mQuatIndex != q && CUBITS[ 9].mQuatIndex != q1 && CUBITS[ 9].mQuatIndex != q2 ) return false;
391
      if( CUBITS[11].mQuatIndex != q && CUBITS[11].mQuatIndex != q1 && CUBITS[11].mQuatIndex != q2 ) return false;
392
393
      q1 = mulQuat(q,4);
394
      q2 = mulQuat(q,8);
395
396
      if( CUBITS[ 7].mQuatIndex != q && CUBITS[ 7].mQuatIndex != q1 && CUBITS[ 7].mQuatIndex != q2 ) return false;
397
      if( CUBITS[13].mQuatIndex != q && CUBITS[13].mQuatIndex != q1 && CUBITS[13].mQuatIndex != q2 ) return false;
398
399
      q1 = mulQuat(q,6);
400
      q2 = mulQuat(q,10);
401
402
      if( CUBITS[ 6].mQuatIndex != q && CUBITS[ 6].mQuatIndex != q1 && CUBITS[ 6].mQuatIndex != q2 ) return false;
403
      if( CUBITS[12].mQuatIndex != q && CUBITS[12].mQuatIndex != q1 && CUBITS[12].mQuatIndex != q2 ) return false;
404
405
      q1 = mulQuat(q,7);
406
      q2 = mulQuat(q,11);
407
408
      if( CUBITS[ 8].mQuatIndex != q && CUBITS[ 8].mQuatIndex != q1 && CUBITS[ 8].mQuatIndex != q2 ) return false;
409
      if( CUBITS[10].mQuatIndex != q && CUBITS[10].mQuatIndex != q1 && CUBITS[10].mQuatIndex != q2 ) return false;
410
411
      return true;
412
      }
413
414
    return false;
415 ece1b58d Leszek Koltunski
    }
416
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418 ab0c28f0 Leszek Koltunski
// only needed for solvers - there are no Diamond solvers ATM
419 ece1b58d Leszek Koltunski
420
  public String retObjectString()
421
    {
422
    return "";
423
    }
424
425 6fd4a72c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
426
427
  public int getObjectName(int numLayers)
428
    {
429
    return R.string.diam2;
430
    }
431
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433
434
  public int getInventor(int numLayers)
435
    {
436
    return R.string.diam2_inventor;
437
    }
438
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440
441
  public int getComplexity(int numLayers)
442
    {
443
    return 5;
444
    }
445 ece1b58d Leszek Koltunski
}