Project

General

Profile

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

magiccube / src / main / java / org / distorted / object / RubikCube.java @ 97c012ae

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 beb325a0 Leszek Koltunski
package org.distorted.object;
21 0c52af30 Leszek Koltunski
22 5bfc1b49 Leszek Koltunski
import android.content.SharedPreferences;
23 0c52af30 Leszek Koltunski
import android.graphics.Bitmap;
24
import android.graphics.Canvas;
25
import android.graphics.Paint;
26
27 434f2f5a Leszek Koltunski
import org.distorted.library.effect.Effect;
28 0c52af30 Leszek Koltunski
import org.distorted.library.effect.MatrixEffectMove;
29
import org.distorted.library.effect.MatrixEffectQuaternion;
30
import org.distorted.library.effect.MatrixEffectRotate;
31
import org.distorted.library.main.DistortedEffects;
32 34998c9d Leszek Koltunski
import org.distorted.library.main.DistortedNode;
33 0c52af30 Leszek Koltunski
import org.distorted.library.main.DistortedTexture;
34
import org.distorted.library.mesh.MeshCubes;
35 97c012ae Leszek Koltunski
import org.distorted.library.mesh.MeshRectangles;
36 0c52af30 Leszek Koltunski
import org.distorted.library.message.EffectListener;
37
import org.distorted.library.type.Dynamic1D;
38
import org.distorted.library.type.Static1D;
39
import org.distorted.library.type.Static3D;
40
import org.distorted.library.type.Static4D;
41 beb325a0 Leszek Koltunski
import org.distorted.magic.RubikSurfaceView;
42 0c52af30 Leszek Koltunski
43 27a70eae Leszek Koltunski
import static org.distorted.object.RubikObjectList.VECTX;
44
import static org.distorted.object.RubikObjectList.VECTY;
45
import static org.distorted.object.RubikObjectList.VECTZ;
46
47 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
48
49 27a70eae Leszek Koltunski
class RubikCube extends RubikObject
50 0c52af30 Leszek Koltunski
{
51
    private static final Static3D VectX = new Static3D(1,0,0);
52
    private static final Static3D VectY = new Static3D(0,1,0);
53
    private static final Static3D VectZ = new Static3D(0,0,1);
54
55 34998c9d Leszek Koltunski
    private DistortedNode[][][] mNodes;
56 0c52af30 Leszek Koltunski
    private MeshCubes[][][] mCubes;
57
    private DistortedEffects[][][] mEffects;
58
    private Static4D[][][] mQuatScramble;
59
    private Static3D[][][] mRotationAxis;
60
    private Dynamic1D[][][] mRotationAngle;
61
    private Static3D[][][] mCurrentPosition;
62 434f2f5a Leszek Koltunski
    private MatrixEffectRotate[][][] mRotateEffect;
63 05fa94d9 Leszek Koltunski
64 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
65 47ba5ddc Leszek Koltunski
// All legal rotation quats must have all four of their components equal to either
66
// 0, 1, -1, 0.5, -0.5 or +-sqrt(2)/2.
67
//
68
// Because of quatMultiplication, errors can accumulate - so to avoid this, we
69
// correct the value of the 'scramble' quat to what it should be.
70
//
71
// We also have to remember that the group of unit quaternions is a double-cover of rotations
72
// in 3D ( q represents the same rotation as -q ) - so invert if needed.
73 0c52af30 Leszek Koltunski
74 47ba5ddc Leszek Koltunski
    private static final float SQ2 = 0.5f*((float)Math.sqrt(2));
75
    private static final float[] LEGAL = { 0.0f , 0.5f , -0.5f , 1.0f , -1.0f , SQ2 , -SQ2 };
76
77
    private void normalizeScrambleQuat(int i, int j, int k)
78 0c52af30 Leszek Koltunski
      {
79 47ba5ddc Leszek Koltunski
      Static4D quat = mQuatScramble[i][j][k];
80 34998c9d Leszek Koltunski
81 348dfe69 Leszek Koltunski
      float x = quat.get0();
82
      float y = quat.get1();
83
      float z = quat.get2();
84
      float w = quat.get3();
85 47ba5ddc Leszek Koltunski
      float diff;
86 434f2f5a Leszek Koltunski
87 47ba5ddc Leszek Koltunski
      for(float legal: LEGAL)
88
        {
89
        diff = x-legal;
90
        if( diff*diff<0.01f ) x = legal;
91
        diff = y-legal;
92
        if( diff*diff<0.01f ) y = legal;
93
        diff = z-legal;
94
        if( diff*diff<0.01f ) z = legal;
95
        diff = w-legal;
96
        if( diff*diff<0.01f ) w = legal;
97
        }
98
99
      if( w<0 )
100
        {
101
        w = -w;
102
        z = -z;
103
        y = -y;
104
        x = -x;
105
        }
106
      else if( w==0 )
107
        {
108
        if( z<0 )
109
          {
110
          z = -z;
111
          y = -y;
112
          x = -x;
113
          }
114
        else if( z==0 )
115
          {
116
          if( y<0 )
117 434f2f5a Leszek Koltunski
            {
118 47ba5ddc Leszek Koltunski
            y = -y;
119
            x = -x;
120
            }
121
          else if( y==0 )
122
            {
123
            if( x<0 )
124 434f2f5a Leszek Koltunski
              {
125 47ba5ddc Leszek Koltunski
              x = -x;
126 9208e27b Leszek Koltunski
              }
127
            }
128 47ba5ddc Leszek Koltunski
          }
129
        }
130 584f7954 Leszek Koltunski
131 47ba5ddc Leszek Koltunski
      mQuatScramble[i][j][k].set(x,y,z,w);
132 584f7954 Leszek Koltunski
      }
133
134 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
135 30b68322 Leszek Koltunski
136 47ba5ddc Leszek Koltunski
    private boolean belongsToRotation(int x, int y, int z, int vector, int row)
137
      {
138
      switch(vector)
139 30b68322 Leszek Koltunski
        {
140 348dfe69 Leszek Koltunski
        case VECTX: return mCurrentPosition[x][y][z].get0()==row;
141
        case VECTY: return mCurrentPosition[x][y][z].get1()==row;
142
        case VECTZ: return mCurrentPosition[x][y][z].get2()==row;
143 30b68322 Leszek Koltunski
        }
144
145 47ba5ddc Leszek Koltunski
      return false;
146 30b68322 Leszek Koltunski
      }
147 47ba5ddc Leszek Koltunski
148 9208e27b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
149
150 47ba5ddc Leszek Koltunski
    private void modifyCurrentPosition(int x, int y, int z, Static4D quat)
151 9208e27b Leszek Koltunski
      {
152 47ba5ddc Leszek Koltunski
      Static3D current = mCurrentPosition[x][y][z];
153
      float diff = 0.5f*(mSize-1);
154 348dfe69 Leszek Koltunski
      float cubitCenterX = current.get0() - diff;
155
      float cubitCenterY = current.get1() - diff;
156
      float cubitCenterZ = current.get2() - diff;
157 47ba5ddc Leszek Koltunski
158
      Static4D cubitCenter =  new Static4D(cubitCenterX, cubitCenterY, cubitCenterZ, 0);
159
      Static4D rotatedCenter = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat);
160
161 348dfe69 Leszek Koltunski
      float rotatedX = rotatedCenter.get0() + diff;
162
      float rotatedY = rotatedCenter.get1() + diff;
163
      float rotatedZ = rotatedCenter.get2() + diff;
164 47ba5ddc Leszek Koltunski
165
      int roundedX = (int)(rotatedX+0.1f);
166
      int roundedY = (int)(rotatedY+0.1f);
167
      int roundedZ = (int)(rotatedZ+0.1f);
168
169 348dfe69 Leszek Koltunski
      mCurrentPosition[x][y][z].set0(roundedX);
170
      mCurrentPosition[x][y][z].set1(roundedY);
171
      mCurrentPosition[x][y][z].set2(roundedZ);
172 434f2f5a Leszek Koltunski
      }
173
174 beb325a0 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
175
176 97c012ae Leszek Koltunski
    RubikCube(int size, Static4D quatCur, Static4D quatAcc, DistortedTexture texture, MeshRectangles mesh, DistortedEffects effects)
177 beb325a0 Leszek Koltunski
      {
178 27a70eae Leszek Koltunski
      super(size,quatCur,quatAcc,texture,mesh,effects);
179 beb325a0 Leszek Koltunski
180
      mRotAxis = VECTX;
181
      mTexture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
182
183
      mNodes          = new DistortedNode[mSize][mSize][mSize];
184
      mCubes          = new MeshCubes[mSize][mSize][mSize];
185
      mEffects        = new DistortedEffects[mSize][mSize][mSize];
186
      mQuatScramble   = new Static4D[mSize][mSize][mSize];
187
      mRotationAxis   = new Static3D[mSize][mSize][mSize];
188
      mRotationAngle  = new Dynamic1D[mSize][mSize][mSize];
189
      mCurrentPosition= new Static3D[mSize][mSize][mSize];
190
      mRotateEffect   = new MatrixEffectRotate[mSize][mSize][mSize];
191
192
      Static3D[][][] cubeVectors = new Static3D[mSize][mSize][mSize];
193
      Static3D matrCenter = new Static3D(0,0,0);
194
195
      // 3x2 bitmap = 6 squares:
196
      //
197
      // RED     GREEN   BLUE
198
      // YELLOW  WHITE   BROWN
199
200
      final float ze = 0.0f;
201
      final float ot = 1.0f/3.0f;
202
      final float tt = 2.0f/3.0f;
203
      final float oh = 1.0f/2.0f;
204
      final float of = 1.0f/40.0f;
205
206
      final Static4D mapFront = new Static4D(ze,oh, ze+ot,oh+oh);
207
      final Static4D mapBack  = new Static4D(tt,ze, tt+ot,ze+oh);
208
      final Static4D mapLeft  = new Static4D(ot,ze, ot+ot,ze+oh);
209
      final Static4D mapRight = new Static4D(ze,ze, ze+ot,ze+oh);
210
      final Static4D mapTop   = new Static4D(tt,oh, tt+ot,oh+oh);
211
      final Static4D mapBottom= new Static4D(ot,oh, ot+ot,oh+oh);
212
213
      final Static4D mapBlack = new Static4D(ze,ze, ze+of,ze+of);
214
215
      Static4D tmpFront, tmpBack, tmpLeft, tmpRight, tmpTop, tmpBottom;
216
      float nc = 0.5f*mSize;
217
      int vertices = (int)(24.0f/mSize + 2.0f);
218
219
      for(int x = 0; x< mSize; x++)
220
        for(int y = 0; y< mSize; y++)
221
          for(int z = 0; z< mSize; z++)
222
            {
223
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 ) // only the external walls
224
              {
225
              tmpLeft  = (x==       0 ? mapLeft  :mapBlack);
226
              tmpRight = (x== mSize-1 ? mapRight :mapBlack);
227
              tmpFront = (z== mSize-1 ? mapFront :mapBlack);
228
              tmpBack  = (z==       0 ? mapBack  :mapBlack);
229
              tmpTop   = (y== mSize-1 ? mapTop   :mapBlack);
230
              tmpBottom= (y==       0 ? mapBottom:mapBlack);
231
232
              mCubes[x][y][z]           = new MeshCubes(vertices,vertices,vertices, tmpFront, tmpBack, tmpLeft, tmpRight, tmpTop, tmpBottom);
233
              cubeVectors[x][y][z]      = new Static3D( TEXTURE_SIZE*(x-nc), TEXTURE_SIZE*(y-nc), TEXTURE_SIZE*(z-nc) );
234
              mQuatScramble[x][y][z]    = new Static4D(0,0,0,1);
235
              mRotationAngle[x][y][z]   = new Dynamic1D();
236
              mRotationAxis[x][y][z]    = new Static3D(1,0,0);
237
              mCurrentPosition[x][y][z] = new Static3D(x,y,z);
238
              mRotateEffect[x][y][z]    = new MatrixEffectRotate(mRotationAngle[x][y][z], mRotationAxis[x][y][z], matrCenter);
239
240
              mEffects[x][y][z] = new DistortedEffects();
241 27a70eae Leszek Koltunski
              mEffects[x][y][z].apply(mSinkEffect);
242 beb325a0 Leszek Koltunski
              mEffects[x][y][z].apply( new MatrixEffectMove(cubeVectors[x][y][z]) );
243
              mEffects[x][y][z].apply( new MatrixEffectQuaternion(mQuatScramble[x][y][z], matrCenter));
244
              mEffects[x][y][z].apply(mRotateEffect[x][y][z]);
245 27a70eae Leszek Koltunski
              mEffects[x][y][z].apply(mQuatAEffect);
246
              mEffects[x][y][z].apply(mQuatCEffect);
247
              mEffects[x][y][z].apply(mScaleEffect);
248
              mEffects[x][y][z].apply(mMoveEffect);
249 beb325a0 Leszek Koltunski
250
              mNodes[x][y][z] = new DistortedNode(mTexture,mEffects[x][y][z],mCubes[x][y][z]);
251
252
              attach(mNodes[x][y][z]);
253
              }
254
            }
255
      }
256
257 775e675d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
258 27a70eae Leszek Koltunski
// PUBLIC API
259 5bfc1b49 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
260 8e1231ae Leszek Koltunski
// mSize already saved as RubikStatePlay.mButton
261 5bfc1b49 Leszek Koltunski
262
   public void savePreferences(SharedPreferences.Editor editor)
263
     {
264 8e1231ae Leszek Koltunski
     float qx,qy,qz,qw;
265
266
     for(int x=0; x<mSize; x++)
267
        for(int y=0; y<mSize; y++)
268
          for(int z=0; z<mSize; z++)
269
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
270
              {
271
              qx = mQuatScramble[x][y][z].get0();
272
              qy = mQuatScramble[x][y][z].get1();
273
              qz = mQuatScramble[x][y][z].get2();
274
              qw = mQuatScramble[x][y][z].get3();
275
276
              editor.putFloat("qx_"+x+"_"+y+"_"+z, qx);
277
              editor.putFloat("qy_"+x+"_"+y+"_"+z, qy);
278
              editor.putFloat("qz_"+x+"_"+y+"_"+z, qz);
279
              editor.putFloat("qw_"+x+"_"+y+"_"+z, qw);
280
              }
281 5bfc1b49 Leszek Koltunski
     }
282
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284
285
   public void restorePreferences(SharedPreferences preferences)
286
     {
287 8e1231ae Leszek Koltunski
     float qx,qy,qz,qw;
288
289
     for(int x=0; x<mSize; x++)
290
        for(int y=0; y<mSize; y++)
291
          for(int z=0; z<mSize; z++)
292
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
293
              {
294
              qx = preferences.getFloat("qx_"+x+"_"+y+"_"+z, 0.0f);
295
              qy = preferences.getFloat("qy_"+x+"_"+y+"_"+z, 0.0f);
296
              qz = preferences.getFloat("qz_"+x+"_"+y+"_"+z, 0.0f);
297
              qw = preferences.getFloat("qw_"+x+"_"+y+"_"+z, 1.0f);
298
299
              mQuatScramble[x][y][z].set(qx,qy,qz,qw);
300
              modifyCurrentPosition(x, y, z, mQuatScramble[x][y][z]);
301
              }
302 5bfc1b49 Leszek Koltunski
     }
303
304 beb325a0 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
305
306 27a70eae Leszek Koltunski
   public long finishRotationNow(EffectListener listener)
307
     {
308
     boolean first = true;
309
     long effectID=0;
310 434f2f5a Leszek Koltunski
311 27a70eae Leszek Koltunski
     for(int x=0; x<mSize; x++)
312
       for(int y=0; y<mSize; y++)
313
         for(int z=0; z<mSize; z++)
314
           if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
315
             {
316
             if( belongsToRotation(x,y,z,mRotAxis,mRotRow) )
317
               {
318
               if( first )
319
                 {
320
                 first = false;
321
                 mRotateEffect[x][y][z].notifyWhenFinished(listener);
322
                 effectID = mRotateEffect[x][y][z].getID();
323
                 int pointNum = mRotationAngle[x][y][z].getNumPoints();
324
325
                 if( pointNum>=1 )
326
                   {
327
                   float startingAngle = mRotationAngle[x][y][z].getPoint(pointNum-1).get0();
328
                   int nearestAngleInDegrees = computeNearestAngle(startingAngle);
329
                   mRotationAngleStatic.set0(startingAngle);
330
                   mRotationAngleFinal.set0(nearestAngleInDegrees);
331
                   mRotationAngleMiddle.set0( nearestAngleInDegrees + (nearestAngleInDegrees-startingAngle)*0.2f );
332
                   }
333
                 else
334
                   {
335
                   android.util.Log.e("cube", "ERROR finishing rotation!");
336
                   return 0;
337
                   }
338
                 }
339
340
               mRotationAngle[x][y][z].setDuration(POST_ROTATION_MILLISEC);
341
               mRotationAngle[x][y][z].resetToBeginning();
342
               mRotationAngle[x][y][z].removeAll();
343
               mRotationAngle[x][y][z].add(mRotationAngleStatic);
344
               mRotationAngle[x][y][z].add(mRotationAngleMiddle);
345
               mRotationAngle[x][y][z].add(mRotationAngleFinal);
346
               }
347
             }
348
349
     return effectID;
350
     }
351 0c52af30 Leszek Koltunski
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353 beb325a0 Leszek Koltunski
// all DistortedTextures, DistortedNodes, DistortedFramebuffers, DistortedScreens and all types of
354
// Meshes HAVE TO be markedForDeletion when they are no longer needed- otherwise we have a major
355
// memory leak.
356 0c52af30 Leszek Koltunski
357 27a70eae Leszek Koltunski
   public void releaseResources()
358
     {
359
     mTexture.markForDeletion();
360 beb325a0 Leszek Koltunski
361 27a70eae Leszek Koltunski
     for(int x=0; x<mSize; x++)
362
       for(int y=0; y<mSize; y++)
363
         for(int z=0; z<mSize; z++)
364
           {
365
           if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
366
             {
367
             mCubes[x][y][z].markForDeletion();
368
             mNodes[x][y][z].markForDeletion();
369
             }
370
           }
371
     }
372 0c52af30 Leszek Koltunski
373 47ba5ddc Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
374 0c52af30 Leszek Koltunski
375 27a70eae Leszek Koltunski
   public void createTexture()
376
     {
377
     Bitmap bitmap;
378
379
     final int S = 128;
380
     final int W = 3*S;
381
     final int H = 2*S;
382
     final int R = S/10;
383
     final int M = S/20;
384
385
     Paint paint = new Paint();
386
     bitmap = Bitmap.createBitmap(W,H, Bitmap.Config.ARGB_8888);
387
     Canvas canvas = new Canvas(bitmap);
388
389
     paint.setAntiAlias(true);
390
     paint.setTextAlign(Paint.Align.CENTER);
391
     paint.setStyle(Paint.Style.FILL);
392
393
     // 3x2 bitmap = 6 squares:
394
     //
395
     // RED     GREEN   BLUE
396
     // YELLOW  WHITE   BROWN
397
398
     paint.setColor(0xff000000);                                  // BLACK BACKGROUND
399
     canvas.drawRect(0, 0, W, H, paint);                          //
400
401
     paint.setColor(0xffff0000);                                  // RED
402
     canvas.drawRoundRect(    M,   M,   S-M,   S-M, R, R, paint); //
403
     paint.setColor(0xff00ff00);                                  // GREEN
404
     canvas.drawRoundRect(  S+M,   M, 2*S-M,   S-M, R, R, paint); //
405
     paint.setColor(0xff0000ff);                                  // BLUE
406
     canvas.drawRoundRect(2*S+M,   M, 3*S-M,   S-M, R, R, paint); //
407
     paint.setColor(0xffffff00);                                  // YELLOW
408
     canvas.drawRoundRect(    M, S+M,   S-M, 2*S-M, R, R, paint); //
409
     paint.setColor(0xffffffff);                                  // WHITE
410
     canvas.drawRoundRect(  S+M, S+M, 2*S-M, 2*S-M, R, R, paint); //
411
     paint.setColor(0xffb5651d);                                  // BROWN
412
     canvas.drawRoundRect(2*S+M, S+M, 3*S-M, 2*S-M, R, R, paint); //
413
414
     mTexture.setTexture(bitmap);
415
     }
416 0c52af30 Leszek Koltunski
417
///////////////////////////////////////////////////////////////////////////////////////////////////
418
419 27a70eae Leszek Koltunski
   public void apply(Effect effect, int position)
420
     {
421
     for(int x=0; x<mSize; x++)
422
       for(int y=0; y<mSize; y++)
423
         for(int z=0; z<mSize; z++)
424
           {
425
           if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
426
             {
427
             mEffects[x][y][z].apply(effect, position);
428
             }
429
           }
430 0c52af30 Leszek Koltunski
      }
431 47ba5ddc Leszek Koltunski
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433
434 27a70eae Leszek Koltunski
   public void remove(long effectID)
435
     {
436
     for(int x=0; x<mSize; x++)
437
       for(int y=0; y<mSize; y++)
438
         for(int z=0; z<mSize; z++)
439
           {
440
           if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
441
             {
442
             mEffects[x][y][z].abortById(effectID);
443
             }
444
           }
445 47ba5ddc Leszek Koltunski
      }
446
447
///////////////////////////////////////////////////////////////////////////////////////////////////
448
449 27a70eae Leszek Koltunski
   public void solve()
450
     {
451
     for(int x=0; x<mSize; x++)
452
       for(int y=0; y<mSize; y++)
453
         for(int z=0; z<mSize; z++)
454
           if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
455
             {
456
             mQuatScramble[x][y][z].set(0,0,0,1);
457
             mCurrentPosition[x][y][z].set(x,y,z);
458
             }
459 47ba5ddc Leszek Koltunski
      }
460
461
///////////////////////////////////////////////////////////////////////////////////////////////////
462
463 27a70eae Leszek Koltunski
   public boolean isSolved()
464
     {
465
     Static4D q = mQuatScramble[0][0][0];
466
467
     float x = q.get0();
468
     float y = q.get1();
469
     float z = q.get2();
470
     float w = q.get3();
471
472
     for(int i = 0; i< mSize; i++)
473
       for(int j = 0; j< mSize; j++)
474
         for(int k = 0; k< mSize; k++)
475
           {
476
           if( i==0 || i==mSize-1 || j==0 || j==mSize-1 || k==0 || k==mSize-1 )
477
             {
478
             q = mQuatScramble[i][j][k];
479
480
             if( q.get0()!=x || q.get1()!=y || q.get2()!=z || q.get3()!=w )
481
               {
482
               return false;
483
               }
484
             }
485
           }
486
487
     return true;
488
     }
489 47ba5ddc Leszek Koltunski
490 beb325a0 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
491
492 27a70eae Leszek Koltunski
   public void beginNewRotation(int vector, int row )
493
     {
494
     Static3D axis = VectX;
495 beb325a0 Leszek Koltunski
496 27a70eae Leszek Koltunski
     switch(vector)
497
       {
498
       case VECTX: axis = VectX; break;
499
       case VECTY: axis = VectY; break;
500
       case VECTZ: axis = VectZ; break;
501
       }
502 beb325a0 Leszek Koltunski
503 27a70eae Leszek Koltunski
     mRotAxis = vector;
504
     mRotRow  = row;
505 beb325a0 Leszek Koltunski
506 27a70eae Leszek Koltunski
     mRotationAngleStatic.set0(0.0f);
507 47ba5ddc Leszek Koltunski
508 27a70eae Leszek Koltunski
     for(int x=0; x<mSize; x++)
509
       for(int y=0; y<mSize; y++)
510
         for(int z=0; z<mSize; z++)
511
           if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
512
             {
513
             if( belongsToRotation(x,y,z,vector,mRotRow) )
514
               {
515
               mRotationAxis[x][y][z].set(axis);
516
               mRotationAngle[x][y][z].add(mRotationAngleStatic);
517
               }
518
             }
519
     }
520 47ba5ddc Leszek Koltunski
521
///////////////////////////////////////////////////////////////////////////////////////////////////
522
523 27a70eae Leszek Koltunski
   public long addNewRotation(int vector, int row, int angle, long durationMillis, EffectListener listener )
524 47ba5ddc Leszek Koltunski
      {
525
      Static3D axis = VectX;
526
      long effectID=0;
527
      boolean first = true;
528
529
      switch(vector)
530
        {
531
        case VECTX: axis = VectX; break;
532
        case VECTY: axis = VectY; break;
533
        case VECTZ: axis = VectZ; break;
534
        }
535
536
      mRotAxis = vector;
537
      mRotRow  = row;
538
539 348dfe69 Leszek Koltunski
      mRotationAngleStatic.set0(0.0f);
540 47ba5ddc Leszek Koltunski
541
      for(int x=0; x<mSize; x++)
542
        for(int y=0; y<mSize; y++)
543
          for(int z=0; z<mSize; z++)
544
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
545
              {
546
              if( belongsToRotation(x,y,z,vector,mRotRow) )
547
                {
548
                mRotationAxis[x][y][z].set(axis);
549
                mRotationAngle[x][y][z].setDuration(durationMillis);
550
                mRotationAngle[x][y][z].resetToBeginning();
551
                mRotationAngle[x][y][z].add(new Static1D(0));
552
                mRotationAngle[x][y][z].add(new Static1D(angle));
553
554
                if( first )
555
                  {
556
                  first = false;
557
                  effectID = mRotateEffect[x][y][z].getID();
558
                  mRotateEffect[x][y][z].notifyWhenFinished(listener);
559
                  }
560
                }
561
              }
562
563
      return effectID;
564
      }
565
566
///////////////////////////////////////////////////////////////////////////////////////////////////
567
568 27a70eae Leszek Koltunski
   public void removeRotationNow()
569 47ba5ddc Leszek Koltunski
      {
570
      float qx=0,qy=0,qz=0;
571
      boolean first = true;
572
      Static4D quat = null;
573
574
      switch(mRotAxis)
575
        {
576
        case VECTX: qx=1; break;
577
        case VECTY: qy=1; break;
578
        case VECTZ: qz=1; break;
579
        }
580
581
      for(int x=0; x<mSize; x++)
582
        for(int y=0; y<mSize; y++)
583
          for(int z=0; z<mSize; z++)
584
            if( x==0 || x==mSize-1 || y==0 || y==mSize-1 || z==0 || z==mSize-1 )
585
              {
586
              if( belongsToRotation(x,y,z,mRotAxis,mRotRow) )
587
                {
588
                if( first )
589
                  {
590
                  first = false;
591
                  int pointNum = mRotationAngle[x][y][z].getNumPoints();
592
593
                  if( pointNum>=1 )
594
                    {
595 348dfe69 Leszek Koltunski
                    float startingAngle = mRotationAngle[x][y][z].getPoint(pointNum-1).get0();
596 47ba5ddc Leszek Koltunski
                    int nearestAngleInDegrees = computeNearestAngle(startingAngle);
597
                    double nearestAngleInRadians = nearestAngleInDegrees*Math.PI/180;
598
                    float sinA =-(float)Math.sin(nearestAngleInRadians*0.5);
599
                    float cosA = (float)Math.cos(nearestAngleInRadians*0.5);
600
                    quat = new Static4D(qx*sinA, qy*sinA, qz*sinA, cosA);
601
                    }
602
                  else
603
                    {
604
                    android.util.Log.e("cube", "ERROR removing rotation!");
605
                    return;
606
                    }
607
                  }
608
609
                mRotationAngle[x][y][z].removeAll();
610
                mQuatScramble[x][y][z].set(RubikSurfaceView.quatMultiply(quat,mQuatScramble[x][y][z]));
611
                normalizeScrambleQuat(x,y,z);
612
                modifyCurrentPosition(x,y,z,quat);
613
                }
614
              }
615
616 348dfe69 Leszek Koltunski
      mRotationAngleStatic.set0(0);
617 47ba5ddc Leszek Koltunski
      }
618 0c52af30 Leszek Koltunski
}