Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikObject.java @ 470820a7

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 411c6285 Leszek Koltunski
import android.graphics.Bitmap;
24
import android.graphics.Canvas;
25
import android.graphics.Paint;
26 27a70eae Leszek Koltunski
27
import org.distorted.library.effect.Effect;
28 470820a7 Leszek Koltunski
import org.distorted.library.effect.MatrixEffectMove;
29 27a70eae Leszek Koltunski
import org.distorted.library.effect.MatrixEffectQuaternion;
30
import org.distorted.library.effect.MatrixEffectScale;
31
import org.distorted.library.main.DistortedEffects;
32
import org.distorted.library.main.DistortedNode;
33
import org.distorted.library.main.DistortedTexture;
34 b32444ee Leszek Koltunski
import org.distorted.library.mesh.MeshBase;
35 470820a7 Leszek Koltunski
import org.distorted.library.mesh.MeshJoined;
36 97c012ae Leszek Koltunski
import org.distorted.library.mesh.MeshRectangles;
37 27a70eae Leszek Koltunski
import org.distorted.library.message.EffectListener;
38
import org.distorted.library.type.Static1D;
39
import org.distorted.library.type.Static3D;
40
import org.distorted.library.type.Static4D;
41 4f9f99a2 Leszek Koltunski
42 0333d81e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
43
44 27a70eae Leszek Koltunski
public abstract class RubikObject extends DistortedNode
45 fdec60a3 Leszek Koltunski
  {
46 14bd7976 Leszek Koltunski
  static final int INTERIOR_COLOR = 0xff000000;
47 fb6a40c8 Leszek Koltunski
  public static final int NODE_FBO_SIZE = 600;
48
49 7289fd6c Leszek Koltunski
  private static final int TEXTURE_HEIGHT = 128;
50 a10ada2a Leszek Koltunski
  final float[] LEGAL_QUATS;
51 efef689c Leszek Koltunski
  final Static3D[] ROTATION_AXIS;
52 470820a7 Leszek Koltunski
  final int NUM_FACES;
53 27a70eae Leszek Koltunski
54 f0fa83ae Leszek Koltunski
  static float OBJECT_SCREEN_RATIO;
55
56 a10ada2a Leszek Koltunski
  private final int NUM_CUBITS;
57 9224ffd2 Leszek Koltunski
  private int mRotRowBitmap;
58 efef689c Leszek Koltunski
  private int mRotAxis;
59 49f67f9b Leszek Koltunski
  private Static3D[] mOrigPos;
60 fb6a40c8 Leszek Koltunski
  private Static3D mNodeScale;
61 27a70eae Leszek Koltunski
  private Static4D mQuatAccumulated;
62 b32444ee Leszek Koltunski
  private Cubit[] mCubits;
63 49f67f9b Leszek Koltunski
  private int mSize;
64 aa171dee Leszek Koltunski
  private RubikObjectList mList;
65 470820a7 Leszek Koltunski
  private MeshBase mMesh;
66
  private DistortedEffects mEffects;
67 27a70eae Leszek Koltunski
68 e844c116 Leszek Koltunski
  float mStart, mStep;
69 fdec60a3 Leszek Koltunski
70 27a70eae Leszek Koltunski
  Static1D mRotationAngleStatic, mRotationAngleMiddle, mRotationAngleFinal;
71
  DistortedTexture mTexture;
72
73
  MatrixEffectScale mScaleEffect;
74
  MatrixEffectQuaternion mQuatCEffect;
75
  MatrixEffectQuaternion mQuatAEffect;
76
77
///////////////////////////////////////////////////////////////////////////////////////////////////
78 fdec60a3 Leszek Koltunski
79 aa171dee Leszek Koltunski
  RubikObject(int size, int fov, Static4D quatCur, Static4D quatAcc, DistortedTexture nodeTexture,
80 a31d25de Leszek Koltunski
              MeshRectangles nodeMesh, DistortedEffects nodeEffects, int[][] moves, RubikObjectList list)
81 fdec60a3 Leszek Koltunski
    {
82 411c6285 Leszek Koltunski
    super(nodeTexture,nodeEffects,nodeMesh);
83 fdec60a3 Leszek Koltunski
84 ba740a0c Leszek Koltunski
    resizeFBO(NODE_FBO_SIZE, NODE_FBO_SIZE);
85 d41742f7 Leszek Koltunski
86 aa171dee Leszek Koltunski
    mList = list;
87 49f67f9b Leszek Koltunski
    mOrigPos = getCubitPositions(size);
88 10a2e360 Leszek Koltunski
89 f16ff19d Leszek Koltunski
    LEGAL_QUATS = getLegalQuats();
90 49f67f9b Leszek Koltunski
    NUM_CUBITS  = mOrigPos.length;
91 efef689c Leszek Koltunski
    ROTATION_AXIS = getRotationAxis();
92 f0fa83ae Leszek Koltunski
    OBJECT_SCREEN_RATIO = getScreenRatio();
93 470820a7 Leszek Koltunski
    NUM_FACES = getNumFaces();
94 a10ada2a Leszek Koltunski
95 27a70eae Leszek Koltunski
    mSize = size;
96 49f67f9b Leszek Koltunski
    computeStartAndStep(mOrigPos);
97 fb6a40c8 Leszek Koltunski
    mNodeScale= new Static3D(1,1,1);
98
    mQuatAccumulated = quatAcc;
99 e844c116 Leszek Koltunski
100 27a70eae Leszek Koltunski
    mRotationAngleStatic = new Static1D(0);
101
    mRotationAngleMiddle = new Static1D(0);
102
    mRotationAngleFinal  = new Static1D(0);
103
104 5ba13c05 Leszek Koltunski
    Static3D center = new Static3D(0,0,0);
105 fb6a40c8 Leszek Koltunski
    float scale = OBJECT_SCREEN_RATIO*NODE_FBO_SIZE/mSize;
106
    mScaleEffect = new MatrixEffectScale(new Static3D(scale,scale,scale));
107 5ba13c05 Leszek Koltunski
    mQuatCEffect = new MatrixEffectQuaternion(quatCur, center);
108
    mQuatAEffect = new MatrixEffectQuaternion(quatAcc, center);
109 27a70eae Leszek Koltunski
110
    MatrixEffectScale nodeScaleEffect = new MatrixEffectScale(mNodeScale);
111 411c6285 Leszek Koltunski
    nodeEffects.apply(nodeScaleEffect);
112 a10ada2a Leszek Koltunski
113
    mCubits = new Cubit[NUM_CUBITS];
114 5974d2ae Leszek Koltunski
    mTexture = new DistortedTexture();
115 470820a7 Leszek Koltunski
    MeshBase[] cubitMesh = new MeshBase[NUM_CUBITS];
116 a10ada2a Leszek Koltunski
117
    for(int i=0; i<NUM_CUBITS; i++)
118
      {
119 470820a7 Leszek Koltunski
      cubitMesh[i] = createCubitMesh(i);
120
      cubitMesh[i].apply(new MatrixEffectMove(mOrigPos[i]),1,0);
121
      mCubits[i] = new Cubit(this,mOrigPos[i]);
122 a10ada2a Leszek Koltunski
      }
123 7381193e Leszek Koltunski
124 470820a7 Leszek Koltunski
    mMesh = new MeshJoined(cubitMesh);
125
126
    resetAllTextureMaps();
127
128
    mEffects = new DistortedEffects();
129
    mEffects.apply(mQuatAEffect);
130
    mEffects.apply(mQuatCEffect);
131
    mEffects.apply(mScaleEffect);
132
133
    attach( new DistortedNode(mTexture,mEffects,mMesh) );
134
135 aa171dee Leszek Koltunski
    setupPosition(moves);
136
137 4888e97c Leszek Koltunski
    setProjection(fov, 0.1f);
138 27a70eae Leszek Koltunski
    }
139
140 efef689c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
141
142
  private void textureCubitMesh(MeshBase mesh, int cubit)
143
    {
144
    boolean belongs;
145 470820a7 Leszek Koltunski
    final Static4D[] maps = new Static4D[NUM_FACES];
146
    final float ratio = 1.0f/(NUM_FACES+1);
147 efef689c Leszek Koltunski
148 470820a7 Leszek Koltunski
    if( 2*ROTATION_AXIS.length == NUM_FACES )  // i.e. there are faces on both ends of the axis (cube)
149 efef689c Leszek Koltunski
      {
150 470820a7 Leszek Koltunski
      for(int i=0; i<NUM_FACES; i++)
151 efef689c Leszek Koltunski
        {
152 66cbdd21 Leszek Koltunski
        belongs = isOnFace(cubit, i/2, i%2==0 ? mSize-1:0 );
153 470820a7 Leszek Koltunski
        maps[i] = new Static4D( (belongs?i:NUM_FACES)*ratio, 0.0f, ratio, 1.0f);
154 efef689c Leszek Koltunski
        }
155
      }
156 470820a7 Leszek Koltunski
    else if( ROTATION_AXIS.length == NUM_FACES )  // just a single face on the right end of an axis (pyraminx)
157 efef689c Leszek Koltunski
      {
158 470820a7 Leszek Koltunski
      for(int i=0; i<NUM_FACES; i++)
159 efef689c Leszek Koltunski
        {
160 66cbdd21 Leszek Koltunski
        belongs = isOnFace(cubit, i, 0 );
161 470820a7 Leszek Koltunski
        maps[i] = new Static4D( (belongs?i:NUM_FACES)*ratio, 0.0f, ratio, 1.0f);
162 efef689c Leszek Koltunski
        }
163
      }
164
165 470820a7 Leszek Koltunski
    mesh.setTextureMap(maps,NUM_FACES*cubit);
166 efef689c Leszek Koltunski
    }
167
168 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
169 97d2f701 Leszek Koltunski
// Cast centers of all Cubits on the first rotation Axis and compute the leftmost and rightmost
170
// one. From there compute the 'start' (i.e. the leftmost) and 'step' (i.e. distance between two
171
// consecutive).
172
// it is assumed that other rotation axis have the same 'start' and 'step' - this is the case with
173
// the Cube and the Pyraminx.
174
// Start and Step are then needed to compute which rotation row (with respect to a given axis) a
175
// given Cubit belongs to.
176 e844c116 Leszek Koltunski
177
  private void computeStartAndStep(Static3D[] pos)
178
    {
179
    float min = Float.MAX_VALUE;
180
    float max = Float.MIN_VALUE;
181
    float axisX = ROTATION_AXIS[0].get0();
182
    float axisY = ROTATION_AXIS[0].get1();
183
    float axisZ = ROTATION_AXIS[0].get2();
184
    float tmp;
185
186
    for(int i=0; i<NUM_CUBITS; i++)
187
      {
188
      tmp = pos[i].get0()*axisX + pos[i].get1()*axisY + pos[i].get2()*axisZ;
189
      if( tmp<min ) min=tmp;
190
      if( tmp>max ) max=tmp;
191
      }
192
193
    mStart = min;
194
    mStep  = (max-min+1.0f)/mSize;
195
    }
196
197 efef689c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
198
199 9224ffd2 Leszek Koltunski
  private boolean belongsToRotation( int cubit, int axis, int rowBitmap)
200 efef689c Leszek Koltunski
    {
201 9224ffd2 Leszek Koltunski
    int cubitRow = (int)(mCubits[cubit].mRotationRow[axis]+0.5f);
202
    return ((1<<cubitRow)&rowBitmap)!=0;
203 66cbdd21 Leszek Koltunski
    }
204
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206
// we cannot use belongsToRotation for deciding if to texture a face. Counterexample: the 'rotated'
207
// tetrahedrons of Pyraminx nearby the edge: they belong to rotation but their face which is rotated
208
// away from the face of the Pyraminx shouldn't be textured.
209
210
  private boolean isOnFace( int cubit, int axis, int row)
211
    {
212
    final float MAX_ERROR = 0.0001f;
213
    float diff = mCubits[cubit].mRotationRow[axis] - row;
214
    return diff*diff < MAX_ERROR;
215 efef689c Leszek Koltunski
    }
216
217 aa171dee Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
218 a31d25de Leszek Koltunski
// note the minus in front of the sin() - we rotate counterclockwise
219
// when looking towards the direction where the axis increases in values.
220 aa171dee Leszek Koltunski
221 a31d25de Leszek Koltunski
  private Static4D makeQuaternion(int axisIndex, int angleInDegrees)
222 aa171dee Leszek Koltunski
    {
223 a31d25de Leszek Koltunski
    Static3D axis = ROTATION_AXIS[axisIndex];
224
225
    while( angleInDegrees<0 ) angleInDegrees += 360;
226
    angleInDegrees %= 360;
227
    
228
    float cosA = (float)Math.cos(Math.PI*angleInDegrees/360);
229
    float sinA =-(float)Math.sqrt(1-cosA*cosA);
230
231
    return new Static4D(axis.get0()*sinA, axis.get1()*sinA, axis.get2()*sinA, cosA);
232
    }
233
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235
236
  private void setupPosition(int[][] moves)
237
    {
238
    if( moves!=null )
239
      {
240
      Static4D quat;
241
      int axis, rowBitmap, angle;
242
      int corr = (360/getBasicAngle());
243
244
      for(int[] move: moves)
245
        {
246
        axis     = move[0];
247
        rowBitmap= move[1];
248
        angle    = move[2]*corr;
249
        quat     = makeQuaternion(axis,angle);
250
251
        for(int j=0; j<NUM_CUBITS; j++)
252
          if( belongsToRotation(j,axis,rowBitmap) )
253
            {
254
            mCubits[j].removeRotationNow(quat);
255
            }
256
        }
257
      }
258 aa171dee Leszek Koltunski
    }
259
260 fa0f7a56 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
261
262
  int getCubitFaceColorIndex(int cubit, int face)
263
    {
264 470820a7 Leszek Koltunski
    Static4D texMap = mMesh.getTextureMap(NUM_FACES*cubit + face);
265
    return (int)(texMap.get0() / texMap.get2());
266 fa0f7a56 Leszek Koltunski
    }
267
268 49f67f9b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
269
// Clamp all rotated positions to one of those original ones to avoid accumulating errors.
270
271
  void clampPos(Static3D pos)
272
    {
273
    float currError, minError = Float.MAX_VALUE;
274
    int minErrorIndex= -1;
275
    float x = pos.get0();
276
    float y = pos.get1();
277
    float z = pos.get2();
278
    float xo,yo,zo;
279
280
    for(int i=0; i<NUM_CUBITS; i++)
281
      {
282
      xo = mOrigPos[i].get0();
283
      yo = mOrigPos[i].get1();
284
      zo = mOrigPos[i].get2();
285
286
      currError = (xo-x)*(xo-x) + (yo-y)*(yo-y) + (zo-z)*(zo-z);
287
288
      if( currError<minError )
289
        {
290
        minError = currError;
291
        minErrorIndex = i;
292
        }
293
      }
294
295
    pos.set( mOrigPos[minErrorIndex] );
296
    }
297
298 411c6285 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
299
// the getFaceColors + final black in a horizontal strip.
300
301
  public void createTexture()
302
    {
303
    Bitmap bitmap;
304
305
    Paint paint = new Paint();
306 470820a7 Leszek Koltunski
    bitmap = Bitmap.createBitmap( (NUM_FACES+1)*TEXTURE_HEIGHT, TEXTURE_HEIGHT, Bitmap.Config.ARGB_8888);
307 411c6285 Leszek Koltunski
    Canvas canvas = new Canvas(bitmap);
308
309
    paint.setAntiAlias(true);
310
    paint.setTextAlign(Paint.Align.CENTER);
311
    paint.setStyle(Paint.Style.FILL);
312
313 14bd7976 Leszek Koltunski
    paint.setColor(INTERIOR_COLOR);
314 470820a7 Leszek Koltunski
    canvas.drawRect(0, 0, (NUM_FACES+1)*TEXTURE_HEIGHT, TEXTURE_HEIGHT, paint);
315 411c6285 Leszek Koltunski
316 470820a7 Leszek Koltunski
    for(int i=0; i<NUM_FACES; i++)
317 411c6285 Leszek Koltunski
      {
318 ca292407 Leszek Koltunski
      createFaceTexture(canvas, paint, i, i*TEXTURE_HEIGHT, 0, TEXTURE_HEIGHT);
319 411c6285 Leszek Koltunski
      }
320
321
    mTexture.setTexture(bitmap);
322
    }
323
324 dd73fdab Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
325
326 27a70eae Leszek Koltunski
  public int getSize()
327 fdec60a3 Leszek Koltunski
    {
328 27a70eae Leszek Koltunski
    return mSize;
329 fdec60a3 Leszek Koltunski
    }
330
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332
333 27a70eae Leszek Koltunski
  public void continueRotation(float angleInDegrees)
334 fdec60a3 Leszek Koltunski
    {
335 27a70eae Leszek Koltunski
    mRotationAngleStatic.set0(angleInDegrees);
336 fdec60a3 Leszek Koltunski
    }
337
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339
340 27a70eae Leszek Koltunski
  public Static4D getRotationQuat()
341
      {
342
      return mQuatAccumulated;
343
      }
344
345
///////////////////////////////////////////////////////////////////////////////////////////////////
346
347 5ba13c05 Leszek Koltunski
  public void recomputeScaleFactor(int scrWidth, int scrHeight)
348 fdec60a3 Leszek Koltunski
    {
349 f0fa83ae Leszek Koltunski
    float factor = Math.min(scrWidth,scrHeight);
350 5ba13c05 Leszek Koltunski
    mNodeScale.set(factor,factor,factor);
351 fdec60a3 Leszek Koltunski
    }
352 27a70eae Leszek Koltunski
353
///////////////////////////////////////////////////////////////////////////////////////////////////
354
355 a10ada2a Leszek Koltunski
  public void savePreferences(SharedPreferences.Editor editor)
356
    {
357
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].savePreferences(editor);
358
    }
359 f16ff19d Leszek Koltunski
360 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
361 27a70eae Leszek Koltunski
362 a10ada2a Leszek Koltunski
  public void restorePreferences(SharedPreferences preferences)
363
    {
364
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].restorePreferences(preferences);
365
    }
366 27a70eae Leszek Koltunski
367 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
368
369
  public void releaseResources()
370
    {
371
    mTexture.markForDeletion();
372
373 470820a7 Leszek Koltunski
    // TODO ?
374 a10ada2a Leszek Koltunski
    }
375
376
///////////////////////////////////////////////////////////////////////////////////////////////////
377
378
  public void apply(Effect effect, int position)
379
    {
380
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].mEffect.apply(effect, position);
381
    }
382
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384
385
  public void remove(long effectID)
386
    {
387
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].mEffect.abortById(effectID);
388
    }
389 74686c71 Leszek Koltunski
390 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
391
392
  public void solve()
393
    {
394
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].solve();
395
    }
396
397
///////////////////////////////////////////////////////////////////////////////////////////////////
398
399
  public boolean isSolved()
400
    {
401
    Static4D q = mCubits[0].mQuatScramble;
402
403 94ad5a8f Leszek Koltunski
    for(int i=1; i<NUM_CUBITS; i++)
404 a10ada2a Leszek Koltunski
      {
405 94ad5a8f Leszek Koltunski
      if( !mCubits[i].thereIsNoVisibleDifference(q) ) return false;
406 a10ada2a Leszek Koltunski
      }
407
408
    return true;
409
    }
410
411 1f9772f3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
412
413
  public void resetAllTextureMaps()
414
    {
415
    for(int i=0; i<NUM_CUBITS; i++)
416
      {
417 470820a7 Leszek Koltunski
      textureCubitMesh( mMesh , i );
418 1f9772f3 Leszek Koltunski
      }
419
    }
420
421
///////////////////////////////////////////////////////////////////////////////////////////////////
422
423
  public void setTextureMap(int cubit, int face, int newColor)
424
    {
425 470820a7 Leszek Koltunski
    final float ratio = 1.0f/(NUM_FACES+1);
426
    final Static4D[] maps = new Static4D[NUM_FACES];
427 1f9772f3 Leszek Koltunski
428 d5032ac8 Leszek Koltunski
    try
429
      {
430
      maps[face] = new Static4D( newColor*ratio, 0.0f, ratio, 1.0f);
431 470820a7 Leszek Koltunski
      mMesh.setTextureMap(maps,NUM_FACES*cubit);
432 d5032ac8 Leszek Koltunski
      }
433
    catch(ArrayIndexOutOfBoundsException ignored)
434
      {
435
      // the object must have changed in between of us touching the screen and getting here
436
      // (which happens after the next render, i.e. about 30 miliseconds later)
437
      // ignore.
438
      }
439 1f9772f3 Leszek Koltunski
    }
440
441 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
442
443 efef689c Leszek Koltunski
  public void beginNewRotation(int axis, int row )
444 a10ada2a Leszek Koltunski
    {
445 9cd7695f Leszek Koltunski
    if( axis<0 || axis>=ROTATION_AXIS.length )
446
      {
447
      android.util.Log.e("object", "invalid rotation axis: "+axis);
448
      return;
449
      }
450
    if( row<0 || row>=mSize )
451
      {
452
      android.util.Log.e("object", "invalid rotation row: "+row);
453
      return;
454
      }
455
456 9224ffd2 Leszek Koltunski
    mRotAxis       = axis;
457
    mRotRowBitmap  = (1<<row);
458 a10ada2a Leszek Koltunski
459
    mRotationAngleStatic.set0(0.0f);
460
461
    for(int i=0; i<NUM_CUBITS; i++)
462 9224ffd2 Leszek Koltunski
      if( belongsToRotation(i,mRotAxis,mRotRowBitmap) )
463 a10ada2a Leszek Koltunski
        {
464
        mCubits[i].beginNewRotation(axis);
465
        }
466
     }
467
468
///////////////////////////////////////////////////////////////////////////////////////////////////
469
470 9224ffd2 Leszek Koltunski
  public long addNewRotation( int axis, int rowBitmap, int angle, long durationMillis, EffectListener listener )
471 a10ada2a Leszek Koltunski
     {
472
     long effectID=0;
473 001cc0e4 Leszek Koltunski
     int firstCubit = -1;
474 a10ada2a Leszek Koltunski
475 9224ffd2 Leszek Koltunski
     mRotAxis       = axis;
476
     mRotRowBitmap  = rowBitmap;
477 a10ada2a Leszek Koltunski
478
     mRotationAngleStatic.set0(0.0f);
479
480
     for(int i=0; i<NUM_CUBITS; i++)
481 9224ffd2 Leszek Koltunski
       if( belongsToRotation(i,mRotAxis,mRotRowBitmap) )
482 a10ada2a Leszek Koltunski
         {
483
         mCubits[i].addNewRotation(axis,durationMillis,angle);
484 001cc0e4 Leszek Koltunski
         if( firstCubit<0 ) firstCubit = i;
485 a10ada2a Leszek Koltunski
         }
486
487 001cc0e4 Leszek Koltunski
     if( firstCubit>=0 ) effectID = mCubits[firstCubit].setUpCallback(listener);
488
489 a10ada2a Leszek Koltunski
     return effectID;
490
     }
491
492 001cc0e4 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
493
494
  public long finishRotationNow(EffectListener listener)
495
    {
496
    int firstCubit= -1;
497
    long effectID =  0;
498
499
    for(int i=0; i<NUM_CUBITS; i++)
500
      {
501
      if( belongsToRotation(i,mRotAxis,mRotRowBitmap) )
502
        {
503
        if( firstCubit<0 )
504
          {
505
          firstCubit=i;
506
507 f8ce34ab Leszek Koltunski
          float angle = mCubits[i].getAngle();
508 001cc0e4 Leszek Koltunski
          int nearestAngleInDegrees = computeNearestAngle(angle);
509
          mRotationAngleStatic.set0(angle);
510
          mRotationAngleFinal.set0(nearestAngleInDegrees);
511
          mRotationAngleMiddle.set0( nearestAngleInDegrees + (nearestAngleInDegrees-angle)*0.2f );
512
          }
513
        mCubits[i].resetRotationAngle();
514
        }
515
      }
516
517
    if( firstCubit>=0 ) effectID = mCubits[firstCubit].setUpCallback(listener);
518
519
    return effectID;
520
    }
521
522 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
523
524
  public void removeRotationNow()
525
     {
526
     boolean first = true;
527
     Static4D quat = null;
528
529
     for(int i=0; i<NUM_CUBITS; i++)
530 9224ffd2 Leszek Koltunski
       if( belongsToRotation(i,mRotAxis,mRotRowBitmap) )
531 a10ada2a Leszek Koltunski
         {
532
         if( first )
533
           {
534
           first = false;
535 001cc0e4 Leszek Koltunski
536 f8ce34ab Leszek Koltunski
           float angle = mCubits[i].getAngle();
537 001cc0e4 Leszek Koltunski
           int nearestAngleInDegrees = computeNearestAngle(angle);
538
           double nearestAngleInRadians = nearestAngleInDegrees*Math.PI/180;
539
           float sinA =-(float)Math.sin(nearestAngleInRadians*0.5);
540
           float cosA = (float)Math.cos(nearestAngleInRadians*0.5);
541
           float axisX = ROTATION_AXIS[mRotAxis].get0();
542
           float axisY = ROTATION_AXIS[mRotAxis].get1();
543
           float axisZ = ROTATION_AXIS[mRotAxis].get2();
544
           quat = new Static4D( axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
545 a10ada2a Leszek Koltunski
           }
546
547
         mCubits[i].removeRotationNow(quat);
548
         }
549
550
     mRotationAngleStatic.set0(0);
551
     }
552
553 aa171dee Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
554
555 a31d25de Leszek Koltunski
  public void initializeObject(int[][] moves)
556 aa171dee Leszek Koltunski
    {
557
    solve();
558
    setupPosition(moves);
559
    }
560
561 9621255f Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
562
563
  public int getCubit(float[] point3D)
564
    {
565
    float dist, minDist = Float. MAX_VALUE;
566
    int currentBest=-1;
567
    float multiplier = returnMultiplier();
568
569
    point3D[0] *= multiplier;
570
    point3D[1] *= multiplier;
571
    point3D[2] *= multiplier;
572
573
    for(int i=0; i<NUM_CUBITS; i++)
574
      {
575
      dist = mCubits[i].getDistSquared(point3D);
576
      if( dist<minDist )
577
        {
578
        minDist = dist;
579
        currentBest = i;
580
        }
581
      }
582
583
    return currentBest;
584
    }
585
586 0e5ad27c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
587
588
  public int computeNearestAngle(float angle)
589
    {
590
    final int NEAREST = 360/getBasicAngle();
591
592
    int tmp = (int)((angle+NEAREST/2)/NEAREST);
593
    if( angle< -(NEAREST*0.5) ) tmp-=1;
594
595
    return NEAREST*tmp;
596
    }
597
598 aa171dee Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
599
600
  public RubikObjectList getObjectList()
601
    {
602
    return mList;
603
    }
604
605 10a2e360 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
606
607 f0fa83ae Leszek Koltunski
  abstract float getScreenRatio();
608 10a2e360 Leszek Koltunski
  abstract Static3D[] getCubitPositions(int size);
609 a10ada2a Leszek Koltunski
  abstract float[] getLegalQuats();
610 411c6285 Leszek Koltunski
  abstract int getNumFaces();
611 14bd7976 Leszek Koltunski
  abstract MeshBase createCubitMesh(int cubit);
612 7289fd6c Leszek Koltunski
  abstract void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side);
613 12ad3fca Leszek Koltunski
  public abstract Static3D[] getRotationAxis();
614 e844c116 Leszek Koltunski
  public abstract int getBasicAngle();
615 9621255f Leszek Koltunski
  public abstract float returnMultiplier();
616 e46e17fb Leszek Koltunski
  public abstract float returnRotationFactor(float offset);
617 20931cf6 Leszek Koltunski
  public abstract String retObjectString();
618 5cf34c5f Leszek Koltunski
  public abstract float[] getRowChances();
619 fdec60a3 Leszek Koltunski
  }