Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyCube.java @ 9c2f0c91

1 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4 fdec60a3 Leszek Koltunski
// This file is part of Magic Cube.                                                              //
5 0c52af30 Leszek Koltunski
//                                                                                               //
6 fdec60a3 Leszek Koltunski
// Magic Cube is free software: you can redistribute it and/or modify                            //
7 0c52af30 Leszek Koltunski
// 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 fdec60a3 Leszek Koltunski
// Magic Cube is distributed in the hope that it will be useful,                                 //
12 0c52af30 Leszek Koltunski
// 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 fdec60a3 Leszek Koltunski
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20 1f9772f3 Leszek Koltunski
package org.distorted.objects;
21 0c52af30 Leszek Koltunski
22 ccf9fec5 Leszek Koltunski
import android.content.res.Resources;
23 0c52af30 Leszek Koltunski
import android.graphics.Canvas;
24
import android.graphics.Paint;
25
26 14bd7976 Leszek Koltunski
import org.distorted.library.effect.VertexEffectDeform;
27 40ab026e Leszek Koltunski
import org.distorted.library.effect.VertexEffectMove;
28
import org.distorted.library.effect.VertexEffectRotate;
29 0c52af30 Leszek Koltunski
import org.distorted.library.main.DistortedEffects;
30
import org.distorted.library.main.DistortedTexture;
31 b32444ee Leszek Koltunski
import org.distorted.library.mesh.MeshBase;
32 411c6285 Leszek Koltunski
import org.distorted.library.mesh.MeshJoined;
33 c0b37c89 Leszek Koltunski
import org.distorted.library.mesh.MeshPolygon;
34 efa8aa48 Leszek Koltunski
import org.distorted.library.mesh.MeshSquare;
35 411c6285 Leszek Koltunski
import org.distorted.library.type.Static1D;
36 0c52af30 Leszek Koltunski
import org.distorted.library.type.Static3D;
37
import org.distorted.library.type.Static4D;
38 1ebc4767 Leszek Koltunski
import org.distorted.main.RubikSurfaceView;
39 0c52af30 Leszek Koltunski
40 7c969a6d Leszek Koltunski
import java.util.Random;
41
42
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
43
44 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
45
46 9c2f0c91 Leszek Koltunski
class TwistyCube extends TwistyObject
47 0c52af30 Leszek Koltunski
{
48 10585385 Leszek Koltunski
  static final float SQ2 = (float)Math.sqrt(2);
49
50 e844c116 Leszek Koltunski
  // the three rotation axis of a RubikCube. Must be normalized.
51 ad38d800 Leszek Koltunski
  static final Static3D[] ROT_AXIS = new Static3D[]
52 efef689c Leszek Koltunski
         {
53
           new Static3D(1,0,0),
54
           new Static3D(0,1,0),
55
           new Static3D(0,0,1)
56
         };
57
58 ad38d800 Leszek Koltunski
  // the six axis that determine the faces
59
  static final Static3D[] FACE_AXIS = new Static3D[]
60
         {
61 c7e79b69 Leszek Koltunski
           new Static3D(1,0,0), new Static3D(-1,0,0),
62
           new Static3D(0,1,0), new Static3D(0,-1,0),
63
           new Static3D(0,0,1), new Static3D(0,0,-1)
64 ad38d800 Leszek Koltunski
         };
65
66 37a25788 Leszek Koltunski
  private static final int[] FACE_COLORS = new int[]
67 efef689c Leszek Koltunski
         {
68 ece1b58d Leszek Koltunski
           COLOR_YELLOW, COLOR_WHITE,
69
           COLOR_BLUE  , COLOR_GREEN,
70
           COLOR_RED   , COLOR_BROWN
71 efef689c Leszek Koltunski
         };
72
73 10585385 Leszek Koltunski
  // All legal rotation quats of a RubikCube of any size.
74 efef689c Leszek Koltunski
  // Here's how to compute this:
75
  // 1) compute how many rotations there are (RubikCube of any size = 24)
76
  // 2) take the AXIS, angles of rotation (90 in RubikCube's case) compute the basic quaternions
77
  // (i.e. rotations of 1 basic angle along each of the axis) and from there start semi-randomly
78
  // multiplying them and eventually you'll find all (24) legal rotations.
79 9f4c44fe Leszek Koltunski
  // Example program in C, res/raw/compute_quats.c , is included.
80 10585385 Leszek Koltunski
  private static final Static4D[] QUATS = new Static4D[]
81 efef689c Leszek Koltunski
         {
82 10585385 Leszek Koltunski
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
83
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
84
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
85
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
86
87
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
88
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
89
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
90
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
91
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
92
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
93
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
94
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
95
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
96
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
97
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
98
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
99
100
         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
101
         new Static4D(  0.5f,   0.5f,  -0.5f,   0.5f),
102
         new Static4D(  0.5f,   0.5f,  -0.5f,  -0.5f),
103
         new Static4D(  0.5f,  -0.5f,   0.5f,  -0.5f),
104
         new Static4D( -0.5f,  -0.5f,  -0.5f,   0.5f),
105
         new Static4D( -0.5f,   0.5f,  -0.5f,  -0.5f),
106
         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
107
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
108 efef689c Leszek Koltunski
         };
109 411c6285 Leszek Koltunski
110 fbca0033 Leszek Koltunski
  private static MeshBase[] mMeshes;
111 40ab026e Leszek Koltunski
112 411c6285 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
113
114 9c2f0c91 Leszek Koltunski
  TwistyCube(int size, Static4D quat, DistortedTexture texture,
115
             MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
116 411c6285 Leszek Koltunski
    {
117 9c2f0c91 Leszek Koltunski
    super(size, 60, quat, texture, mesh, effects, moves, ObjectList.CUBE, res, scrWidth);
118 411c6285 Leszek Koltunski
    }
119
120 7289fd6c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
121 42803ba0 Leszek Koltunski
// paint the square with upper-right corner at (left,top) and side length 'side' with texture
122 7289fd6c Leszek Koltunski
// for face 'face'.
123
124
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side)
125
    {
126
    final float R = side*0.10f;
127
    final float M = side*0.05f;
128
129
    paint.setColor(FACE_COLORS[face]);
130
    canvas.drawRoundRect( left+M, top+M, left+side-M, top+side-M, R, R, paint);
131
    }
132
133 411c6285 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
134
135 10a2e360 Leszek Koltunski
  Static3D[] getCubitPositions(int size)
136 a10ada2a Leszek Koltunski
    {
137 10a2e360 Leszek Koltunski
    int numCubits = size>1 ? 6*size*size - 12*size + 8 : 1;
138
    Static3D[] tmp = new Static3D[numCubits];
139 beb325a0 Leszek Koltunski
140 49f67f9b Leszek Koltunski
    float diff = 0.5f*(size-1);
141 a10ada2a Leszek Koltunski
    int currentPosition = 0;
142 beb325a0 Leszek Koltunski
143 a10ada2a Leszek Koltunski
    for(int x = 0; x<size; x++)
144
      for(int y = 0; y<size; y++)
145
        for(int z = 0; z<size; z++)
146
          if( x==0 || x==size-1 || y==0 || y==size-1 || z==0 || z==size-1 )
147 beb325a0 Leszek Koltunski
            {
148 49f67f9b Leszek Koltunski
            tmp[currentPosition++] = new Static3D(x-diff,y-diff,z-diff);
149 a10ada2a Leszek Koltunski
            }
150 47ba5ddc Leszek Koltunski
151 a10ada2a Leszek Koltunski
    return tmp;
152
    }
153 47ba5ddc Leszek Koltunski
154 beb325a0 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
155
156 10585385 Leszek Koltunski
  Static4D[] getQuats()
157 a10ada2a Leszek Koltunski
    {
158 10585385 Leszek Koltunski
    return QUATS;
159 a10ada2a Leszek Koltunski
    }
160 47ba5ddc Leszek Koltunski
161 eaee1ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
162
163
  boolean shouldResetTextureMaps()
164
    {
165
    return false;
166
    }
167
168 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
169
170 411c6285 Leszek Koltunski
  int getNumFaces()
171 a10ada2a Leszek Koltunski
    {
172 411c6285 Leszek Koltunski
    return FACE_COLORS.length;
173 8f53e513 Leszek Koltunski
    }
174
175 7403cdfa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
176
177
  float getBasicStep()
178
    {
179
    return 1.0f;
180
    }
181
182 eab9d8f8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
183
184
  int getNumStickerTypes()
185
    {
186
    return 1;
187
    }
188
189 8f53e513 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
190
191
  int getNumCubitFaces()
192
    {
193
    return FACE_COLORS.length;
194 411c6285 Leszek Koltunski
    }
195 47ba5ddc Leszek Koltunski
196 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
197
198
  float getScreenRatio()
199
    {
200
    return 0.5f;
201
    }
202
203 f6d06256 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
204
205
  int getFaceColor(int cubit, int cubitface, int size)
206
    {
207
    boolean belongs = isOnFace(cubit, cubitface/2, cubitface%2==0 ? size-1:0 );
208
    return belongs ? cubitface : NUM_FACES;
209
    }
210
211 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
212
213 14bd7976 Leszek Koltunski
  MeshBase createCubitMesh(int cubit)
214 a10ada2a Leszek Koltunski
    {
215 fbca0033 Leszek Koltunski
    int size   = getSize();
216 9c2f0c91 Leszek Koltunski
    int ordinal= ObjectList.CUBE.ordinal();
217
    int index  = ObjectList.getSizeIndex(ordinal,size);
218 c0b37c89 Leszek Koltunski
    float[] bands;
219
    float D = 0.027f;
220
    float E = 0.5f-D;
221
    float[] vertices = { -E,-E, +E,-E, +E,+E, -E,+E };
222
    int extraI, extraV;
223 fbca0033 Leszek Koltunski
224
    switch(size)
225
      {
226 c0b37c89 Leszek Koltunski
      case 2 : bands = new float[] { 1.0f    ,-D,
227 231771f3 Leszek Koltunski
                                     1.0f-D/2,-D*0.55f,
228
                                     1.0f-D  ,-D*0.25f,
229 c0b37c89 Leszek Koltunski
                                     1.0f-2*D, 0.0f,
230
                                     0.50f, 0.040f,
231
                                     0.0f, 0.048f };
232
               extraI = 2;
233
               extraV = 2;
234 fbca0033 Leszek Koltunski
               break;
235 c0b37c89 Leszek Koltunski
      case 3 : bands = new float[] { 1.0f    ,-D,
236
                                     1.0f-D*1.2f,-D*0.55f,
237
                                     1.0f-2*D, 0.0f,
238
                                     0.50f, 0.040f,
239
                                     0.0f, 0.048f };
240
               extraI = 2;
241
               extraV = 2;
242
               break;
243
      case 4 : bands = new float[] { 1.0f    ,-D,
244
                                     1.0f-D*1.2f,-D*0.55f,
245
                                     1.0f-2*D, 0.0f,
246
                                     0.50f, 0.040f,
247
                                     0.0f, 0.048f };
248
               extraI = 1;
249
               extraV = 2;
250
               break;
251
      default: bands = new float[] { 1.0f    ,-D,
252
                                     1.0f-2*D, 0.0f,
253
                                     0.50f, 0.025f,
254
                                     0.0f, 0.030f };
255
               extraI = 1;
256
               extraV = 1;
257 fbca0033 Leszek Koltunski
               break;
258
      }
259
260 c0b37c89 Leszek Koltunski
    return createCubitMesh(index,vertices,bands,extraI,extraV);
261 55fa2499 Leszek Koltunski
    }
262
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264
265 c0b37c89 Leszek Koltunski
  MeshBase createCubitMesh(int index, float[] vertices, float[] bands, int extraI, int extraV)
266 55fa2499 Leszek Koltunski
    {
267 fbca0033 Leszek Koltunski
    if( mMeshes==null )
268
      {
269 9c2f0c91 Leszek Koltunski
      mMeshes = new MeshBase[ObjectList.CUBE.getNumVariants()];
270 fbca0033 Leszek Koltunski
      }
271 55fa2499 Leszek Koltunski
272 fbca0033 Leszek Koltunski
    if( mMeshes[index]==null )
273 40ab026e Leszek Koltunski
      {
274
      final int MESHES=6;
275
      int association = 1;
276 c0b37c89 Leszek Koltunski
      MeshBase[] meshes = new MeshPolygon[MESHES];
277
      meshes[0] = new MeshPolygon(vertices,bands,extraI,extraV);
278 e82f3f9c Leszek Koltunski
      meshes[0].setEffectAssociation(0,association,0);
279 40ab026e Leszek Koltunski
280
      for(int i=1; i<MESHES; i++)
281
        {
282
        association <<=1;
283
        meshes[i] = meshes[0].copy(true);
284 e82f3f9c Leszek Koltunski
        meshes[i].setEffectAssociation(0,association,0);
285 40ab026e Leszek Koltunski
        }
286
287 fbca0033 Leszek Koltunski
      mMeshes[index] = new MeshJoined(meshes);
288 40ab026e Leszek Koltunski
289
      Static3D axisY   = new Static3D(0,1,0);
290
      Static3D axisX   = new Static3D(1,0,0);
291
      Static3D center  = new Static3D(0,0,0);
292
      Static1D angle90 = new Static1D(90);
293
      Static1D angle180= new Static1D(180);
294
      Static1D angle270= new Static1D(270);
295
296 14bd7976 Leszek Koltunski
      float d1 = 1.0f;
297
      float d2 =-0.05f;
298
      float d3 = 0.12f;
299
300
      Static3D dCen0 = new Static3D( d1*(+0.5f), d1*(+0.5f), d1*(+0.5f) );
301
      Static3D dCen1 = new Static3D( d1*(+0.5f), d1*(+0.5f), d1*(-0.5f) );
302
      Static3D dCen2 = new Static3D( d1*(+0.5f), d1*(-0.5f), d1*(+0.5f) );
303
      Static3D dCen3 = new Static3D( d1*(+0.5f), d1*(-0.5f), d1*(-0.5f) );
304
      Static3D dCen4 = new Static3D( d1*(-0.5f), d1*(+0.5f), d1*(+0.5f) );
305
      Static3D dCen5 = new Static3D( d1*(-0.5f), d1*(+0.5f), d1*(-0.5f) );
306
      Static3D dCen6 = new Static3D( d1*(-0.5f), d1*(-0.5f), d1*(+0.5f) );
307
      Static3D dCen7 = new Static3D( d1*(-0.5f), d1*(-0.5f), d1*(-0.5f) );
308
309
      Static3D dVec0 = new Static3D( d2*(+0.5f), d2*(+0.5f), d2*(+0.5f) );
310
      Static3D dVec1 = new Static3D( d2*(+0.5f), d2*(+0.5f), d2*(-0.5f) );
311
      Static3D dVec2 = new Static3D( d2*(+0.5f), d2*(-0.5f), d2*(+0.5f) );
312
      Static3D dVec3 = new Static3D( d2*(+0.5f), d2*(-0.5f), d2*(-0.5f) );
313
      Static3D dVec4 = new Static3D( d2*(-0.5f), d2*(+0.5f), d2*(+0.5f) );
314
      Static3D dVec5 = new Static3D( d2*(-0.5f), d2*(+0.5f), d2*(-0.5f) );
315
      Static3D dVec6 = new Static3D( d2*(-0.5f), d2*(-0.5f), d2*(+0.5f) );
316
      Static3D dVec7 = new Static3D( d2*(-0.5f), d2*(-0.5f), d2*(-0.5f) );
317
318
      Static4D dReg  = new Static4D(0,0,0,d3);
319
      Static1D dRad  = new Static1D(1);
320
321 40ab026e Leszek Koltunski
      VertexEffectMove   effect0 = new VertexEffectMove(new Static3D(0,0,+0.5f));
322 e82f3f9c Leszek Koltunski
      effect0.setMeshAssociation(63,-1);  // all 6 sides
323 40ab026e Leszek Koltunski
      VertexEffectRotate effect1 = new VertexEffectRotate( angle180, axisX, center );
324 e82f3f9c Leszek Koltunski
      effect1.setMeshAssociation(32,-1);  // back
325 40ab026e Leszek Koltunski
      VertexEffectRotate effect2 = new VertexEffectRotate( angle90 , axisX, center );
326 e82f3f9c Leszek Koltunski
      effect2.setMeshAssociation( 8,-1);  // bottom
327 40ab026e Leszek Koltunski
      VertexEffectRotate effect3 = new VertexEffectRotate( angle270, axisX, center );
328 e82f3f9c Leszek Koltunski
      effect3.setMeshAssociation( 4,-1);  // top
329 40ab026e Leszek Koltunski
      VertexEffectRotate effect4 = new VertexEffectRotate( angle270, axisY, center );
330 e82f3f9c Leszek Koltunski
      effect4.setMeshAssociation( 2,-1);  // left
331 40ab026e Leszek Koltunski
      VertexEffectRotate effect5 = new VertexEffectRotate( angle90 , axisY, center );
332 e82f3f9c Leszek Koltunski
      effect5.setMeshAssociation( 1,-1);  // right
333 40ab026e Leszek Koltunski
334 14bd7976 Leszek Koltunski
      VertexEffectDeform effect6 = new VertexEffectDeform(dVec0, dRad, dCen0, dReg);
335
      VertexEffectDeform effect7 = new VertexEffectDeform(dVec1, dRad, dCen1, dReg);
336
      VertexEffectDeform effect8 = new VertexEffectDeform(dVec2, dRad, dCen2, dReg);
337
      VertexEffectDeform effect9 = new VertexEffectDeform(dVec3, dRad, dCen3, dReg);
338
      VertexEffectDeform effect10= new VertexEffectDeform(dVec4, dRad, dCen4, dReg);
339
      VertexEffectDeform effect11= new VertexEffectDeform(dVec5, dRad, dCen5, dReg);
340
      VertexEffectDeform effect12= new VertexEffectDeform(dVec6, dRad, dCen6, dReg);
341
      VertexEffectDeform effect13= new VertexEffectDeform(dVec7, dRad, dCen7, dReg);
342
343 fbca0033 Leszek Koltunski
      mMeshes[index].apply(effect0);
344
      mMeshes[index].apply(effect1);
345
      mMeshes[index].apply(effect2);
346
      mMeshes[index].apply(effect3);
347
      mMeshes[index].apply(effect4);
348
      mMeshes[index].apply(effect5);
349
      mMeshes[index].apply(effect6);
350
      mMeshes[index].apply(effect7);
351
      mMeshes[index].apply(effect8);
352
      mMeshes[index].apply(effect9);
353
      mMeshes[index].apply(effect10);
354
      mMeshes[index].apply(effect11);
355
      mMeshes[index].apply(effect12);
356
      mMeshes[index].apply(effect13);
357
358
      mMeshes[index].mergeEffComponents();
359 40ab026e Leszek Koltunski
      }
360 411c6285 Leszek Koltunski
361 fbca0033 Leszek Koltunski
    return mMeshes[index].copy(true);
362 a10ada2a Leszek Koltunski
    }
363 e844c116 Leszek Koltunski
364 fb377dae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
365
366
  float returnMultiplier()
367
    {
368
    return getSize();
369
    }
370
371 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
372
373
  float[] getRowChances()
374
    {
375
    int size = getSize();
376
    float[] chances = new float[size];
377
378
    for(int i=0; i<size; i++)
379
      {
380
      chances[i] = (i+1.0f) / size;
381
      }
382
383
    return chances;
384
    }
385
386 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
387
// PUBLIC API
388
389 12ad3fca Leszek Koltunski
  public Static3D[] getRotationAxis()
390
    {
391 ad38d800 Leszek Koltunski
    return ROT_AXIS;
392 12ad3fca Leszek Koltunski
    }
393
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395
396 e844c116 Leszek Koltunski
  public int getBasicAngle()
397
    {
398
    return 4;
399
    }
400 39e74052 Leszek Koltunski
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402
403 fb377dae Leszek Koltunski
  public int computeRowFromOffset(float offset)
404 39e74052 Leszek Koltunski
    {
405 fb377dae Leszek Koltunski
    return (int)(getSize()*offset);
406 39e74052 Leszek Koltunski
    }
407 e46e17fb Leszek Koltunski
408 5cf34c5f Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
409
410 7c969a6d Leszek Koltunski
  public float returnRotationFactor(float offset)
411 5cf34c5f Leszek Koltunski
    {
412 7c969a6d Leszek Koltunski
    return 1.0f;
413
    }
414 5cf34c5f Leszek Koltunski
415 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
416
417
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
418
    {
419
    int numAxis = ROTATION_AXIS.length;
420
421
    if( oldRotAxis == START_AXIS )
422 5cf34c5f Leszek Koltunski
      {
423 7c969a6d Leszek Koltunski
      return rnd.nextInt(numAxis);
424
      }
425
    else
426
      {
427
      int newVector = rnd.nextInt(numAxis-1);
428
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
429 5cf34c5f Leszek Koltunski
      }
430
    }
431
432 e46e17fb Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
433
434 7c969a6d Leszek Koltunski
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
435 e46e17fb Leszek Koltunski
    {
436 7c969a6d Leszek Koltunski
    float rowFloat = rnd.nextFloat();
437
438
    for(int row=0; row<mRowChances.length; row++)
439
      {
440
      if( rowFloat<=mRowChances[row] ) return row;
441
      }
442
443
    return 0;
444 e46e17fb Leszek Koltunski
    }
445 f0336037 Leszek Koltunski
446 6b6504fe Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
447
448
  public boolean isSolved()
449
    {
450
    int index = CUBITS[0].mQuatIndex;
451
452
    for(int i=1; i<NUM_CUBITS; i++)
453
      {
454
      if( !thereIsNoVisibleDifference(CUBITS[i], index) ) return false;
455
      }
456
457
    return true;
458
    }
459
460 1ebc4767 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
461
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different
462
// then if it were rotated by quaternion 'quat'.
463
// No it is not so simple as the quats need to be the same - imagine a 4x4x4 cube where the two
464
// middle squares get interchanged. No visible difference!
465
//
466
// So: this is true iff the cubit
467
// a) is a corner or edge and the quaternions are the same
468
// b) is inside one of the faces and after rotations by both quats it ends up on the same face.
469
470 6b6504fe Leszek Koltunski
  private boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex)
471 1ebc4767 Leszek Koltunski
    {
472
    if ( cubit.mQuatIndex == quatIndex ) return true;
473
474
    int belongsToHowManyFaces = 0;
475
    int size = getSize()-1;
476
    float row;
477
    final float MAX_ERROR = 0.01f;
478
479
    for(int i=0; i<NUM_AXIS; i++)
480
      {
481
      row = cubit.mRotationRow[i];
482
      if( (row     <MAX_ERROR && row     >-MAX_ERROR) ||
483
          (row-size<MAX_ERROR && row-size>-MAX_ERROR)  ) belongsToHowManyFaces++;
484
      }
485
486
    switch(belongsToHowManyFaces)
487
      {
488
      case 0 : return true ;  // 'inside' cubit that does not lie on any face
489
      case 1 :                // cubit that lies inside one of the faces
490
               Static3D orig = cubit.getOrigPosition();
491
               Static4D quat1 = QUATS[quatIndex];
492
               Static4D quat2 = QUATS[cubit.mQuatIndex];
493
494
               Static4D cubitCenter = new Static4D( orig.get0(), orig.get1(), orig.get2(), 0);
495
               Static4D rotated1 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat1 );
496
               Static4D rotated2 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat2 );
497
498
               float row1, row2, row3, row4;
499
               float ax,ay,az;
500
               Static3D axis;
501
               float x1 = rotated1.get0();
502
               float y1 = rotated1.get1();
503
               float z1 = rotated1.get2();
504
               float x2 = rotated2.get0();
505
               float y2 = rotated2.get1();
506
               float z2 = rotated2.get2();
507
508
               for(int i=0; i<NUM_AXIS; i++)
509
                 {
510
                 axis = ROTATION_AXIS[i];
511
                 ax = axis.get0();
512
                 ay = axis.get1();
513
                 az = axis.get2();
514
515
                 row1 = ((x1*ax + y1*ay + z1*az) - mStart) / mStep;
516
                 row2 = ((x2*ax + y2*ay + z2*az) - mStart) / mStep;
517
                 row3 = row1 - size;
518
                 row4 = row2 - size;
519
520
                 if( (row1<MAX_ERROR && row1>-MAX_ERROR && row2<MAX_ERROR && row2>-MAX_ERROR) ||
521
                     (row3<MAX_ERROR && row3>-MAX_ERROR && row4<MAX_ERROR && row4>-MAX_ERROR)  )
522
                   {
523
                   return true;
524
                   }
525
                 }
526
               return false;
527
528
      default: return false;  // edge or corner
529
      }
530
    }
531
532 f0336037 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
533 a304ee64 Leszek Koltunski
// order: Up --> Right --> Front --> Down --> Left --> Back
534
// (because the first implemented Solver - the two-phase Cube3 one - expects such order)
535
//
536 fa0f7a56 Leszek Koltunski
// Solved 3x3x3 Cube maps to "UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB"
537 a304ee64 Leszek Koltunski
//
538 fa0f7a56 Leszek Koltunski
// s : size of the cube; let index = a*s + b    (i.e. a,b = row,column)
539
//
540
// Up    :   index --> b<s-1 ? (s-1)*(s+4b)+a : 6*s*s -13*s +8 +a
541 a304ee64 Leszek Koltunski
// Right :   index --> 6*s*s - 12*s + 7 - index
542 fa0f7a56 Leszek Koltunski
// Front :   index --> if b==0  : s*s - 1 - index
543
//                     if b==s-1: 6*s*s -11*s +6 - index
544
//                     else
545
//                         a==0: s*s + s-1 + 4*(b-1)*(s-1) + 2*(s-2) + s
546
//                         else: s*s + s-1 + 4*(b-1)*(s-1) + 2*(s-1-a)
547
// Down  :   index --> b==0 ? (s-1-a) : s*s + s-1 + 4*(b-1)*(s-1) - a
548
// Left  :   index --> (s-1-a)*s + b
549
// Back  :   index --> if b==s-1: s*(s-1-a)
550
//                     if b==0  : 5*s*s -12*s + 8 + (s-1-a)*s
551
//                     else
552
//                        if a==s-1: s*s + 4*(s-2-b)*(s-1)
553
//                        else     : s*s + 4*(s-2-b)*(s-1) + s + (s-2-a)*2
554 f0336037 Leszek Koltunski
555 20931cf6 Leszek Koltunski
  public String retObjectString()
556 f0336037 Leszek Koltunski
    {
557 fa0f7a56 Leszek Koltunski
    StringBuilder objectString = new StringBuilder();
558
    int size = getSize();
559
    int len = size*size;
560 49595e4b Leszek Koltunski
    int cubitIndex=-1, row=-1, col=-1;
561
    int color=-1, face=-1;
562 fa0f7a56 Leszek Koltunski
563
    final int RIGHT= 0;
564
    final int LEFT = 1;
565
    final int UP   = 2;
566
    final int DOWN = 3;
567
    final int FRONT= 4;
568
    final int BACK = 5;
569
570 fb52fae9 Leszek Koltunski
    // 'I' - interior, theoretically can happen
571
    final char[] FACE_NAMES = { 'R', 'L', 'U', 'D', 'F', 'B', 'I'};
572 49595e4b Leszek Koltunski
573
    face = UP;
574
575 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
576
      {
577
      row = i/size;
578
      col = i%size;
579
580
      cubitIndex = col<size-1 ? (size-1)*(size+4*col) + row : 6*size*size - 13*size + 8 + row;
581 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
582 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
583
      }
584
585 49595e4b Leszek Koltunski
    face = RIGHT;
586
587 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
588
      {
589
      cubitIndex = 6*size*size - 12*size +7 - i;
590 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
591 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
592
      }
593
594 49595e4b Leszek Koltunski
     face = FRONT;
595
596 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
597
      {
598
      row = i/size;
599
      col = i%size;
600
601
      if( col==size-1 ) cubitIndex = 6*size*size - 11*size + 6 -i;
602
      else if( col==0 ) cubitIndex = size*size - 1 - i;
603
      else
604
        {
605
        if( row==0 ) cubitIndex = size*size + size-1 + 4*(col-1)*(size-1) + 2*(size-2) + size;
606
        else         cubitIndex = size*size + size-1 + 4*(col-1)*(size-1) + 2*(size-1-row);
607
        }
608
609 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
610 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
611
      }
612
613 49595e4b Leszek Koltunski
    face = DOWN;
614
615 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
616
      {
617
      row = i/size;
618
      col = i%size;
619
620
      cubitIndex = col==0 ? size-1-row : size*size + size-1 + 4*(col-1)*(size-1) - row;
621 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
622 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
623
      }
624
625 49595e4b Leszek Koltunski
    face = LEFT;
626
627 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
628
      {
629
      row = i/size;
630
      col = i%size;
631
632
      cubitIndex = (size-1-row)*size + col;
633 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
634 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
635
      }
636
637 49595e4b Leszek Koltunski
    face = BACK;
638
639 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
640
      {
641
      row = i/size;
642
      col = i%size;
643
644
      if( col==size-1 ) cubitIndex = size*(size-1-row);
645
      else if( col==0 ) cubitIndex = 5*size*size - 12*size + 8 + (size-1-row)*size;
646
      else
647
        {
648
        if( row==size-1 ) cubitIndex = size*size + 4*(size-2-col)*(size-1);
649
        else              cubitIndex = size*size + 4*(size-2-col)*(size-1) + size + 2*(size-2-row);
650
        }
651
652 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
653 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
654
      }
655
656
    return objectString.toString();
657 f0336037 Leszek Koltunski
    }
658 0c52af30 Leszek Koltunski
}