Project

General

Profile

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

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

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