Project

General

Profile

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

magiccube / src / main / java / org / distorted / object / RubikObject.java @ 5ba13c05

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.MatrixEffectQuaternion;
26
import org.distorted.library.effect.MatrixEffectScale;
27
import org.distorted.library.effect.VertexEffectSink;
28
import org.distorted.library.main.DistortedEffects;
29
import org.distorted.library.main.DistortedNode;
30
import org.distorted.library.main.DistortedTexture;
31
import org.distorted.library.mesh.MeshBase;
32
import org.distorted.library.mesh.MeshRectangles;
33
import org.distorted.library.message.EffectListener;
34
import org.distorted.library.type.Dynamic1D;
35
import org.distorted.library.type.Static1D;
36
import org.distorted.library.type.Static3D;
37
import org.distorted.library.type.Static4D;
38

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

    
41
public abstract class RubikObject extends DistortedNode
42
  {
43
  static final float OBJECT_SCREEN_RATIO = 0.5f;
44
  final float[] LEGAL_QUATS;
45

    
46
  private static final int POST_ROTATION_MILLISEC = 500;
47
  private final int NUM_CUBITS;
48
  private int mRotRow;
49
  private Static3D mRotAxis;
50
  private Static3D mScale, mNodeScale;
51
  private Static4D mQuatAccumulated;
52
  private Cubit[] mCubits;
53

    
54
  int mSize;
55

    
56
  Static1D mRotationAngleStatic, mRotationAngleMiddle, mRotationAngleFinal;
57
  DistortedTexture mTexture;
58

    
59
  VertexEffectSink mSinkEffect;
60
  MatrixEffectScale mScaleEffect;
61
  MatrixEffectQuaternion mQuatCEffect;
62
  MatrixEffectQuaternion mQuatAEffect;
63

    
64
///////////////////////////////////////////////////////////////////////////////////////////////////
65

    
66
  RubikObject(int size, Static4D quatCur, Static4D quatAcc, DistortedTexture texture, MeshRectangles mesh, DistortedEffects effects)
67
    {
68
    super(texture,effects,mesh);
69

    
70
    LEGAL_QUATS = getLegalQuats();
71
    NUM_CUBITS  = getNumCubits(size);
72

    
73
    mSize = size;
74

    
75
    mRotationAngleStatic = new Static1D(0);
76
    mRotationAngleMiddle = new Static1D(0);
77
    mRotationAngleFinal  = new Static1D(0);
78

    
79
    mScale    = new Static3D(1,1,1);
80
    mNodeScale= new Static3D(1,1,1);
81

    
82
    mQuatAccumulated = quatAcc;
83

    
84
    Static3D center = new Static3D(0,0,0);
85
    Static4D region = new Static4D(0,0,0,0.72f);
86

    
87
    mSinkEffect = new VertexEffectSink( new Static1D(getSinkStrength()), center, region );
88
    mScaleEffect = new MatrixEffectScale(mScale);
89
    mQuatCEffect = new MatrixEffectQuaternion(quatCur, center);
90
    mQuatAEffect = new MatrixEffectQuaternion(quatAcc, center);
91

    
92
    MatrixEffectScale nodeScaleEffect = new MatrixEffectScale(mNodeScale);
93

    
94
    effects.apply(nodeScaleEffect);
95

    
96
    mCubits = new Cubit[NUM_CUBITS];
97
    mTexture = new DistortedTexture();
98

    
99
    int vertices = (int)(24.0f/mSize + 2.0f);
100
    int[][] positions = getCubitPositions(size);
101

    
102
    for(int i=0; i<NUM_CUBITS; i++)
103
      {
104
      int x = positions[i][0];
105
      int y = positions[i][1];
106
      int z = positions[i][2];
107

    
108
      mCubits[i] = new Cubit( this ,createCubitMesh(vertices,x,y,z), new Static3D(x,y,z) );
109
      attach(mCubits[i].mNode);
110
      }
111
    }
112

    
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114

    
115
  private void resetRotationAngle(Dynamic1D rotationAngle)
116
    {
117
    rotationAngle.setDuration(POST_ROTATION_MILLISEC);
118
    rotationAngle.resetToBeginning();
119
    rotationAngle.removeAll();
120
    rotationAngle.add(mRotationAngleStatic);
121
    rotationAngle.add(mRotationAngleMiddle);
122
    rotationAngle.add(mRotationAngleFinal);
123
    }
124

    
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126

    
127
  private float getSinkStrength()
128
    {
129
    switch(mSize)
130
      {
131
      case 1 : return 1.1f;
132
      case 2 : return 1.5f;
133
      case 3 : return 1.8f;
134
      case 4 : return 2.0f;
135
      default: return 3.0f - 4.0f/mSize;
136
      }
137
    }
138

    
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140

    
141
  public int getSize()
142
    {
143
    return mSize;
144
    }
145

    
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147

    
148
  public void continueRotation(float angleInDegrees)
149
    {
150
    mRotationAngleStatic.set0(angleInDegrees);
151
    }
152

    
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154

    
155
  public Static4D getRotationQuat()
156
      {
157
      return mQuatAccumulated;
158
      }
159

    
160
///////////////////////////////////////////////////////////////////////////////////////////////////
161

    
162
  public void recomputeScaleFactor(int scrWidth, int scrHeight)
163
    {
164
    float mx = getMesh().getStretchX();
165
    float my = getMesh().getStretchY();
166
    float factor = (my/mx > (float)scrHeight/scrWidth) ? (float)scrHeight/my : (float)scrWidth/mx;
167
    float scaleFactor = (OBJECT_SCREEN_RATIO*mx/mSize);
168

    
169
    mNodeScale.set(factor,factor,factor);
170
    mScale.set(scaleFactor,scaleFactor,scaleFactor);
171
    }
172

    
173
///////////////////////////////////////////////////////////////////////////////////////////////////
174

    
175
  public void savePreferences(SharedPreferences.Editor editor)
176
    {
177
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].savePreferences(editor);
178
    }
179

    
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181

    
182
  public void restorePreferences(SharedPreferences preferences)
183
    {
184
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].restorePreferences(preferences);
185
    }
186

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

    
189
  public long finishRotationNow(EffectListener listener)
190
    {
191
    boolean first = true;
192
    long effectID=0;
193

    
194
    for(int i=0; i<NUM_CUBITS; i++)
195
      {
196
      if( belongsToRotation(mCubits[i].mCurrentPosition,mRotAxis,mRotRow) )
197
        {
198
        if( first )
199
          {
200
          first=false;
201
          effectID = mCubits[i].finishRotationNow(listener);
202
          }
203
        resetRotationAngle(mCubits[i].mRotationAngle);
204
        }
205
      }
206

    
207
    return effectID;
208
    }
209

    
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211

    
212
  public void releaseResources()
213
    {
214
    mTexture.markForDeletion();
215

    
216
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].releaseResources();
217
    }
218

    
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220

    
221
  public void apply(Effect effect, int position)
222
    {
223
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].mEffect.apply(effect, position);
224
    }
225

    
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227

    
228
  public void remove(long effectID)
229
    {
230
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].mEffect.abortById(effectID);
231
    }
232

    
233
///////////////////////////////////////////////////////////////////////////////////////////////////
234

    
235
  public void solve()
236
    {
237
    for(int i=0; i<NUM_CUBITS; i++) mCubits[i].solve();
238
    }
239

    
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241

    
242
  public boolean isSolved()
243
    {
244
    Static4D q = mCubits[0].mQuatScramble;
245

    
246
    float x = q.get0();
247
    float y = q.get1();
248
    float z = q.get2();
249
    float w = q.get3();
250

    
251
    for(int i=0; i<NUM_CUBITS; i++)
252
      {
253
      q = mCubits[i].mQuatScramble;
254

    
255
      if( q.get0()!=x || q.get1()!=y || q.get2()!=z || q.get3()!=w ) return false;
256
      }
257

    
258
    return true;
259
    }
260

    
261
///////////////////////////////////////////////////////////////////////////////////////////////////
262

    
263
  public void beginNewRotation(Static3D axis, int row )
264
    {
265
    mRotAxis = axis;
266
    mRotRow  = row;
267

    
268
    mRotationAngleStatic.set0(0.0f);
269

    
270
    for(int i=0; i<NUM_CUBITS; i++)
271
      if( belongsToRotation( mCubits[i].mCurrentPosition,axis,mRotRow) )
272
        {
273
        mCubits[i].beginNewRotation(axis);
274
        }
275
     }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

    
279
  public long addNewRotation( Static3D axis, int row, int angle, long durationMillis, EffectListener listener )
280
     {
281
     long effectID=0;
282
     boolean first = true;
283

    
284
     mRotAxis = axis;
285
     mRotRow  = row;
286

    
287
     mRotationAngleStatic.set0(0.0f);
288

    
289
     for(int i=0; i<NUM_CUBITS; i++)
290
       if( belongsToRotation(mCubits[i].mCurrentPosition,axis,mRotRow) )
291
         {
292
         mCubits[i].addNewRotation(axis,durationMillis,angle);
293

    
294
         if( first )
295
           {
296
           first = false;
297
           effectID = mCubits[i].setUpCallback(listener);
298
           }
299
         }
300

    
301
     return effectID;
302
     }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

    
306
  public void removeRotationNow()
307
     {
308
     boolean first = true;
309
     Static4D quat = null;
310

    
311
     for(int i=0; i<NUM_CUBITS; i++)
312
       if( belongsToRotation(mCubits[i].mCurrentPosition,mRotAxis,mRotRow) )
313
         {
314
         if( first )
315
           {
316
           first = false;
317
           quat = mCubits[i].returnRotationQuat(mRotAxis);
318
           }
319

    
320
         mCubits[i].removeRotationNow(quat);
321
         }
322

    
323
     mRotationAngleStatic.set0(0);
324
     }
325

    
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327

    
328
  abstract int getNumCubits(int size);
329
  abstract int[][] getCubitPositions(int size);
330
  abstract float[] getLegalQuats();
331
  abstract boolean belongsToRotation(Static3D position, Static3D axis, int row);
332
  abstract MeshBase createCubitMesh(int vertices, int x, int y, int z);
333

    
334
  public abstract void createTexture();
335
  }
(4-4/6)