Project

General

Profile

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

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

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