Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikObject.java @ 7e8b9852

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