Project

General

Profile

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

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

1
///////////////////////////////////////////////////////////////////////////////////////////////////
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
package org.distorted.object;
21

    
22
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
import org.distorted.library.mesh.MeshBase;
33
import org.distorted.library.mesh.MeshRectangles;
34
import org.distorted.library.message.EffectListener;
35
import org.distorted.library.type.Dynamic1D;
36
import org.distorted.library.type.Static1D;
37
import org.distorted.library.type.Static3D;
38
import org.distorted.library.type.Static4D;
39

    
40
///////////////////////////////////////////////////////////////////////////////////////////////////
41

    
42
public abstract class RubikObject extends DistortedNode
43
  {
44
  static final float OBJECT_SCREEN_RATIO = 0.5f;
45
  static final int TEXTURE_SIZE = 100;
46
  final float[] LEGAL_QUATS;
47

    
48
  private static final int POST_ROTATION_MILLISEC = 500;
49
  private final int NUM_CUBITS;
50
  private int mRotRow;
51
  private Static3D mRotAxis;
52
  private Static3D mMove, mScale, mNodeMove, mNodeScale;
53
  private Static4D mQuatAccumulated;
54
  private DistortedTexture mNodeTexture;
55
  private Cubit[] mCubits;
56

    
57
  int mSize;
58

    
59
  Static1D mRotationAngleStatic, mRotationAngleMiddle, mRotationAngleFinal;
60
  DistortedTexture mTexture;
61

    
62
  VertexEffectSink mSinkEffect;
63
  MatrixEffectMove mMoveEffect;
64
  MatrixEffectScale mScaleEffect;
65
  MatrixEffectQuaternion mQuatCEffect;
66
  MatrixEffectQuaternion mQuatAEffect;
67

    
68
///////////////////////////////////////////////////////////////////////////////////////////////////
69

    
70
  RubikObject(int size, Static4D quatCur, Static4D quatAcc, DistortedTexture texture, MeshRectangles mesh, DistortedEffects effects)
71
    {
72
    super(texture,effects,mesh);
73

    
74
    LEGAL_QUATS = getLegalQuats();
75
    NUM_CUBITS  = getNumCubits(size);
76

    
77
    mNodeTexture = texture;
78
    mSize = size;
79

    
80
    mRotationAngleStatic = new Static1D(0);
81
    mRotationAngleMiddle = new Static1D(0);
82
    mRotationAngleFinal  = new Static1D(0);
83

    
84
    mMove     = new Static3D(0,0,0);
85
    mScale    = new Static3D(1,1,1);
86
    mNodeMove = new Static3D(0,0,0);
87
    mNodeScale= new Static3D(1,1,1);
88

    
89
    mQuatAccumulated = quatAcc;
90

    
91
    Static3D sinkCenter = new Static3D(TEXTURE_SIZE*0.5f, TEXTURE_SIZE*0.5f, TEXTURE_SIZE*0.5f);
92
    Static3D matrCenter = new Static3D(0,0,0);
93
    Static4D region = new Static4D(0,0,0, TEXTURE_SIZE*0.72f);
94

    
95
    mSinkEffect = new VertexEffectSink( new Static1D(getSinkStrength()), sinkCenter, region );
96
    mMoveEffect = new MatrixEffectMove(mMove);
97
    mScaleEffect = new MatrixEffectScale(mScale);
98
    mQuatCEffect = new MatrixEffectQuaternion(quatCur, matrCenter);
99
    mQuatAEffect = new MatrixEffectQuaternion(quatAcc, matrCenter);
100

    
101
    MatrixEffectMove  nodeMoveEffect  = new MatrixEffectMove(mNodeMove);
102
    MatrixEffectScale nodeScaleEffect = new MatrixEffectScale(mNodeScale);
103

    
104
    effects.apply(nodeScaleEffect);
105
    effects.apply(nodeMoveEffect);
106

    
107
    mCubits = new Cubit[NUM_CUBITS];
108
    mTexture = new DistortedTexture(TEXTURE_SIZE,TEXTURE_SIZE);
109

    
110
    int vertices = (int)(24.0f/mSize + 2.0f);
111
    int[][] positions = getCubitPositions(size);
112

    
113
    for(int i=0; i<NUM_CUBITS; i++)
114
      {
115
      int x = positions[i][0];
116
      int y = positions[i][1];
117
      int z = positions[i][2];
118

    
119
      mCubits[i] = new Cubit( this ,createCubitMesh(vertices,x,y,z), new Static3D(x,y,z) );
120
      attach(mCubits[i].mNode);
121
      }
122
    }
123

    
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125

    
126
  private void resetRotationAngle(Dynamic1D rotationAngle)
127
    {
128
    rotationAngle.setDuration(POST_ROTATION_MILLISEC);
129
    rotationAngle.resetToBeginning();
130
    rotationAngle.removeAll();
131
    rotationAngle.add(mRotationAngleStatic);
132
    rotationAngle.add(mRotationAngleMiddle);
133
    rotationAngle.add(mRotationAngleFinal);
134
    }
135

    
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

    
138
  private float getSinkStrength()
139
    {
140
    switch(mSize)
141
      {
142
      case 1 : return 1.1f;
143
      case 2 : return 1.5f;
144
      case 3 : return 1.8f;
145
      case 4 : return 2.0f;
146
      default: return 3.0f - 4.0f/mSize;
147
      }
148
    }
149

    
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

    
152
  public int getSize()
153
    {
154
    return mSize;
155
    }
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158

    
159
  public void continueRotation(float angleInDegrees)
160
    {
161
    mRotationAngleStatic.set0(angleInDegrees);
162
    }
163

    
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165

    
166
  public Static4D getRotationQuat()
167
      {
168
      return mQuatAccumulated;
169
      }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172

    
173
  public void recomputeScaleFactor(int screenWidth, int screenHeight)
174
    {
175
    int texW = mNodeTexture.getWidth();
176
    int texH = mNodeTexture.getHeight();
177

    
178
    if( (float)texH/texW > (float)screenHeight/screenWidth )
179
      {
180
      int w = (screenHeight*texW)/texH;
181
      float factor = (float)screenHeight/texH;
182
      mNodeMove.set((screenWidth-w)*0.5f ,0, 0);
183
      mNodeScale.set(factor,factor,factor);
184
      }
185
    else
186
      {
187
      int h = (screenWidth*texH)/texW;
188
      float factor = (float)screenWidth/texW;
189
      mNodeMove.set(0,(screenHeight-h)*0.5f,0);
190
      mNodeScale.set(factor,factor,factor);
191
      }
192

    
193
    float scaleFactor = (OBJECT_SCREEN_RATIO*texW/(TEXTURE_SIZE*mSize));
194

    
195
    mMove.set( texW*0.5f , texH*0.5f , 0.0f );
196
    mScale.set(scaleFactor,scaleFactor,scaleFactor);
197
    }
198

    
199
///////////////////////////////////////////////////////////////////////////////////////////////////
200

    
201
  public void savePreferences(SharedPreferences.Editor editor)
202
    {
203
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].savePreferences(editor);
204
    }
205

    
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

    
208
  public void restorePreferences(SharedPreferences preferences)
209
    {
210
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].restorePreferences(preferences);
211
    }
212

    
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214

    
215
  public long finishRotationNow(EffectListener listener)
216
    {
217
    boolean first = true;
218
    long effectID=0;
219

    
220
    for(int i=0; i<NUM_CUBITS; i++)
221
      {
222
      if( belongsToRotation(mCubits[i].mCurrentPosition,mRotAxis,mRotRow) )
223
        {
224
        if( first )
225
          {
226
          first=false;
227
          effectID = mCubits[i].finishRotationNow(listener);
228
          }
229
        resetRotationAngle(mCubits[i].mRotationAngle);
230
        }
231
      }
232

    
233
    return effectID;
234
    }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237

    
238
  public void releaseResources()
239
    {
240
    mTexture.markForDeletion();
241

    
242
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].releaseResources();
243
    }
244

    
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246

    
247
  public void apply(Effect effect, int position)
248
    {
249
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].mEffect.apply(effect, position);
250
    }
251

    
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253

    
254
  public void remove(long effectID)
255
    {
256
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].mEffect.abortById(effectID);
257
    }
258

    
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260

    
261
  public void solve()
262
    {
263
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].solve();
264
    }
265

    
266
///////////////////////////////////////////////////////////////////////////////////////////////////
267

    
268
  public boolean isSolved()
269
    {
270
    Static4D q = mCubits[0].mQuatScramble;
271

    
272
    float x = q.get0();
273
    float y = q.get1();
274
    float z = q.get2();
275
    float w = q.get3();
276

    
277
    for(int i=0; i<NUM_CUBITS; i++)
278
      {
279
      q = mCubits[i].mQuatScramble;
280

    
281
      if( q.get0()!=x || q.get1()!=y || q.get2()!=z || q.get3()!=w ) return false;
282
      }
283

    
284
    return true;
285
    }
286

    
287
///////////////////////////////////////////////////////////////////////////////////////////////////
288

    
289
  public void beginNewRotation(Static3D axis, int row )
290
    {
291
    mRotAxis = axis;
292
    mRotRow  = row;
293

    
294
    mRotationAngleStatic.set0(0.0f);
295

    
296
    for(int i=0; i<NUM_CUBITS; i++)
297
      if( belongsToRotation( mCubits[i].mCurrentPosition,axis,mRotRow) )
298
        {
299
        mCubits[i].beginNewRotation(axis);
300
        }
301
     }
302

    
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304

    
305
  public long addNewRotation( Static3D axis, int row, int angle, long durationMillis, EffectListener listener )
306
     {
307
     long effectID=0;
308
     boolean first = true;
309

    
310
     mRotAxis = axis;
311
     mRotRow  = row;
312

    
313
     mRotationAngleStatic.set0(0.0f);
314

    
315
     for(int i=0; i<NUM_CUBITS; i++)
316
       if( belongsToRotation(mCubits[i].mCurrentPosition,axis,mRotRow) )
317
         {
318
         mCubits[i].addNewRotation(axis,durationMillis,angle);
319

    
320
         if( first )
321
           {
322
           first = false;
323
           effectID = mCubits[i].setUpCallback(listener);
324
           }
325
         }
326

    
327
     return effectID;
328
     }
329

    
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331

    
332
  public void removeRotationNow()
333
     {
334
     boolean first = true;
335
     Static4D quat = null;
336

    
337
     for(int i=0; i<NUM_CUBITS; i++)
338
       if( belongsToRotation(mCubits[i].mCurrentPosition,mRotAxis,mRotRow) )
339
         {
340
         if( first )
341
           {
342
           first = false;
343
           quat = mCubits[i].returnRotationQuat(mRotAxis);
344
           }
345

    
346
         mCubits[i].removeRotationNow(quat);
347
         }
348

    
349
     mRotationAngleStatic.set0(0);
350
     }
351

    
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353

    
354
  abstract int getNumCubits(int size);
355
  abstract int[][] getCubitPositions(int size);
356
  abstract float[] getLegalQuats();
357
  abstract boolean belongsToRotation(Static3D position, Static3D axis, int row);
358
  abstract MeshBase createCubitMesh(int vertices, int x, int y, int z);
359

    
360
  public abstract void createTexture();
361
  }
(4-4/6)