Project

General

Profile

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

magiccube / src / main / java / org / distorted / object / RubikObject.java @ a10ada2a

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 4f9f99a2 Leszek Koltunski
package org.distorted.object;
21 fdec60a3 Leszek Koltunski
22 27a70eae Leszek Koltunski
import android.content.SharedPreferences;
23
24
import org.distorted.library.effect.Effect;
25
import org.distorted.library.effect.MatrixEffectMove;
26
import org.distorted.library.effect.MatrixEffectQuaternion;
27
import org.distorted.library.effect.MatrixEffectScale;
28
import org.distorted.library.effect.VertexEffectSink;
29
import org.distorted.library.main.DistortedEffects;
30
import org.distorted.library.main.DistortedNode;
31
import org.distorted.library.main.DistortedTexture;
32 a10ada2a Leszek Koltunski
import org.distorted.library.mesh.MeshCubes;
33 97c012ae Leszek Koltunski
import org.distorted.library.mesh.MeshRectangles;
34 27a70eae Leszek Koltunski
import org.distorted.library.message.EffectListener;
35 f16ff19d Leszek Koltunski
import org.distorted.library.type.Dynamic1D;
36 27a70eae Leszek Koltunski
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 a10ada2a Leszek Koltunski
import static org.distorted.object.RubikObjectList.*;
41
42 0333d81e Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
43
44 27a70eae Leszek Koltunski
public abstract class RubikObject extends DistortedNode
45 fdec60a3 Leszek Koltunski
  {
46 27a70eae Leszek Koltunski
  static final float OBJECT_SCREEN_RATIO = 0.5f;
47
  static final int TEXTURE_SIZE = 100;
48 a10ada2a Leszek Koltunski
  final float[] LEGAL_QUATS;
49 27a70eae Leszek Koltunski
50 f16ff19d Leszek Koltunski
  private static final int POST_ROTATION_MILLISEC = 500;
51 a10ada2a Leszek Koltunski
  private final int NUM_CUBITS;
52
  private final int[][] CUBIT_POSITIONS;
53
  private int mRotAxis, mRotRow;
54 f16ff19d Leszek Koltunski
55 27a70eae Leszek Koltunski
  private Static3D mMove, mScale, mNodeMove, mNodeScale;
56
  private Static4D mQuatAccumulated;
57
  private DistortedTexture mNodeTexture;
58
59 a10ada2a Leszek Koltunski
  int mSize;
60 fdec60a3 Leszek Koltunski
61 27a70eae Leszek Koltunski
  Static1D mRotationAngleStatic, mRotationAngleMiddle, mRotationAngleFinal;
62
  DistortedTexture mTexture;
63
64
  VertexEffectSink mSinkEffect;
65
  MatrixEffectMove mMoveEffect;
66
  MatrixEffectScale mScaleEffect;
67
  MatrixEffectQuaternion mQuatCEffect;
68
  MatrixEffectQuaternion mQuatAEffect;
69
70 a10ada2a Leszek Koltunski
  private Cubit[] mCubits;
71
72 27a70eae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
73 fdec60a3 Leszek Koltunski
74 97c012ae Leszek Koltunski
  RubikObject(int size, Static4D quatCur, Static4D quatAcc, DistortedTexture texture, MeshRectangles mesh, DistortedEffects effects)
75 fdec60a3 Leszek Koltunski
    {
76 27a70eae Leszek Koltunski
    super(texture,effects,mesh);
77 fdec60a3 Leszek Koltunski
78 f16ff19d Leszek Koltunski
    LEGAL_QUATS = getLegalQuats();
79 a10ada2a Leszek Koltunski
    NUM_CUBITS  = getNumCubits(size);
80
    CUBIT_POSITIONS = getCubitPositions(size);
81
82 27a70eae Leszek Koltunski
    mNodeTexture = texture;
83
    mSize = size;
84
85
    mRotationAngleStatic = new Static1D(0);
86
    mRotationAngleMiddle = new Static1D(0);
87
    mRotationAngleFinal  = new Static1D(0);
88
89
    mMove     = new Static3D(0,0,0);
90
    mScale    = new Static3D(1,1,1);
91
    mNodeMove = new Static3D(0,0,0);
92
    mNodeScale= new Static3D(1,1,1);
93
94
    mQuatAccumulated = quatAcc;
95
96
    Static3D sinkCenter = new Static3D(TEXTURE_SIZE*0.5f, TEXTURE_SIZE*0.5f, TEXTURE_SIZE*0.5f);
97
    Static3D matrCenter = new Static3D(0,0,0);
98
    Static4D region = new Static4D(0,0,0, TEXTURE_SIZE*0.72f);
99
100
    mSinkEffect = new VertexEffectSink( new Static1D(getSinkStrength()), sinkCenter, region );
101
    mMoveEffect = new MatrixEffectMove(mMove);
102
    mScaleEffect = new MatrixEffectScale(mScale);
103
    mQuatCEffect = new MatrixEffectQuaternion(quatCur, matrCenter);
104
    mQuatAEffect = new MatrixEffectQuaternion(quatAcc, matrCenter);
105
106
    MatrixEffectMove  nodeMoveEffect  = new MatrixEffectMove(mNodeMove);
107
    MatrixEffectScale nodeScaleEffect = new MatrixEffectScale(mNodeScale);
108
109
    effects.apply(nodeScaleEffect);
110
    effects.apply(nodeMoveEffect);
111 a10ada2a Leszek Koltunski
112
113
    mCubits = new Cubit[NUM_CUBITS];
114
115
    mTexture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
116
117
    int vertices = (int)(24.0f/mSize + 2.0f);
118
119
    for(int i=0; i<NUM_CUBITS; i++)
120
      {
121
      int x = CUBIT_POSITIONS[i][0];
122
      int y = CUBIT_POSITIONS[i][1];
123
      int z = CUBIT_POSITIONS[i][2];
124
125
      mCubits[i] = new Cubit( this ,createMesh(vertices,x,y,z), new Static3D(x,y,z) );
126
      attach(mCubits[i].mNode);
127
      }
128 27a70eae Leszek Koltunski
    }
129
130 f16ff19d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
131
132 a10ada2a Leszek Koltunski
  private void resetRotationAngle(Dynamic1D rotationAngle)
133 f16ff19d Leszek Koltunski
    {
134
    rotationAngle.setDuration(POST_ROTATION_MILLISEC);
135
    rotationAngle.resetToBeginning();
136
    rotationAngle.removeAll();
137
    rotationAngle.add(mRotationAngleStatic);
138
    rotationAngle.add(mRotationAngleMiddle);
139
    rotationAngle.add(mRotationAngleFinal);
140
    }
141
142 fdec60a3 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
143
144 27a70eae Leszek Koltunski
  private float getSinkStrength()
145 dd73fdab Leszek Koltunski
    {
146 27a70eae Leszek Koltunski
    switch(mSize)
147
      {
148
      case 1 : return 1.1f;
149
      case 2 : return 1.5f;
150
      case 3 : return 1.8f;
151
      case 4 : return 2.0f;
152
      default: return 3.0f - 4.0f/mSize;
153
      }
154 dd73fdab Leszek Koltunski
    }
155
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157
158 27a70eae Leszek Koltunski
  public int getSize()
159 fdec60a3 Leszek Koltunski
    {
160 27a70eae Leszek Koltunski
    return mSize;
161 fdec60a3 Leszek Koltunski
    }
162
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164
165 27a70eae Leszek Koltunski
  public void continueRotation(float angleInDegrees)
166 fdec60a3 Leszek Koltunski
    {
167 27a70eae Leszek Koltunski
    mRotationAngleStatic.set0(angleInDegrees);
168 fdec60a3 Leszek Koltunski
    }
169
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171
172 27a70eae Leszek Koltunski
  public Static4D getRotationQuat()
173
      {
174
      return mQuatAccumulated;
175
      }
176
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178
179
  public void recomputeScaleFactor(int screenWidth, int screenHeight)
180 fdec60a3 Leszek Koltunski
    {
181 27a70eae Leszek Koltunski
    int texW = mNodeTexture.getWidth();
182
    int texH = mNodeTexture.getHeight();
183
184
    if( (float)texH/texW > (float)screenHeight/screenWidth )
185
      {
186
      int w = (screenHeight*texW)/texH;
187
      float factor = (float)screenHeight/texH;
188
      mNodeMove.set((screenWidth-w)*0.5f ,0, 0);
189
      mNodeScale.set(factor,factor,factor);
190
      }
191
    else
192
      {
193
      int h = (screenWidth*texH)/texW;
194
      float factor = (float)screenWidth/texW;
195
      mNodeMove.set(0,(screenHeight-h)*0.5f,0);
196
      mNodeScale.set(factor,factor,factor);
197
      }
198
199
    float scaleFactor = (OBJECT_SCREEN_RATIO*texW/(TEXTURE_SIZE*mSize));
200
201
    mMove.set( texW*0.5f , texH*0.5f , 0.0f );
202
    mScale.set(scaleFactor,scaleFactor,scaleFactor);
203 fdec60a3 Leszek Koltunski
    }
204 27a70eae Leszek Koltunski
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206
207 a10ada2a Leszek Koltunski
  public void savePreferences(SharedPreferences.Editor editor)
208
    {
209
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].savePreferences(editor);
210
    }
211 f16ff19d Leszek Koltunski
212 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
213 27a70eae Leszek Koltunski
214 a10ada2a Leszek Koltunski
  public void restorePreferences(SharedPreferences preferences)
215
    {
216
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].restorePreferences(preferences);
217
    }
218 27a70eae Leszek Koltunski
219 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
220 74686c71 Leszek Koltunski
221 a10ada2a Leszek Koltunski
  public long finishRotationNow(EffectListener listener)
222
    {
223
    boolean first = true;
224
    long effectID=0;
225
226
    for(int i=0; i<NUM_CUBITS; i++)
227
      {
228
      if( belongsToRotation(mCubits[i].mCurrentPosition,mRotAxis,mRotRow) )
229
        {
230
        if( first )
231
          {
232
          first=false;
233
          effectID = mCubits[i].finishRotationNow(listener);
234
          }
235
        resetRotationAngle(mCubits[i].mRotationAngle);
236
        }
237
      }
238
239
    return effectID;
240
    }
241
242
///////////////////////////////////////////////////////////////////////////////////////////////////
243
244
  public void releaseResources()
245
    {
246
    mTexture.markForDeletion();
247
248
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].releaseResources();
249
    }
250
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252
253
  public void apply(Effect effect, int position)
254
    {
255
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].mEffect.apply(effect, position);
256
    }
257
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259
260
  public void remove(long effectID)
261
    {
262
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].mEffect.abortById(effectID);
263
    }
264 74686c71 Leszek Koltunski
265 a10ada2a Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
266
267
  public void solve()
268
    {
269
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].solve();
270
    }
271
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273
274
  public boolean isSolved()
275
    {
276
    Static4D q = mCubits[0].mQuatScramble;
277
278
    float x = q.get0();
279
    float y = q.get1();
280
    float z = q.get2();
281
    float w = q.get3();
282
283
    for(int i=0; i<NUM_CUBITS; i++)
284
      {
285
      q = mCubits[i].mQuatScramble;
286
287
      if( q.get0()!=x || q.get1()!=y || q.get2()!=z || q.get3()!=w ) return false;
288
      }
289
290
    return true;
291
    }
292
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294
295
  public void beginNewRotation(int vector, int row )
296
    {
297
    Static3D axis = VectX;
298
299
    switch(vector)
300
      {
301
      case VECTX: axis = VectX; break;
302
      case VECTY: axis = VectY; break;
303
      case VECTZ: axis = VectZ; break;
304
      }
305
306
    mRotAxis = vector;
307
    mRotRow  = row;
308
309
    mRotationAngleStatic.set0(0.0f);
310
311
    for(int i=0; i<NUM_CUBITS; i++)
312
      if( belongsToRotation( mCubits[i].mCurrentPosition,vector,mRotRow) )
313
        {
314
        mCubits[i].beginNewRotation(axis);
315
        }
316
     }
317
318
///////////////////////////////////////////////////////////////////////////////////////////////////
319
320
  public long addNewRotation(int vector, int row, int angle, long durationMillis, EffectListener listener )
321
     {
322
     Static3D axis = VectX;
323
     long effectID=0;
324
     boolean first = true;
325
326
     switch(vector)
327
       {
328
       case VECTX: axis = VectX; break;
329
       case VECTY: axis = VectY; break;
330
       case VECTZ: axis = VectZ; break;
331
       }
332
333
     mRotAxis = vector;
334
     mRotRow  = row;
335
336
     mRotationAngleStatic.set0(0.0f);
337
338
     for(int i=0; i<NUM_CUBITS; i++)
339
       if( belongsToRotation(mCubits[i].mCurrentPosition,vector,mRotRow) )
340
         {
341
         mCubits[i].addNewRotation(axis,durationMillis,angle);
342
343
         if( first )
344
           {
345
           first = false;
346
           effectID = mCubits[i].setUpCallback(listener);
347
           }
348
         }
349
350
     return effectID;
351
     }
352
353
///////////////////////////////////////////////////////////////////////////////////////////////////
354
355
  public void removeRotationNow()
356
     {
357
     float qx=0,qy=0,qz=0;
358
     boolean first = true;
359
     Static4D quat = null;
360
361
     switch(mRotAxis)
362
       {
363
       case VECTX: qx=1; break;
364
       case VECTY: qy=1; break;
365
       case VECTZ: qz=1; break;
366
       }
367
368
     for(int i=0; i<NUM_CUBITS; i++)
369
       if( belongsToRotation(mCubits[i].mCurrentPosition,mRotAxis,mRotRow) )
370
         {
371
         if( first )
372
           {
373
           first = false;
374
           quat = mCubits[i].returnRotationQuat(qx,qy,qz);
375
           }
376
377
         mCubits[i].removeRotationNow(quat);
378
         }
379
380
     mRotationAngleStatic.set0(0);
381
     }
382
383
///////////////////////////////////////////////////////////////////////////////////////////////////
384
385
  abstract int getNumCubits(int size);
386
  abstract int[][] getCubitPositions(int size);
387
  abstract float[] getLegalQuats();
388
  abstract boolean belongsToRotation(Static3D position, int axis, int row);
389
  abstract MeshCubes createMesh(int vertices,int x, int y, int z);
390
391
  public abstract void createTexture();
392 fdec60a3 Leszek Koltunski
  }