Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyObject.java @ 516451c4

1 fdec60a3 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 1f9772f3 Leszek Koltunski
package org.distorted.objects;
21 fdec60a3 Leszek Koltunski
22 27a70eae Leszek Koltunski
import android.content.SharedPreferences;
23 ccf9fec5 Leszek Koltunski
import android.content.res.Resources;
24 411c6285 Leszek Koltunski
import android.graphics.Bitmap;
25
import android.graphics.Canvas;
26
import android.graphics.Paint;
27 27a70eae Leszek Koltunski
28 27e6c301 Leszek Koltunski
import com.google.firebase.crashlytics.FirebaseCrashlytics;
29
30 b1f2ccf5 Leszek Koltunski
import org.distorted.helpers.FactoryCubit;
31 27a70eae Leszek Koltunski
import org.distorted.library.effect.Effect;
32 19f0f767 Leszek Koltunski
import org.distorted.library.effect.MatrixEffectMove;
33 27a70eae Leszek Koltunski
import org.distorted.library.effect.MatrixEffectQuaternion;
34
import org.distorted.library.effect.MatrixEffectScale;
35 10585385 Leszek Koltunski
import org.distorted.library.effect.VertexEffectQuaternion;
36 27e6c301 Leszek Koltunski
import org.distorted.library.effect.VertexEffectRotate;
37 27a70eae Leszek Koltunski
import org.distorted.library.main.DistortedEffects;
38 c7e23561 Leszek Koltunski
import org.distorted.library.main.DistortedLibrary;
39 27a70eae Leszek Koltunski
import org.distorted.library.main.DistortedNode;
40
import org.distorted.library.main.DistortedTexture;
41 b32444ee Leszek Koltunski
import org.distorted.library.mesh.MeshBase;
42 ccf9fec5 Leszek Koltunski
import org.distorted.library.mesh.MeshFile;
43 19f0f767 Leszek Koltunski
import org.distorted.library.mesh.MeshJoined;
44 efa8aa48 Leszek Koltunski
import org.distorted.library.mesh.MeshSquare;
45 27a70eae Leszek Koltunski
import org.distorted.library.message.EffectListener;
46 27e6c301 Leszek Koltunski
import org.distorted.library.type.Dynamic1D;
47 27a70eae Leszek Koltunski
import org.distorted.library.type.Static1D;
48
import org.distorted.library.type.Static3D;
49
import org.distorted.library.type.Static4D;
50 25445dcf Leszek Koltunski
import org.distorted.main.BuildConfig;
51 221a4090 Leszek Koltunski
import org.distorted.main.RubikSurfaceView;
52 4f9f99a2 Leszek Koltunski
53 ccf9fec5 Leszek Koltunski
import java.io.DataInputStream;
54
import java.io.IOException;
55
import java.io.InputStream;
56 7c969a6d Leszek Koltunski
import java.util.Random;
57 ccf9fec5 Leszek Koltunski
58 0333d81e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
59
60 9c2f0c91 Leszek Koltunski
public abstract class TwistyObject extends DistortedNode
61 fdec60a3 Leszek Koltunski
  {
62 749ef882 Leszek Koltunski
  public static final int COLOR_YELLOW = 0xffffff00;
63
  public static final int COLOR_WHITE  = 0xffffffff;
64
  public static final int COLOR_BLUE   = 0xff0000ff;
65
  public static final int COLOR_GREEN  = 0xff00bb00;
66
  public static final int COLOR_RED    = 0xff990000;
67
  public static final int COLOR_ORANGE = 0xffff6200;
68
  public static final int COLOR_GREY   = 0xff727c7b;
69
  public static final int COLOR_VIOLET = 0xff7700bb;
70
  public static final int COLOR_BLACK  = 0xff000000;
71 ece1b58d Leszek Koltunski
72 749ef882 Leszek Koltunski
  public static final int TEXTURE_HEIGHT = 256;
73 ae755eda Leszek Koltunski
  static final int NUM_STICKERS_IN_ROW = 4;
74 b89898c5 Leszek Koltunski
75 3f3ff476 Leszek Koltunski
  static final float SQ2 = (float)Math.sqrt(2);
76
  static final float SQ3 = (float)Math.sqrt(3);
77 bbc6da6c Leszek Koltunski
  static final float SQ5 = (float)Math.sqrt(5);
78 3f3ff476 Leszek Koltunski
  static final float SQ6 = (float)Math.sqrt(6);
79
80 ee526fe0 Leszek Koltunski
  private static final float NODE_RATIO = 1.40f;
81
  private static final float MAX_SIZE_CHANGE = 1.35f;
82 81f4fd77 Leszek Koltunski
  private static final float MIN_SIZE_CHANGE = 0.75f;
83 c7b00dfb Leszek Koltunski
84 8cccfb10 Leszek Koltunski
  private static final Static3D CENTER = new Static3D(0,0,0);
85 27e6c301 Leszek Koltunski
  private static final int POST_ROTATION_MILLISEC = 500;
86
87 98904e45 Leszek Koltunski
  final Static4D[] QUATS;
88 6b6504fe Leszek Koltunski
  final Cubit[] CUBITS;
89 470820a7 Leszek Koltunski
  final int NUM_FACES;
90 eab9d8f8 Leszek Koltunski
  final int NUM_TEXTURES;
91 6b6504fe Leszek Koltunski
  final int NUM_CUBITS;
92 582617c1 Leszek Koltunski
  final int NUM_AXIS;
93 27a70eae Leszek Koltunski
94 b30695c6 Leszek Koltunski
  private static float mInitScreenRatio;
95
  private static float mObjectScreenRatio = 1.0f;
96 e6cf7283 Leszek Koltunski
  private static final float[] mTmp1 = new float[4];
97
  private static final float[] mTmp2 = new float[4];
98 f0fa83ae Leszek Koltunski
99 582617c1 Leszek Koltunski
  private final int mNumCubitFaces;
100
  private final Static3D[] mAxis;
101 e6734aa9 Leszek Koltunski
  private final float[][] mCuts;
102
  private final int[] mNumCuts;
103 5b893eee Leszek Koltunski
  private final int mNodeSize;
104 e6cf7283 Leszek Koltunski
  private final float[][] mOrigPos;
105 03aa05d5 Leszek Koltunski
  private final Static3D mNodeScale;
106
  private final Static4D mQuat;
107
  private final int mNumLayers, mRealSize;
108
  private final ObjectList mList;
109
  private final DistortedEffects mEffects;
110
  private final VertexEffectRotate mRotateEffect;
111
  private final Dynamic1D mRotationAngle;
112
  private final Static3D mRotationAxis;
113
  private final Static3D mObjectScale;
114
  private final int[] mQuatDebug;
115 30bc2d91 Leszek Koltunski
  private final float mCameraDist;
116 582617c1 Leszek Koltunski
  private final Static1D mRotationAngleStatic, mRotationAngleMiddle, mRotationAngleFinal;
117
  private final DistortedTexture mTexture;
118 03aa05d5 Leszek Koltunski
  private int mNumTexRows, mNumTexCols;
119 9224ffd2 Leszek Koltunski
  private int mRotRowBitmap;
120 efef689c Leszek Koltunski
  private int mRotAxis;
121 470820a7 Leszek Koltunski
  private MeshBase mMesh;
122 27a70eae Leszek Koltunski
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124 fdec60a3 Leszek Koltunski
125 db875721 Leszek Koltunski
  TwistyObject(int numLayers, int realSize, Static4D quat, DistortedTexture nodeTexture, MeshSquare nodeMesh,
126 9c2f0c91 Leszek Koltunski
               DistortedEffects nodeEffects, int[][] moves, ObjectList list, Resources res, int screenWidth)
127 fdec60a3 Leszek Koltunski
    {
128 411c6285 Leszek Koltunski
    super(nodeTexture,nodeEffects,nodeMesh);
129 fdec60a3 Leszek Koltunski
130 5b893eee Leszek Koltunski
    mNodeSize = screenWidth;
131
132 c7b00dfb Leszek Koltunski
    resizeFBO(mNodeSize, (int)(NODE_RATIO*mNodeSize));
133 d41742f7 Leszek Koltunski
134 d99f3a48 Leszek Koltunski
    mNumLayers = numLayers;
135
    mRealSize = realSize;
136 aa171dee Leszek Koltunski
    mList = list;
137 d99f3a48 Leszek Koltunski
    mOrigPos = getCubitPositions(mNumLayers);
138 582617c1 Leszek Koltunski
    mAxis = getRotationAxis();
139
    mInitScreenRatio = getScreenRatio();
140
    mNumCubitFaces = getNumCubitFaces();
141 e6734aa9 Leszek Koltunski
142 582617c1 Leszek Koltunski
    mCuts = getCuts(mNumLayers);
143 e6734aa9 Leszek Koltunski
    mNumCuts = new int[mAxis.length];
144
    if( mCuts==null ) for(int i=0; i<mAxis.length; i++) mNumCuts[i] = 0;
145
    else              for(int i=0; i<mAxis.length; i++) mNumCuts[i] = mCuts[i].length;
146 10a2e360 Leszek Koltunski
147 98904e45 Leszek Koltunski
    QUATS = getQuats();
148 49f67f9b Leszek Koltunski
    NUM_CUBITS  = mOrigPos.length;
149 470820a7 Leszek Koltunski
    NUM_FACES = getNumFaces();
150 a64e07d0 Leszek Koltunski
    NUM_TEXTURES = getNumStickerTypes(mNumLayers)*NUM_FACES;
151 582617c1 Leszek Koltunski
    NUM_AXIS = mAxis.length;
152 a10ada2a Leszek Koltunski
153 a15078bb Leszek Koltunski
    mQuatDebug = new int[NUM_CUBITS];
154
155 b30695c6 Leszek Koltunski
    if( mObjectScreenRatio>MAX_SIZE_CHANGE) mObjectScreenRatio = MAX_SIZE_CHANGE;
156
    if( mObjectScreenRatio<MIN_SIZE_CHANGE) mObjectScreenRatio = MIN_SIZE_CHANGE;
157
158 c7b00dfb Leszek Koltunski
    mNodeScale= new Static3D(1,NODE_RATIO,1);
159 4da7d87a Leszek Koltunski
    mQuat = quat;
160 e844c116 Leszek Koltunski
161 27e6c301 Leszek Koltunski
    mRotationAngle= new Dynamic1D();
162
    mRotationAxis = new Static3D(1,0,0);
163 8cccfb10 Leszek Koltunski
    mRotateEffect = new VertexEffectRotate(mRotationAngle, mRotationAxis, CENTER);
164 27e6c301 Leszek Koltunski
165 27a70eae Leszek Koltunski
    mRotationAngleStatic = new Static1D(0);
166
    mRotationAngleMiddle = new Static1D(0);
167
    mRotationAngleFinal  = new Static1D(0);
168
169 d99f3a48 Leszek Koltunski
    float scale  = mObjectScreenRatio*mInitScreenRatio*mNodeSize/mRealSize;
170 19f0f767 Leszek Koltunski
    mObjectScale = new Static3D(scale,scale,scale);
171 582617c1 Leszek Koltunski
    MatrixEffectScale scaleEffect = new MatrixEffectScale(mObjectScale);
172
    MatrixEffectQuaternion quatEffect  = new MatrixEffectQuaternion(quat, CENTER);
173 27a70eae Leszek Koltunski
174
    MatrixEffectScale nodeScaleEffect = new MatrixEffectScale(mNodeScale);
175 411c6285 Leszek Koltunski
    nodeEffects.apply(nodeScaleEffect);
176 a10ada2a Leszek Koltunski
177 ae755eda Leszek Koltunski
    mNumTexCols = NUM_STICKERS_IN_ROW;
178
    mNumTexRows = (NUM_TEXTURES+1)/NUM_STICKERS_IN_ROW;
179
180
    if( mNumTexCols*mNumTexRows < NUM_TEXTURES+1 ) mNumTexRows++;
181
182 6b6504fe Leszek Koltunski
    CUBITS = new Cubit[NUM_CUBITS];
183 19f0f767 Leszek Koltunski
    createMeshAndCubits(list,res);
184 7381193e Leszek Koltunski
185 19f0f767 Leszek Koltunski
    mTexture = new DistortedTexture();
186 470820a7 Leszek Koltunski
    mEffects = new DistortedEffects();
187 10585385 Leszek Koltunski
188 98904e45 Leszek Koltunski
    int num_quats = QUATS.length;
189 10585385 Leszek Koltunski
    for(int q=0; q<num_quats; q++)
190
      {
191 98904e45 Leszek Koltunski
      VertexEffectQuaternion vq = new VertexEffectQuaternion(QUATS[q],CENTER);
192 10585385 Leszek Koltunski
      vq.setMeshAssociation(0,q);
193
      mEffects.apply(vq);
194
      }
195
196 27e6c301 Leszek Koltunski
    mEffects.apply(mRotateEffect);
197 582617c1 Leszek Koltunski
    mEffects.apply(quatEffect);
198
    mEffects.apply(scaleEffect);
199 470820a7 Leszek Koltunski
200 dfbb340a Leszek Koltunski
    // Now postprocessed effects (the glow when you solve an object) require component centers. In
201 b376bfd7 Leszek Koltunski
    // order for the effect to be in front of the object, we need to set the center to be behind it.
202 dfbb340a Leszek Koltunski
    getMesh().setComponentCenter(0,0,0,-0.1f);
203
204 470820a7 Leszek Koltunski
    attach( new DistortedNode(mTexture,mEffects,mMesh) );
205
206 aa171dee Leszek Koltunski
    setupPosition(moves);
207
208 30bc2d91 Leszek Koltunski
    float fov = list.getFOV();
209
    double halfFOV = fov * (Math.PI/360);
210
    mCameraDist = 0.5f*NODE_RATIO / (float)Math.tan(halfFOV);
211
212
    setProjection( fov, 0.1f);
213 27a70eae Leszek Koltunski
    }
214
215 e6cf7283 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
216
217
  private Static3D getPos(float[] origPos)
218
    {
219
    int len = origPos.length/3;
220
    float sumX = 0.0f;
221
    float sumY = 0.0f;
222
    float sumZ = 0.0f;
223
224
    for(int i=0; i<len; i++)
225
      {
226
      sumX += origPos[3*i  ];
227
      sumY += origPos[3*i+1];
228
      sumZ += origPos[3*i+2];
229
      }
230
231
    sumX /= len;
232
    sumY /= len;
233
    sumZ /= len;
234
235
    return new Static3D(sumX,sumY,sumZ);
236
    }
237
238 19f0f767 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
239
240 9c2f0c91 Leszek Koltunski
  private void createMeshAndCubits(ObjectList list, Resources res)
241 19f0f767 Leszek Koltunski
    {
242 c494476f Leszek Koltunski
    int sizeIndex = ObjectList.getSizeIndex(list.ordinal(),mNumLayers);
243
    int resourceID= list.getResourceIDs()[sizeIndex];
244 19f0f767 Leszek Koltunski
245 c494476f Leszek Koltunski
    if( resourceID!=0 )
246
      {
247 19f0f767 Leszek Koltunski
      InputStream is = res.openRawResource(resourceID);
248
      DataInputStream dos = new DataInputStream(is);
249
      mMesh = new MeshFile(dos);
250
251
      try
252
        {
253
        is.close();
254
        }
255
      catch(IOException e)
256
        {
257
        android.util.Log.e("meshFile", "Error closing InputStream: "+e.toString());
258
        }
259
260
      for(int i=0; i<NUM_CUBITS; i++)
261
        {
262 582617c1 Leszek Koltunski
        CUBITS[i] = new Cubit(this,mOrigPos[i], NUM_AXIS);
263 6b6504fe Leszek Koltunski
        mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(), 0);
264 19f0f767 Leszek Koltunski
        }
265 eaee1ddc Leszek Koltunski
266
      if( shouldResetTextureMaps() ) resetAllTextureMaps();
267 19f0f767 Leszek Koltunski
      }
268
    else
269
      {
270
      MeshBase[] cubitMesh = new MeshBase[NUM_CUBITS];
271
272
      for(int i=0; i<NUM_CUBITS; i++)
273
        {
274 582617c1 Leszek Koltunski
        CUBITS[i] = new Cubit(this,mOrigPos[i], NUM_AXIS);
275 a64e07d0 Leszek Koltunski
        cubitMesh[i] = createCubitMesh(i,mNumLayers);
276 e6cf7283 Leszek Koltunski
        Static3D pos = getPos(mOrigPos[i]);
277
        cubitMesh[i].apply(new MatrixEffectMove(pos),1,0);
278 6b6504fe Leszek Koltunski
        cubitMesh[i].setEffectAssociation(0, CUBITS[i].computeAssociation(), 0);
279 19f0f767 Leszek Koltunski
        }
280
281
      mMesh = new MeshJoined(cubitMesh);
282
      resetAllTextureMaps();
283
      }
284
    }
285
286 c7b00dfb Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
287
288
  public void setObjectRatio(float sizeChange)
289
    {
290
    mObjectScreenRatio *= (1.0f+sizeChange)/2;
291
292 b30695c6 Leszek Koltunski
    if( mObjectScreenRatio>MAX_SIZE_CHANGE) mObjectScreenRatio = MAX_SIZE_CHANGE;
293
    if( mObjectScreenRatio<MIN_SIZE_CHANGE) mObjectScreenRatio = MIN_SIZE_CHANGE;
294 c7b00dfb Leszek Koltunski
295 d99f3a48 Leszek Koltunski
    float scale = mObjectScreenRatio*mInitScreenRatio*mNodeSize/mRealSize;
296 c7b00dfb Leszek Koltunski
    mObjectScale.set(scale,scale,scale);
297
    }
298
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300
301
  static float getObjectRatio()
302
    {
303 b30695c6 Leszek Koltunski
    return mObjectScreenRatio*mInitScreenRatio;
304 c7b00dfb Leszek Koltunski
    }
305
306 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
307
308 e6734aa9 Leszek Koltunski
  int computeRow(float[] pos, int axisIndex)
309 e844c116 Leszek Koltunski
    {
310 e6cf7283 Leszek Koltunski
    int ret=0;
311
    int len = pos.length / 3;
312 e6734aa9 Leszek Koltunski
    Static3D axis = mAxis[axisIndex];
313 e6cf7283 Leszek Koltunski
    float axisX = axis.get0();
314
    float axisY = axis.get1();
315
    float axisZ = axis.get2();
316 e6734aa9 Leszek Koltunski
    float casted;
317 e6cf7283 Leszek Koltunski
318
    for(int i=0; i<len; i++)
319
      {
320 e6734aa9 Leszek Koltunski
      casted = pos[3*i]*axisX + pos[3*i+1]*axisY + pos[3*i+2]*axisZ;
321
      ret |= computeSingleRow(axisIndex,casted);
322 e6cf7283 Leszek Koltunski
      }
323
324
    return ret;
325
    }
326
327
///////////////////////////////////////////////////////////////////////////////////////////////////
328 e844c116 Leszek Koltunski
329 e6734aa9 Leszek Koltunski
  private int computeSingleRow(int axisIndex,float casted)
330 e6cf7283 Leszek Koltunski
    {
331 e6734aa9 Leszek Koltunski
    int num = mNumCuts[axisIndex];
332
333
    for(int i=0; i<num; i++)
334 e844c116 Leszek Koltunski
      {
335 e6734aa9 Leszek Koltunski
      if( casted<mCuts[axisIndex][i] ) return (1<<i);
336 e844c116 Leszek Koltunski
      }
337
338 e6734aa9 Leszek Koltunski
    return (1<<num);
339 e844c116 Leszek Koltunski
    }
340
341 985f3dfa Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
342
343
  private boolean wasRotateApplied()
344
    {
345
    return mEffects.exists(mRotateEffect.getID());
346
    }
347
348 efef689c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
349
350 9224ffd2 Leszek Koltunski
  private boolean belongsToRotation( int cubit, int axis, int rowBitmap)
351 efef689c Leszek Koltunski
    {
352 f0450fcc Leszek Koltunski
    return (CUBITS[cubit].mRotationRow[axis] & rowBitmap) != 0;
353 66cbdd21 Leszek Koltunski
    }
354
355 aa171dee Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
356 a31d25de Leszek Koltunski
// note the minus in front of the sin() - we rotate counterclockwise
357
// when looking towards the direction where the axis increases in values.
358 aa171dee Leszek Koltunski
359 a31d25de Leszek Koltunski
  private Static4D makeQuaternion(int axisIndex, int angleInDegrees)
360 aa171dee Leszek Koltunski
    {
361 582617c1 Leszek Koltunski
    Static3D axis = mAxis[axisIndex];
362 a31d25de Leszek Koltunski
363
    while( angleInDegrees<0 ) angleInDegrees += 360;
364
    angleInDegrees %= 360;
365
    
366
    float cosA = (float)Math.cos(Math.PI*angleInDegrees/360);
367
    float sinA =-(float)Math.sqrt(1-cosA*cosA);
368
369
    return new Static4D(axis.get0()*sinA, axis.get1()*sinA, axis.get2()*sinA, cosA);
370
    }
371
372
///////////////////////////////////////////////////////////////////////////////////////////////////
373
374 8bbac3c2 Leszek Koltunski
  private synchronized void setupPosition(int[][] moves)
375 a31d25de Leszek Koltunski
    {
376
    if( moves!=null )
377
      {
378
      Static4D quat;
379 818431ed Leszek Koltunski
      int index, axis, rowBitmap, angle;
380 925ed78f Leszek Koltunski
      int[] basic = getBasicAngle();
381 a31d25de Leszek Koltunski
382
      for(int[] move: moves)
383
        {
384
        axis     = move[0];
385
        rowBitmap= move[1];
386 925ed78f Leszek Koltunski
        angle    = move[2]*(360/basic[axis]);
387 a31d25de Leszek Koltunski
        quat     = makeQuaternion(axis,angle);
388
389
        for(int j=0; j<NUM_CUBITS; j++)
390
          if( belongsToRotation(j,axis,rowBitmap) )
391
            {
392 6b6504fe Leszek Koltunski
            index = CUBITS[j].removeRotationNow(quat);
393
            mMesh.setEffectAssociation(j, CUBITS[j].computeAssociation(),index);
394 a31d25de Leszek Koltunski
            }
395
        }
396
      }
397 aa171dee Leszek Koltunski
    }
398
399 fa0f7a56 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
400
401
  int getCubitFaceColorIndex(int cubit, int face)
402
    {
403 470820a7 Leszek Koltunski
    Static4D texMap = mMesh.getTextureMap(NUM_FACES*cubit + face);
404 064ccc31 Leszek Koltunski
405
    int x = (int)(texMap.get0()/texMap.get2());
406
    int y = (int)(texMap.get1()/texMap.get3());
407
408
    return (mNumTexRows-1-y)*NUM_STICKERS_IN_ROW + x;
409 fa0f7a56 Leszek Koltunski
    }
410
411 ce366b42 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
412
// normal, not bandaged, object.
413
414
  int computeBitmapFromRow(int rowBitmap, int axis)
415
    {
416
    return rowBitmap;
417
    }
418
419 49f67f9b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
420
// Clamp all rotated positions to one of those original ones to avoid accumulating errors.
421 f20119c6 Leszek Koltunski
// Do so only if minimal Error is appropriately low (shape-shifting puzzles - Square-1)
422 49f67f9b Leszek Koltunski
423 e6cf7283 Leszek Koltunski
  void clampPos(float[] pos, int offset)
424 49f67f9b Leszek Koltunski
    {
425
    float currError, minError = Float.MAX_VALUE;
426 e6cf7283 Leszek Koltunski
    int minErrorIndex1 = -1;
427
    int minErrorIndex2 = -1;
428
429
    float x = pos[offset  ];
430
    float y = pos[offset+1];
431
    float z = pos[offset+2];
432
433 49f67f9b Leszek Koltunski
    float xo,yo,zo;
434
435
    for(int i=0; i<NUM_CUBITS; i++)
436
      {
437 e6cf7283 Leszek Koltunski
      int len = mOrigPos[i].length / 3;
438 49f67f9b Leszek Koltunski
439 e6cf7283 Leszek Koltunski
      for(int j=0; j<len; j++)
440 49f67f9b Leszek Koltunski
        {
441 e6cf7283 Leszek Koltunski
        xo = mOrigPos[i][3*j  ];
442
        yo = mOrigPos[i][3*j+1];
443
        zo = mOrigPos[i][3*j+2];
444
445
        currError = (xo-x)*(xo-x) + (yo-y)*(yo-y) + (zo-z)*(zo-z);
446
447
        if( currError<minError )
448
          {
449
          minError = currError;
450
          minErrorIndex1 = i;
451
          minErrorIndex2 = j;
452
          }
453 49f67f9b Leszek Koltunski
        }
454
      }
455
456 f20119c6 Leszek Koltunski
    if( minError< 0.1f ) // TODO: 0.1 ?
457 43889e94 Leszek Koltunski
      {
458
      pos[offset  ] = mOrigPos[minErrorIndex1][3*minErrorIndex2  ];
459
      pos[offset+1] = mOrigPos[minErrorIndex1][3*minErrorIndex2+1];
460
      pos[offset+2] = mOrigPos[minErrorIndex1][3*minErrorIndex2+2];
461
      }
462 49f67f9b Leszek Koltunski
    }
463
464 cb137f36 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
465
// remember about the double cover or unit quaternions!
466
467
  int mulQuat(int q1, int q2)
468
    {
469
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
470
471
    float rX = result.get0();
472
    float rY = result.get1();
473
    float rZ = result.get2();
474
    float rW = result.get3();
475
476
    final float MAX_ERROR = 0.1f;
477
    float dX,dY,dZ,dW;
478
479
    for(int i=0; i<QUATS.length; i++)
480
      {
481
      dX = QUATS[i].get0() - rX;
482
      dY = QUATS[i].get1() - rY;
483
      dZ = QUATS[i].get2() - rZ;
484
      dW = QUATS[i].get3() - rW;
485
486
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
487
          dY<MAX_ERROR && dY>-MAX_ERROR &&
488
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
489
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
490
491
      dX = QUATS[i].get0() + rX;
492
      dY = QUATS[i].get1() + rY;
493
      dZ = QUATS[i].get2() + rZ;
494
      dW = QUATS[i].get3() + rW;
495
496
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
497
          dY<MAX_ERROR && dY>-MAX_ERROR &&
498
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
499
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
500
      }
501
502
    return -1;
503
    }
504
505 221a4090 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
506
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different
507
// then if it were rotated by quaternion 'quat'.
508
// No it is not so simple as the quats need to be the same - imagine a 4x4x4 cube where the two
509
// middle squares get interchanged. No visible difference!
510
//
511
// So: this is true iff the cubit
512
// a) is a corner or edge and the quaternions are the same
513
// b) is inside one of the faces and after rotations by both quats it ends up on the same face.
514
515 722b2512 Leszek Koltunski
  boolean thereIsVisibleDifference(Cubit cubit, int quatIndex)
516 221a4090 Leszek Koltunski
    {
517 722b2512 Leszek Koltunski
    if ( cubit.mQuatIndex == quatIndex ) return false;
518 221a4090 Leszek Koltunski
519
    int belongsToHowManyFaces = 0;
520 f0450fcc Leszek Koltunski
    int bitmap = (1<<(getNumLayers()-1)) + 1;
521 221a4090 Leszek Koltunski
522 582617c1 Leszek Koltunski
    for(int i = 0; i< NUM_AXIS; i++)
523 221a4090 Leszek Koltunski
      {
524 f0450fcc Leszek Koltunski
      if( (cubit.mRotationRow[i] & bitmap) != 0 ) belongsToHowManyFaces++;
525 221a4090 Leszek Koltunski
      }
526
527
    switch(belongsToHowManyFaces)
528
      {
529 722b2512 Leszek Koltunski
      case 0 : return false;  // 'inside' cubit that does not lie on any face
530 221a4090 Leszek Koltunski
      case 1 :                // cubit that lies inside one of the faces
531 e6cf7283 Leszek Koltunski
               float[] orig   = cubit.getOrigPosition();
532 221a4090 Leszek Koltunski
               Static4D quat1 = QUATS[quatIndex];
533
               Static4D quat2 = QUATS[cubit.mQuatIndex];
534
535 e6cf7283 Leszek Koltunski
               Static4D cubitCenter = new Static4D( orig[0], orig[1], orig[2], 0);              // not used for bandaged objects,
536
               Static4D rotated1 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat1 );   // only check the first position
537 221a4090 Leszek Koltunski
               Static4D rotated2 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat2 );
538
539 e6cf7283 Leszek Koltunski
               rotated1.get(mTmp1, 0, 0, 0);
540
               rotated2.get(mTmp2, 0, 0, 0);
541 221a4090 Leszek Koltunski
542 582617c1 Leszek Koltunski
               for(int i = 0; i< NUM_AXIS; i++)
543 221a4090 Leszek Koltunski
                 {
544 e6cf7283 Leszek Koltunski
                 if( (computeRow(mTmp1,i) & computeRow(mTmp2,i) & bitmap) != 0 ) return false;
545 221a4090 Leszek Koltunski
                 }
546 722b2512 Leszek Koltunski
               return true;
547 221a4090 Leszek Koltunski
548 722b2512 Leszek Koltunski
      default: return true;  // edge or corner
549 221a4090 Leszek Koltunski
      }
550
    }
551
552 b1f2ccf5 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
553
// create StickerCoord and FaceTransform data structures
554
555 7d8cc029 Leszek Koltunski
  void createFaceDataStructures(double[][][] verts, int[][][] indices)
556 b1f2ccf5 Leszek Koltunski
    {
557 7d8cc029 Leszek Koltunski
    int numCubitTypes = verts.length;
558 b1f2ccf5 Leszek Koltunski
    FactoryCubit factory = FactoryCubit.getInstance();
559
    factory.clear();
560
561
    for(int cubit=0; cubit<numCubitTypes; cubit++)
562
      {
563 7d8cc029 Leszek Koltunski
      double[][] vertices = verts[cubit];
564
      int[][] vertIndices = indices[cubit];
565 b1f2ccf5 Leszek Koltunski
      factory.createNewFaceTransform(vertices,vertIndices);
566
      }
567
568 31cd7256 Leszek Koltunski
    factory.printFaceTransform();
569 b1f2ccf5 Leszek Koltunski
    factory.printStickerCoords();
570
    }
571
572 411c6285 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
573 ae755eda Leszek Koltunski
// the getFaceColors + final black in a grid (so that we do not exceed the maximum texture size)
574 411c6285 Leszek Koltunski
575
  public void createTexture()
576
    {
577
    Bitmap bitmap;
578
579
    Paint paint = new Paint();
580 ae755eda Leszek Koltunski
    bitmap = Bitmap.createBitmap( mNumTexCols*TEXTURE_HEIGHT, mNumTexRows*TEXTURE_HEIGHT, Bitmap.Config.ARGB_8888);
581 411c6285 Leszek Koltunski
    Canvas canvas = new Canvas(bitmap);
582
583
    paint.setAntiAlias(true);
584
    paint.setTextAlign(Paint.Align.CENTER);
585
    paint.setStyle(Paint.Style.FILL);
586
587 ee526fe0 Leszek Koltunski
    paint.setColor(COLOR_BLACK);
588 ae755eda Leszek Koltunski
    canvas.drawRect(0, 0, mNumTexCols*TEXTURE_HEIGHT, mNumTexRows*TEXTURE_HEIGHT, paint);
589 411c6285 Leszek Koltunski
590 ae755eda Leszek Koltunski
    int tex = 0;
591
592
    for(int row=0; row<mNumTexRows; row++)
593
      for(int col=0; col<mNumTexCols; col++)
594
        {
595
        if( tex>=NUM_TEXTURES ) break;
596
        createFaceTexture(canvas, paint, tex, col*TEXTURE_HEIGHT, row*TEXTURE_HEIGHT);
597
        tex++;
598
        }
599 411c6285 Leszek Koltunski
600 c7e23561 Leszek Koltunski
    if( !mTexture.setTexture(bitmap) )
601
      {
602
      int max = DistortedLibrary.getMaxTextureSize();
603
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
604
      crashlytics.log("failed to set texture of size "+bitmap.getWidth()+"x"+bitmap.getHeight()+" max is "+max);
605
      }
606 411c6285 Leszek Koltunski
    }
607
608 dd73fdab Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
609
610 d99f3a48 Leszek Koltunski
  public int getNumLayers()
611 fdec60a3 Leszek Koltunski
    {
612 d99f3a48 Leszek Koltunski
    return mNumLayers;
613 fdec60a3 Leszek Koltunski
    }
614
615
///////////////////////////////////////////////////////////////////////////////////////////////////
616
617 27a70eae Leszek Koltunski
  public void continueRotation(float angleInDegrees)
618 fdec60a3 Leszek Koltunski
    {
619 27a70eae Leszek Koltunski
    mRotationAngleStatic.set0(angleInDegrees);
620 fdec60a3 Leszek Koltunski
    }
621
622
///////////////////////////////////////////////////////////////////////////////////////////////////
623
624 27a70eae Leszek Koltunski
  public Static4D getRotationQuat()
625
      {
626 4da7d87a Leszek Koltunski
      return mQuat;
627 27a70eae Leszek Koltunski
      }
628
629
///////////////////////////////////////////////////////////////////////////////////////////////////
630
631 f18e8fae Leszek Koltunski
  public void recomputeScaleFactor(int scrWidth)
632 fdec60a3 Leszek Koltunski
    {
633 3717a94e Leszek Koltunski
    mNodeScale.set(scrWidth,NODE_RATIO*scrWidth,scrWidth);
634 fdec60a3 Leszek Koltunski
    }
635 27a70eae Leszek Koltunski
636
///////////////////////////////////////////////////////////////////////////////////////////////////
637
638 a10ada2a Leszek Koltunski
  public void savePreferences(SharedPreferences.Editor editor)
639
    {
640 6b6504fe Leszek Koltunski
    for(int i=0; i<NUM_CUBITS; i++) CUBITS[i].savePreferences(editor);
641 a10ada2a Leszek Koltunski
    }
642 f16ff19d Leszek Koltunski
643 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
644 27a70eae Leszek Koltunski
645 8bbac3c2 Leszek Koltunski
  public synchronized void restorePreferences(SharedPreferences preferences)
646 a10ada2a Leszek Koltunski
    {
647 fc3c5170 Leszek Koltunski
    boolean error = false;
648
649 2fcad75d Leszek Koltunski
    for(int i=0; i<NUM_CUBITS; i++)
650
      {
651 a15078bb Leszek Koltunski
      mQuatDebug[i] = CUBITS[i].restorePreferences(preferences);
652 1d6c1eea Leszek Koltunski
653 fc3c5170 Leszek Koltunski
      if( mQuatDebug[i]>=0 && mQuatDebug[i]<QUATS.length)
654 1d6c1eea Leszek Koltunski
        {
655 fc3c5170 Leszek Koltunski
        CUBITS[i].modifyCurrentPosition(QUATS[mQuatDebug[i]]);
656
        mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(),mQuatDebug[i]);
657
        }
658
      else
659
        {
660
        error = true;
661 1d6c1eea Leszek Koltunski
        }
662 fc3c5170 Leszek Koltunski
      }
663 1d6c1eea Leszek Koltunski
664 fc3c5170 Leszek Koltunski
    if( error )
665
      {
666
      for(int i=0; i<NUM_CUBITS; i++)
667
        {
668
        CUBITS[i].solve();
669
        mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(),0);
670
        }
671
      recordQuatsState("Failed to restorePreferences");
672 a15078bb Leszek Koltunski
      }
673
    }
674
675
///////////////////////////////////////////////////////////////////////////////////////////////////
676
677
  public void recordQuatsState(String message)
678
    {
679
    StringBuilder quats = new StringBuilder();
680
681
    for(int j=0; j<NUM_CUBITS; j++)
682
      {
683
      quats.append(mQuatDebug[j]);
684
      quats.append(" ");
685 2fcad75d Leszek Koltunski
      }
686 a15078bb Leszek Koltunski
687 25445dcf Leszek Koltunski
    if( BuildConfig.DEBUG )
688
      {
689 2d9d9d62 Leszek Koltunski
      android.util.Log.e("quats" , quats.toString());
690 25445dcf Leszek Koltunski
      android.util.Log.e("object", mList.name()+"_"+mNumLayers);
691
      }
692
    else
693
      {
694
      Exception ex = new Exception(message);
695
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
696
      crashlytics.setCustomKey("quats" , quats.toString());
697
      crashlytics.setCustomKey("object", mList.name()+"_"+mNumLayers );
698
      crashlytics.recordException(ex);
699
      }
700 a10ada2a Leszek Koltunski
    }
701 27a70eae Leszek Koltunski
702 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
703
704
  public void releaseResources()
705
    {
706
    mTexture.markForDeletion();
707 54342a21 Leszek Koltunski
    mMesh.markForDeletion();
708
    mEffects.markForDeletion();
709
710
    for(int j=0; j<NUM_CUBITS; j++)
711
      {
712
      CUBITS[j].releaseResources();
713
      }
714 a10ada2a Leszek Koltunski
    }
715
716
///////////////////////////////////////////////////////////////////////////////////////////////////
717
718
  public void apply(Effect effect, int position)
719
    {
720 8cccfb10 Leszek Koltunski
    mEffects.apply(effect, position);
721 a10ada2a Leszek Koltunski
    }
722
723
///////////////////////////////////////////////////////////////////////////////////////////////////
724
725
  public void remove(long effectID)
726
    {
727 8cccfb10 Leszek Koltunski
    mEffects.abortById(effectID);
728 a10ada2a Leszek Koltunski
    }
729 74686c71 Leszek Koltunski
730 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
731
732 8bbac3c2 Leszek Koltunski
  public synchronized void solve()
733 a10ada2a Leszek Koltunski
    {
734 98904e45 Leszek Koltunski
    for(int i=0; i<NUM_CUBITS; i++)
735
      {
736 6b6504fe Leszek Koltunski
      CUBITS[i].solve();
737
      mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(), 0);
738 a10ada2a Leszek Koltunski
      }
739
    }
740
741 1f9772f3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
742
743
  public void resetAllTextureMaps()
744
    {
745 ae755eda Leszek Koltunski
    final float ratioW = 1.0f/mNumTexCols;
746
    final float ratioH = 1.0f/mNumTexRows;
747
    int color, row, col;
748 380162cb Leszek Koltunski
749 ad73edd5 Leszek Koltunski
    for(int cubit=0; cubit<NUM_CUBITS; cubit++)
750 1f9772f3 Leszek Koltunski
      {
751 582617c1 Leszek Koltunski
      final Static4D[] maps = new Static4D[mNumCubitFaces];
752 ad73edd5 Leszek Koltunski
753 582617c1 Leszek Koltunski
      for(int cubitface=0; cubitface<mNumCubitFaces; cubitface++)
754 ad73edd5 Leszek Koltunski
        {
755 d99f3a48 Leszek Koltunski
        color = getFaceColor(cubit,cubitface,mNumLayers);
756 ae755eda Leszek Koltunski
        row = (mNumTexRows-1) - color/mNumTexCols;
757
        col = color%mNumTexCols;
758
        maps[cubitface] = new Static4D( col*ratioW, row*ratioH, ratioW, ratioH);
759 ad73edd5 Leszek Koltunski
        }
760
761 582617c1 Leszek Koltunski
      mMesh.setTextureMap(maps,mNumCubitFaces*cubit);
762 1f9772f3 Leszek Koltunski
      }
763
    }
764
765
///////////////////////////////////////////////////////////////////////////////////////////////////
766
767
  public void setTextureMap(int cubit, int face, int newColor)
768
    {
769 064ccc31 Leszek Koltunski
    final float ratioW = 1.0f/mNumTexCols;
770
    final float ratioH = 1.0f/mNumTexRows;
771 582617c1 Leszek Koltunski
    final Static4D[] maps = new Static4D[mNumCubitFaces];
772 064ccc31 Leszek Koltunski
    int row = (mNumTexRows-1) - newColor/mNumTexCols;
773
    int col = newColor%mNumTexCols;
774 1f9772f3 Leszek Koltunski
775 064ccc31 Leszek Koltunski
    maps[face] = new Static4D( col*ratioW, row*ratioH, ratioW, ratioH);
776 582617c1 Leszek Koltunski
    mMesh.setTextureMap(maps,mNumCubitFaces*cubit);
777 1f9772f3 Leszek Koltunski
    }
778
779 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
780
781 8bbac3c2 Leszek Koltunski
  public synchronized void beginNewRotation(int axis, int row )
782 a10ada2a Leszek Koltunski
    {
783 582617c1 Leszek Koltunski
    if( axis<0 || axis>=NUM_AXIS )
784 9cd7695f Leszek Koltunski
      {
785
      android.util.Log.e("object", "invalid rotation axis: "+axis);
786
      return;
787
      }
788 d99f3a48 Leszek Koltunski
    if( row<0 || row>=mNumLayers )
789 9cd7695f Leszek Koltunski
      {
790
      android.util.Log.e("object", "invalid rotation row: "+row);
791
      return;
792
      }
793
794 27e6c301 Leszek Koltunski
    mRotAxis     = axis;
795 ce366b42 Leszek Koltunski
    mRotRowBitmap= computeBitmapFromRow( (1<<row),axis );
796 a10ada2a Leszek Koltunski
    mRotationAngleStatic.set0(0.0f);
797 582617c1 Leszek Koltunski
    mRotationAxis.set( mAxis[axis] );
798 27e6c301 Leszek Koltunski
    mRotationAngle.add(mRotationAngleStatic);
799 9c2f0c91 Leszek Koltunski
    mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis* ObjectList.MAX_OBJECT_SIZE) , -1);
800 27e6c301 Leszek Koltunski
    }
801 a10ada2a Leszek Koltunski
802
///////////////////////////////////////////////////////////////////////////////////////////////////
803
804 8bbac3c2 Leszek Koltunski
  public synchronized long addNewRotation( int axis, int rowBitmap, int angle, long durationMillis, EffectListener listener )
805 27e6c301 Leszek Koltunski
    {
806 985f3dfa Leszek Koltunski
    if( wasRotateApplied() )
807
      {
808
      mRotAxis     = axis;
809 ce366b42 Leszek Koltunski
      mRotRowBitmap= computeBitmapFromRow( rowBitmap,axis );
810 985f3dfa Leszek Koltunski
811
      mRotationAngleStatic.set0(0.0f);
812 582617c1 Leszek Koltunski
      mRotationAxis.set( mAxis[axis] );
813 985f3dfa Leszek Koltunski
      mRotationAngle.setDuration(durationMillis);
814
      mRotationAngle.resetToBeginning();
815
      mRotationAngle.add(new Static1D(0));
816
      mRotationAngle.add(new Static1D(angle));
817
      mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis* ObjectList.MAX_OBJECT_SIZE) , -1);
818
      mRotateEffect.notifyWhenFinished(listener);
819
820
      return mRotateEffect.getID();
821
      }
822 27e6c301 Leszek Koltunski
823 985f3dfa Leszek Koltunski
    return 0;
824 27e6c301 Leszek Koltunski
    }
825 a10ada2a Leszek Koltunski
826 27e6c301 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
827 a10ada2a Leszek Koltunski
828 168b6b56 Leszek Koltunski
  public long finishRotationNow(EffectListener listener, int nearestAngleInDegrees)
829 27e6c301 Leszek Koltunski
    {
830 985f3dfa Leszek Koltunski
    if( wasRotateApplied() )
831
      {
832
      float angle = getAngle();
833
      mRotationAngleStatic.set0(angle);
834
      mRotationAngleFinal.set0(nearestAngleInDegrees);
835
      mRotationAngleMiddle.set0( nearestAngleInDegrees + (nearestAngleInDegrees-angle)*0.2f );
836
837
      mRotationAngle.setDuration(POST_ROTATION_MILLISEC);
838
      mRotationAngle.resetToBeginning();
839
      mRotationAngle.removeAll();
840
      mRotationAngle.add(mRotationAngleStatic);
841
      mRotationAngle.add(mRotationAngleMiddle);
842
      mRotationAngle.add(mRotationAngleFinal);
843
      mRotateEffect.notifyWhenFinished(listener);
844
845
      return mRotateEffect.getID();
846
      }
847 27e6c301 Leszek Koltunski
848 985f3dfa Leszek Koltunski
    return 0;
849 27e6c301 Leszek Koltunski
    }
850 001cc0e4 Leszek Koltunski
851
///////////////////////////////////////////////////////////////////////////////////////////////////
852
853 27e6c301 Leszek Koltunski
  private float getAngle()
854 001cc0e4 Leszek Koltunski
    {
855 27e6c301 Leszek Koltunski
    int pointNum = mRotationAngle.getNumPoints();
856 001cc0e4 Leszek Koltunski
857 27e6c301 Leszek Koltunski
    if( pointNum>=1 )
858 001cc0e4 Leszek Koltunski
      {
859 27e6c301 Leszek Koltunski
      return mRotationAngle.getPoint(pointNum-1).get0();
860
      }
861
    else
862
      {
863
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
864
      crashlytics.log("points in RotationAngle: "+pointNum);
865
      return 0;
866 001cc0e4 Leszek Koltunski
      }
867
    }
868
869 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
870
871 8bbac3c2 Leszek Koltunski
  public synchronized void removeRotationNow()
872 168b6b56 Leszek Koltunski
    {
873
    float angle = getAngle();
874
    double nearestAngleInRadians = angle*Math.PI/180;
875
    float sinA =-(float)Math.sin(nearestAngleInRadians*0.5);
876
    float cosA = (float)Math.cos(nearestAngleInRadians*0.5);
877 582617c1 Leszek Koltunski
    float axisX = mAxis[mRotAxis].get0();
878
    float axisY = mAxis[mRotAxis].get1();
879
    float axisZ = mAxis[mRotAxis].get2();
880 168b6b56 Leszek Koltunski
    Static4D quat = new Static4D( axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
881
882
    mRotationAngle.removeAll();
883
    mRotationAngleStatic.set0(0);
884
885
    for(int i=0; i<NUM_CUBITS; i++)
886
      if( belongsToRotation(i,mRotAxis,mRotRowBitmap) )
887
        {
888 6b6504fe Leszek Koltunski
        int index = CUBITS[i].removeRotationNow(quat);
889
        mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(),index);
890 168b6b56 Leszek Koltunski
        }
891
    }
892 a10ada2a Leszek Koltunski
893 aa171dee Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
894
895 a31d25de Leszek Koltunski
  public void initializeObject(int[][] moves)
896 aa171dee Leszek Koltunski
    {
897
    solve();
898
    setupPosition(moves);
899
    }
900
901 9621255f Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
902
903
  public int getCubit(float[] point3D)
904
    {
905 418aa554 Leszek Koltunski
    float dist, minDist = Float.MAX_VALUE;
906 9621255f Leszek Koltunski
    int currentBest=-1;
907
    float multiplier = returnMultiplier();
908
909
    point3D[0] *= multiplier;
910
    point3D[1] *= multiplier;
911
    point3D[2] *= multiplier;
912
913
    for(int i=0; i<NUM_CUBITS; i++)
914
      {
915 6b6504fe Leszek Koltunski
      dist = CUBITS[i].getDistSquared(point3D);
916 9621255f Leszek Koltunski
      if( dist<minDist )
917
        {
918
        minDist = dist;
919
        currentBest = i;
920
        }
921
      }
922
923
    return currentBest;
924
    }
925
926 0e5ad27c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
927
928 925ed78f Leszek Koltunski
  public int computeNearestAngle(int axis, float angle, float speed)
929 0e5ad27c Leszek Koltunski
    {
930 925ed78f Leszek Koltunski
    final int NEAREST = 360/getBasicAngle()[axis];
931 0e5ad27c Leszek Koltunski
932 4c864c68 Leszek Koltunski
    int tmp = (int)((angle+NEAREST/2)/NEAREST);
933
    if( angle< -(NEAREST*0.5) ) tmp-=1;
934 168b6b56 Leszek Koltunski
935 4c864c68 Leszek Koltunski
    if( tmp!=0 ) return NEAREST*tmp;
936 168b6b56 Leszek Koltunski
937 c7b00dfb Leszek Koltunski
    return speed> 1.2f ? NEAREST*(angle>0 ? 1:-1) : 0;
938 0e5ad27c Leszek Koltunski
    }
939
940 30bc2d91 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
941
942
  public float getCameraDist()
943
    {
944
    return mCameraDist;
945
    }
946
947 5b893eee Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
948
949
  public int getNodeSize()
950
    {
951
    return mNodeSize;
952
    }
953
954 aa171dee Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
955
956 9c2f0c91 Leszek Koltunski
  public ObjectList getObjectList()
957 aa171dee Leszek Koltunski
    {
958
    return mList;
959
    }
960
961 10a2e360 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
962
963 f0fa83ae Leszek Koltunski
  abstract float getScreenRatio();
964 e6cf7283 Leszek Koltunski
  abstract float[][] getCubitPositions(int numLayers);
965 10585385 Leszek Koltunski
  abstract Static4D[] getQuats();
966 411c6285 Leszek Koltunski
  abstract int getNumFaces();
967 a64e07d0 Leszek Koltunski
  abstract int getNumStickerTypes(int numLayers);
968 8f53e513 Leszek Koltunski
  abstract int getNumCubitFaces();
969 a64e07d0 Leszek Koltunski
  abstract MeshBase createCubitMesh(int cubit, int numLayers);
970 ae755eda Leszek Koltunski
  abstract void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top);
971
  abstract int getFaceColor(int cubit, int cubitface, int numLayers);
972 fb377dae Leszek Koltunski
  abstract float returnMultiplier();
973 e6734aa9 Leszek Koltunski
  abstract float[][] getCuts(int numLayers);
974 eaee1ddc Leszek Koltunski
  abstract boolean shouldResetTextureMaps();
975 925ed78f Leszek Koltunski
  abstract Static3D[] getRotationAxis();
976 7c969a6d Leszek Koltunski
977 6b6504fe Leszek Koltunski
  public abstract boolean isSolved();
978 925ed78f Leszek Koltunski
  public abstract int[] getBasicAngle();
979 20931cf6 Leszek Koltunski
  public abstract String retObjectString();
980 9f171eba Leszek Koltunski
  public abstract void randomizeNewScramble(int[][] scramble, Random rnd, int curScramble, int totScrambles);
981 6fd4a72c Leszek Koltunski
  public abstract int getObjectName(int numLayers);
982
  public abstract int getInventor(int numLayers);
983
  public abstract int getComplexity(int numLayers);
984 fdec60a3 Leszek Koltunski
  }