Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistyObject.java @ 31cd7256

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 221a4090 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
462
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different
463
// then if it were rotated by quaternion 'quat'.
464
// No it is not so simple as the quats need to be the same - imagine a 4x4x4 cube where the two
465
// middle squares get interchanged. No visible difference!
466
//
467
// So: this is true iff the cubit
468
// a) is a corner or edge and the quaternions are the same
469
// b) is inside one of the faces and after rotations by both quats it ends up on the same face.
470
471 722b2512 Leszek Koltunski
  boolean thereIsVisibleDifference(Cubit cubit, int quatIndex)
472 221a4090 Leszek Koltunski
    {
473 722b2512 Leszek Koltunski
    if ( cubit.mQuatIndex == quatIndex ) return false;
474 221a4090 Leszek Koltunski
475
    int belongsToHowManyFaces = 0;
476 f0450fcc Leszek Koltunski
    int bitmap = (1<<(getNumLayers()-1)) + 1;
477 221a4090 Leszek Koltunski
478
    for(int i=0; i<NUM_AXIS; i++)
479
      {
480 f0450fcc Leszek Koltunski
      if( (cubit.mRotationRow[i] & bitmap) != 0 ) belongsToHowManyFaces++;
481 221a4090 Leszek Koltunski
      }
482
483
    switch(belongsToHowManyFaces)
484
      {
485 722b2512 Leszek Koltunski
      case 0 : return false;  // 'inside' cubit that does not lie on any face
486 221a4090 Leszek Koltunski
      case 1 :                // cubit that lies inside one of the faces
487 e6cf7283 Leszek Koltunski
               float[] orig   = cubit.getOrigPosition();
488 221a4090 Leszek Koltunski
               Static4D quat1 = QUATS[quatIndex];
489
               Static4D quat2 = QUATS[cubit.mQuatIndex];
490
491 e6cf7283 Leszek Koltunski
               Static4D cubitCenter = new Static4D( orig[0], orig[1], orig[2], 0);              // not used for bandaged objects,
492
               Static4D rotated1 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat1 );   // only check the first position
493 221a4090 Leszek Koltunski
               Static4D rotated2 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat2 );
494
495 e6cf7283 Leszek Koltunski
               rotated1.get(mTmp1, 0, 0, 0);
496
               rotated2.get(mTmp2, 0, 0, 0);
497 221a4090 Leszek Koltunski
498
               for(int i=0; i<NUM_AXIS; i++)
499
                 {
500 e6cf7283 Leszek Koltunski
                 if( (computeRow(mTmp1,i) & computeRow(mTmp2,i) & bitmap) != 0 ) return false;
501 221a4090 Leszek Koltunski
                 }
502 722b2512 Leszek Koltunski
               return true;
503 221a4090 Leszek Koltunski
504 722b2512 Leszek Koltunski
      default: return true;  // edge or corner
505 221a4090 Leszek Koltunski
      }
506
    }
507
508 b1f2ccf5 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
509
// create StickerCoord and FaceTransform data structures
510
511
  void createFaceDataStructures()
512
    {
513
    int numCubitTypes = getNumCubitTypes(mNumLayers);
514
    FactoryCubit factory = FactoryCubit.getInstance();
515
    factory.clear();
516
517
    for(int cubit=0; cubit<numCubitTypes; cubit++)
518
      {
519
      double[][] vertices = getVertices(cubit);
520
      int[][] vertIndices = getVertIndexes(cubit);
521
      factory.createNewFaceTransform(vertices,vertIndices);
522
      }
523
524 31cd7256 Leszek Koltunski
    factory.printFaceTransform();
525 b1f2ccf5 Leszek Koltunski
    factory.printStickerCoords();
526
    }
527
528 411c6285 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
529 ae755eda Leszek Koltunski
// the getFaceColors + final black in a grid (so that we do not exceed the maximum texture size)
530 411c6285 Leszek Koltunski
531
  public void createTexture()
532
    {
533
    Bitmap bitmap;
534
535
    Paint paint = new Paint();
536 ae755eda Leszek Koltunski
    bitmap = Bitmap.createBitmap( mNumTexCols*TEXTURE_HEIGHT, mNumTexRows*TEXTURE_HEIGHT, Bitmap.Config.ARGB_8888);
537 411c6285 Leszek Koltunski
    Canvas canvas = new Canvas(bitmap);
538
539
    paint.setAntiAlias(true);
540
    paint.setTextAlign(Paint.Align.CENTER);
541
    paint.setStyle(Paint.Style.FILL);
542
543 ee526fe0 Leszek Koltunski
    paint.setColor(COLOR_BLACK);
544 ae755eda Leszek Koltunski
    canvas.drawRect(0, 0, mNumTexCols*TEXTURE_HEIGHT, mNumTexRows*TEXTURE_HEIGHT, paint);
545 411c6285 Leszek Koltunski
546 ae755eda Leszek Koltunski
    int tex = 0;
547
548
    for(int row=0; row<mNumTexRows; row++)
549
      for(int col=0; col<mNumTexCols; col++)
550
        {
551
        if( tex>=NUM_TEXTURES ) break;
552
        createFaceTexture(canvas, paint, tex, col*TEXTURE_HEIGHT, row*TEXTURE_HEIGHT);
553
        tex++;
554
        }
555 411c6285 Leszek Koltunski
556 c7e23561 Leszek Koltunski
    if( !mTexture.setTexture(bitmap) )
557
      {
558
      int max = DistortedLibrary.getMaxTextureSize();
559
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
560
      crashlytics.log("failed to set texture of size "+bitmap.getWidth()+"x"+bitmap.getHeight()+" max is "+max);
561
      }
562 411c6285 Leszek Koltunski
    }
563
564 dd73fdab Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
565
566 d99f3a48 Leszek Koltunski
  public int getNumLayers()
567 fdec60a3 Leszek Koltunski
    {
568 d99f3a48 Leszek Koltunski
    return mNumLayers;
569 fdec60a3 Leszek Koltunski
    }
570
571
///////////////////////////////////////////////////////////////////////////////////////////////////
572
573 27a70eae Leszek Koltunski
  public void continueRotation(float angleInDegrees)
574 fdec60a3 Leszek Koltunski
    {
575 27a70eae Leszek Koltunski
    mRotationAngleStatic.set0(angleInDegrees);
576 fdec60a3 Leszek Koltunski
    }
577
578
///////////////////////////////////////////////////////////////////////////////////////////////////
579
580 27a70eae Leszek Koltunski
  public Static4D getRotationQuat()
581
      {
582 4da7d87a Leszek Koltunski
      return mQuat;
583 27a70eae Leszek Koltunski
      }
584
585
///////////////////////////////////////////////////////////////////////////////////////////////////
586
587 f18e8fae Leszek Koltunski
  public void recomputeScaleFactor(int scrWidth)
588 fdec60a3 Leszek Koltunski
    {
589 3717a94e Leszek Koltunski
    mNodeScale.set(scrWidth,NODE_RATIO*scrWidth,scrWidth);
590 fdec60a3 Leszek Koltunski
    }
591 27a70eae Leszek Koltunski
592
///////////////////////////////////////////////////////////////////////////////////////////////////
593
594 a10ada2a Leszek Koltunski
  public void savePreferences(SharedPreferences.Editor editor)
595
    {
596 6b6504fe Leszek Koltunski
    for(int i=0; i<NUM_CUBITS; i++) CUBITS[i].savePreferences(editor);
597 a10ada2a Leszek Koltunski
    }
598 f16ff19d Leszek Koltunski
599 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
600 27a70eae Leszek Koltunski
601 8bbac3c2 Leszek Koltunski
  public synchronized void restorePreferences(SharedPreferences preferences)
602 a10ada2a Leszek Koltunski
    {
603 fc3c5170 Leszek Koltunski
    boolean error = false;
604
605 2fcad75d Leszek Koltunski
    for(int i=0; i<NUM_CUBITS; i++)
606
      {
607 a15078bb Leszek Koltunski
      mQuatDebug[i] = CUBITS[i].restorePreferences(preferences);
608 1d6c1eea Leszek Koltunski
609 fc3c5170 Leszek Koltunski
      if( mQuatDebug[i]>=0 && mQuatDebug[i]<QUATS.length)
610 1d6c1eea Leszek Koltunski
        {
611 fc3c5170 Leszek Koltunski
        CUBITS[i].modifyCurrentPosition(QUATS[mQuatDebug[i]]);
612
        mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(),mQuatDebug[i]);
613
        }
614
      else
615
        {
616
        error = true;
617 1d6c1eea Leszek Koltunski
        }
618 fc3c5170 Leszek Koltunski
      }
619 1d6c1eea Leszek Koltunski
620 fc3c5170 Leszek Koltunski
    if( error )
621
      {
622
      for(int i=0; i<NUM_CUBITS; i++)
623
        {
624
        CUBITS[i].solve();
625
        mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(),0);
626
        }
627
      recordQuatsState("Failed to restorePreferences");
628 a15078bb Leszek Koltunski
      }
629
    }
630
631
///////////////////////////////////////////////////////////////////////////////////////////////////
632
633
  public void recordQuatsState(String message)
634
    {
635
    StringBuilder quats = new StringBuilder();
636
637
    for(int j=0; j<NUM_CUBITS; j++)
638
      {
639
      quats.append(mQuatDebug[j]);
640
      quats.append(" ");
641 2fcad75d Leszek Koltunski
      }
642 a15078bb Leszek Koltunski
643 25445dcf Leszek Koltunski
    if( BuildConfig.DEBUG )
644
      {
645 2d9d9d62 Leszek Koltunski
      android.util.Log.e("quats" , quats.toString());
646 25445dcf Leszek Koltunski
      android.util.Log.e("object", mList.name()+"_"+mNumLayers);
647
      }
648
    else
649
      {
650
      Exception ex = new Exception(message);
651
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
652
      crashlytics.setCustomKey("quats" , quats.toString());
653
      crashlytics.setCustomKey("object", mList.name()+"_"+mNumLayers );
654
      crashlytics.recordException(ex);
655
      }
656 a10ada2a Leszek Koltunski
    }
657 27a70eae Leszek Koltunski
658 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
659
660
  public void releaseResources()
661
    {
662
    mTexture.markForDeletion();
663 54342a21 Leszek Koltunski
    mMesh.markForDeletion();
664
    mEffects.markForDeletion();
665
666
    for(int j=0; j<NUM_CUBITS; j++)
667
      {
668
      CUBITS[j].releaseResources();
669
      }
670 a10ada2a Leszek Koltunski
    }
671
672
///////////////////////////////////////////////////////////////////////////////////////////////////
673
674
  public void apply(Effect effect, int position)
675
    {
676 8cccfb10 Leszek Koltunski
    mEffects.apply(effect, position);
677 a10ada2a Leszek Koltunski
    }
678
679
///////////////////////////////////////////////////////////////////////////////////////////////////
680
681
  public void remove(long effectID)
682
    {
683 8cccfb10 Leszek Koltunski
    mEffects.abortById(effectID);
684 a10ada2a Leszek Koltunski
    }
685 74686c71 Leszek Koltunski
686 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
687
688 8bbac3c2 Leszek Koltunski
  public synchronized void solve()
689 a10ada2a Leszek Koltunski
    {
690 98904e45 Leszek Koltunski
    for(int i=0; i<NUM_CUBITS; i++)
691
      {
692 6b6504fe Leszek Koltunski
      CUBITS[i].solve();
693
      mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(), 0);
694 a10ada2a Leszek Koltunski
      }
695
    }
696
697 1f9772f3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
698
699
  public void resetAllTextureMaps()
700
    {
701 ae755eda Leszek Koltunski
    final float ratioW = 1.0f/mNumTexCols;
702
    final float ratioH = 1.0f/mNumTexRows;
703
    int color, row, col;
704 380162cb Leszek Koltunski
705 ad73edd5 Leszek Koltunski
    for(int cubit=0; cubit<NUM_CUBITS; cubit++)
706 1f9772f3 Leszek Koltunski
      {
707 8f53e513 Leszek Koltunski
      final Static4D[] maps = new Static4D[NUM_CUBIT_FACES];
708 ad73edd5 Leszek Koltunski
709 f6d06256 Leszek Koltunski
      for(int cubitface=0; cubitface<NUM_CUBIT_FACES; cubitface++)
710 ad73edd5 Leszek Koltunski
        {
711 d99f3a48 Leszek Koltunski
        color = getFaceColor(cubit,cubitface,mNumLayers);
712 ae755eda Leszek Koltunski
        row = (mNumTexRows-1) - color/mNumTexCols;
713
        col = color%mNumTexCols;
714
        maps[cubitface] = new Static4D( col*ratioW, row*ratioH, ratioW, ratioH);
715 ad73edd5 Leszek Koltunski
        }
716
717 8f53e513 Leszek Koltunski
      mMesh.setTextureMap(maps,NUM_CUBIT_FACES*cubit);
718 1f9772f3 Leszek Koltunski
      }
719
    }
720
721
///////////////////////////////////////////////////////////////////////////////////////////////////
722
723
  public void setTextureMap(int cubit, int face, int newColor)
724
    {
725 064ccc31 Leszek Koltunski
    final float ratioW = 1.0f/mNumTexCols;
726
    final float ratioH = 1.0f/mNumTexRows;
727 8f53e513 Leszek Koltunski
    final Static4D[] maps = new Static4D[NUM_CUBIT_FACES];
728 064ccc31 Leszek Koltunski
    int row = (mNumTexRows-1) - newColor/mNumTexCols;
729
    int col = newColor%mNumTexCols;
730 1f9772f3 Leszek Koltunski
731 064ccc31 Leszek Koltunski
    maps[face] = new Static4D( col*ratioW, row*ratioH, ratioW, ratioH);
732 8f53e513 Leszek Koltunski
    mMesh.setTextureMap(maps,NUM_CUBIT_FACES*cubit);
733 1f9772f3 Leszek Koltunski
    }
734
735 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
736
737 8bbac3c2 Leszek Koltunski
  public synchronized void beginNewRotation(int axis, int row )
738 a10ada2a Leszek Koltunski
    {
739 9cd7695f Leszek Koltunski
    if( axis<0 || axis>=ROTATION_AXIS.length )
740
      {
741
      android.util.Log.e("object", "invalid rotation axis: "+axis);
742
      return;
743
      }
744 d99f3a48 Leszek Koltunski
    if( row<0 || row>=mNumLayers )
745 9cd7695f Leszek Koltunski
      {
746
      android.util.Log.e("object", "invalid rotation row: "+row);
747
      return;
748
      }
749
750 27e6c301 Leszek Koltunski
    mRotAxis     = axis;
751 ce366b42 Leszek Koltunski
    mRotRowBitmap= computeBitmapFromRow( (1<<row),axis );
752 a10ada2a Leszek Koltunski
    mRotationAngleStatic.set0(0.0f);
753 27e6c301 Leszek Koltunski
    mRotationAxis.set( ROTATION_AXIS[axis] );
754
    mRotationAngle.add(mRotationAngleStatic);
755 9c2f0c91 Leszek Koltunski
    mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis* ObjectList.MAX_OBJECT_SIZE) , -1);
756 27e6c301 Leszek Koltunski
    }
757 a10ada2a Leszek Koltunski
758
///////////////////////////////////////////////////////////////////////////////////////////////////
759
760 8bbac3c2 Leszek Koltunski
  public synchronized long addNewRotation( int axis, int rowBitmap, int angle, long durationMillis, EffectListener listener )
761 27e6c301 Leszek Koltunski
    {
762 985f3dfa Leszek Koltunski
    if( wasRotateApplied() )
763
      {
764
      mRotAxis     = axis;
765 ce366b42 Leszek Koltunski
      mRotRowBitmap= computeBitmapFromRow( rowBitmap,axis );
766 985f3dfa Leszek Koltunski
767
      mRotationAngleStatic.set0(0.0f);
768
      mRotationAxis.set( ROTATION_AXIS[axis] );
769
      mRotationAngle.setDuration(durationMillis);
770
      mRotationAngle.resetToBeginning();
771
      mRotationAngle.add(new Static1D(0));
772
      mRotationAngle.add(new Static1D(angle));
773
      mRotateEffect.setMeshAssociation( mRotRowBitmap<<(axis* ObjectList.MAX_OBJECT_SIZE) , -1);
774
      mRotateEffect.notifyWhenFinished(listener);
775
776
      return mRotateEffect.getID();
777
      }
778 27e6c301 Leszek Koltunski
779 985f3dfa Leszek Koltunski
    return 0;
780 27e6c301 Leszek Koltunski
    }
781 a10ada2a Leszek Koltunski
782 27e6c301 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
783 a10ada2a Leszek Koltunski
784 168b6b56 Leszek Koltunski
  public long finishRotationNow(EffectListener listener, int nearestAngleInDegrees)
785 27e6c301 Leszek Koltunski
    {
786 985f3dfa Leszek Koltunski
    if( wasRotateApplied() )
787
      {
788
      float angle = getAngle();
789
      mRotationAngleStatic.set0(angle);
790
      mRotationAngleFinal.set0(nearestAngleInDegrees);
791
      mRotationAngleMiddle.set0( nearestAngleInDegrees + (nearestAngleInDegrees-angle)*0.2f );
792
793
      mRotationAngle.setDuration(POST_ROTATION_MILLISEC);
794
      mRotationAngle.resetToBeginning();
795
      mRotationAngle.removeAll();
796
      mRotationAngle.add(mRotationAngleStatic);
797
      mRotationAngle.add(mRotationAngleMiddle);
798
      mRotationAngle.add(mRotationAngleFinal);
799
      mRotateEffect.notifyWhenFinished(listener);
800
801
      return mRotateEffect.getID();
802
      }
803 27e6c301 Leszek Koltunski
804 985f3dfa Leszek Koltunski
    return 0;
805 27e6c301 Leszek Koltunski
    }
806 001cc0e4 Leszek Koltunski
807
///////////////////////////////////////////////////////////////////////////////////////////////////
808
809 27e6c301 Leszek Koltunski
  private float getAngle()
810 001cc0e4 Leszek Koltunski
    {
811 27e6c301 Leszek Koltunski
    int pointNum = mRotationAngle.getNumPoints();
812 001cc0e4 Leszek Koltunski
813 27e6c301 Leszek Koltunski
    if( pointNum>=1 )
814 001cc0e4 Leszek Koltunski
      {
815 27e6c301 Leszek Koltunski
      return mRotationAngle.getPoint(pointNum-1).get0();
816
      }
817
    else
818
      {
819
      FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
820
      crashlytics.log("points in RotationAngle: "+pointNum);
821
      return 0;
822 001cc0e4 Leszek Koltunski
      }
823
    }
824
825 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
826
827 8bbac3c2 Leszek Koltunski
  public synchronized void removeRotationNow()
828 168b6b56 Leszek Koltunski
    {
829
    float angle = getAngle();
830
    double nearestAngleInRadians = angle*Math.PI/180;
831
    float sinA =-(float)Math.sin(nearestAngleInRadians*0.5);
832
    float cosA = (float)Math.cos(nearestAngleInRadians*0.5);
833
    float axisX = ROTATION_AXIS[mRotAxis].get0();
834
    float axisY = ROTATION_AXIS[mRotAxis].get1();
835
    float axisZ = ROTATION_AXIS[mRotAxis].get2();
836
    Static4D quat = new Static4D( axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
837
838
    mRotationAngle.removeAll();
839
    mRotationAngleStatic.set0(0);
840
841
    for(int i=0; i<NUM_CUBITS; i++)
842
      if( belongsToRotation(i,mRotAxis,mRotRowBitmap) )
843
        {
844 6b6504fe Leszek Koltunski
        int index = CUBITS[i].removeRotationNow(quat);
845
        mMesh.setEffectAssociation(i, CUBITS[i].computeAssociation(),index);
846 168b6b56 Leszek Koltunski
        }
847
    }
848 a10ada2a Leszek Koltunski
849 aa171dee Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
850
851 a31d25de Leszek Koltunski
  public void initializeObject(int[][] moves)
852 aa171dee Leszek Koltunski
    {
853
    solve();
854
    setupPosition(moves);
855
    }
856
857 9621255f Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
858
859
  public int getCubit(float[] point3D)
860
    {
861 418aa554 Leszek Koltunski
    float dist, minDist = Float.MAX_VALUE;
862 9621255f Leszek Koltunski
    int currentBest=-1;
863
    float multiplier = returnMultiplier();
864
865
    point3D[0] *= multiplier;
866
    point3D[1] *= multiplier;
867
    point3D[2] *= multiplier;
868
869
    for(int i=0; i<NUM_CUBITS; i++)
870
      {
871 6b6504fe Leszek Koltunski
      dist = CUBITS[i].getDistSquared(point3D);
872 9621255f Leszek Koltunski
      if( dist<minDist )
873
        {
874
        minDist = dist;
875
        currentBest = i;
876
        }
877
      }
878
879
    return currentBest;
880
    }
881
882 0e5ad27c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
883
884 168b6b56 Leszek Koltunski
  public int computeNearestAngle(float angle, float speed)
885 0e5ad27c Leszek Koltunski
    {
886
    final int NEAREST = 360/getBasicAngle();
887
888 4c864c68 Leszek Koltunski
    int tmp = (int)((angle+NEAREST/2)/NEAREST);
889
    if( angle< -(NEAREST*0.5) ) tmp-=1;
890 168b6b56 Leszek Koltunski
891 4c864c68 Leszek Koltunski
    if( tmp!=0 ) return NEAREST*tmp;
892 168b6b56 Leszek Koltunski
893 c7b00dfb Leszek Koltunski
    return speed> 1.2f ? NEAREST*(angle>0 ? 1:-1) : 0;
894 0e5ad27c Leszek Koltunski
    }
895
896 30bc2d91 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
897
898
  public float getCameraDist()
899
    {
900
    return mCameraDist;
901
    }
902
903 5b893eee Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
904
905
  public int getNodeSize()
906
    {
907
    return mNodeSize;
908
    }
909
910 aa171dee Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
911
912 9c2f0c91 Leszek Koltunski
  public ObjectList getObjectList()
913 aa171dee Leszek Koltunski
    {
914
    return mList;
915
    }
916
917 10a2e360 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
918
919 f0fa83ae Leszek Koltunski
  abstract float getScreenRatio();
920 e6cf7283 Leszek Koltunski
  abstract float[][] getCubitPositions(int numLayers);
921 10585385 Leszek Koltunski
  abstract Static4D[] getQuats();
922 411c6285 Leszek Koltunski
  abstract int getNumFaces();
923 a64e07d0 Leszek Koltunski
  abstract int getNumStickerTypes(int numLayers);
924 8f53e513 Leszek Koltunski
  abstract int getNumCubitFaces();
925 a64e07d0 Leszek Koltunski
  abstract MeshBase createCubitMesh(int cubit, int numLayers);
926 ae755eda Leszek Koltunski
  abstract void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top);
927
  abstract int getFaceColor(int cubit, int cubitface, int numLayers);
928 fb377dae Leszek Koltunski
  abstract float returnMultiplier();
929 a64e07d0 Leszek Koltunski
  abstract float[] getRowChances(int numLayers);
930 ae755eda Leszek Koltunski
  abstract float[] getCuts(int numLayers);
931 eaee1ddc Leszek Koltunski
  abstract boolean shouldResetTextureMaps();
932 b1f2ccf5 Leszek Koltunski
  abstract double[][] getVertices(int cubitType);
933
  abstract int[][] getVertIndexes(int cubitType);
934
  abstract int getNumCubitTypes(int numLayers);
935 7c969a6d Leszek Koltunski
936 6b6504fe Leszek Koltunski
  public abstract boolean isSolved();
937 12ad3fca Leszek Koltunski
  public abstract Static3D[] getRotationAxis();
938 e844c116 Leszek Koltunski
  public abstract int getBasicAngle();
939 20931cf6 Leszek Koltunski
  public abstract String retObjectString();
940 5043d5d0 Leszek Koltunski
  public abstract void randomizeNewScramble(int[][] scramble, Random rnd, int numScramble);
941 6fd4a72c Leszek Koltunski
  public abstract int getObjectName(int numLayers);
942
  public abstract int getInventor(int numLayers);
943
  public abstract int getComplexity(int numLayers);
944 fdec60a3 Leszek Koltunski
  }