Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikObject.java @ 001cc0e4

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