Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyObject.java @ cb137f36

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