Project

General

Profile

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

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

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