Project

General

Profile

Download (8.91 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / main / Cubit.java @ b3b79e9b

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.main;
11

    
12
import android.content.SharedPreferences;
13

    
14
import org.distorted.library.main.QuatHelper;
15
import org.distorted.library.type.Static4D;
16

    
17
///////////////////////////////////////////////////////////////////////////////////////////////////
18

    
19
public class Cubit
20
  {
21
  public static final int TYPE_NORMAL   = 0;  // all 'old', 'pre-crazy' cubits
22
  public static final int TYPE_FOLLOWER = 1;  // those cubits that follow deciders (e.g. small circle edges from Crazy Plus planets)
23
  public static final int TYPE_DECIDER  = 2;  // cubits deciding about rotation rows of their followers (e.g. center cubits of Crazy Plus Planets)
24

    
25
  private final float[] mTmp;
26
  private final float[] mOrigPosition;
27
  private final float[] mCurrentPosition;
28
  private final float[] mRowOffset;
29
  private final float mOrigOffsetX, mOrigOffsetY, mOrigOffsetZ;
30
  private final int mNumAxis;
31
  private final int mLen;
32
  private final int[] mRotationRow;
33
  private final int mCubitType;
34
  private final int mOrigPuzzleFace;
35
  private final int mCubitIndex;
36

    
37
  private float[] mTrackingPoint;
38
  private int mCurrentPuzzleFace;
39
  private TwistyObject mParent;
40

    
41
  int mQuatIndex;
42

    
43
///////////////////////////////////////////////////////////////////////////////////////////////////
44

    
45
  Cubit(TwistyObject parent, float[] position, int numAxis, int cubitIndex)
46
    {
47
    mQuatIndex= 0;
48
    mParent   = parent;
49
    mLen      = position.length;
50

    
51
    mCubitType    = mParent.getCubitRotationType(cubitIndex);
52
    mRowOffset    = mParent.getCubitRowOffset(cubitIndex);
53
    mTrackingPoint= mParent.getTrackingPoint(cubitIndex,mCubitType);
54
    int face      = mParent.computeCurrentPuzzleFace(mCubitType,mTrackingPoint);
55

    
56
    if( mRowOffset!=null )
57
      {
58
      mOrigOffsetX = mRowOffset[0];
59
      mOrigOffsetY = mRowOffset[1];
60
      mOrigOffsetZ = mRowOffset[2];
61
      if( mCubitType==TYPE_DECIDER ) mParent.setRotationRowOffset(face,mRowOffset);
62
      }
63
    else
64
      {
65
      mOrigOffsetX = 0;
66
      mOrigOffsetY = 0;
67
      mOrigOffsetZ = 0;
68
      }
69

    
70
    mCubitIndex       = cubitIndex;
71
    mOrigPuzzleFace   = face;
72
    mCurrentPuzzleFace= face;
73
    mOrigPosition     = new float[mLen];
74
    mCurrentPosition  = new float[mLen];
75
    mTmp              = new float[4];
76

    
77
    for(int i=0; i<mLen; i++)
78
      {
79
      mOrigPosition[i]    = position[i];
80
      mCurrentPosition[i] = position[i];
81
      }
82

    
83
    mNumAxis     = numAxis;
84
    mRotationRow = new int[mNumAxis];
85
    computeRotationRow();
86
    }
87

    
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89
// Because of quatMultiplication, errors can accumulate - so to avoid this, we
90
// correct the value of the 'scramble' quat to what it should be - one of the legal quats from the
91
// list QUATS.
92
//
93
// We also have to remember that the group of unit quaternions is a double-cover of rotations
94
// in 3D ( q represents the same rotation as -q ) - so invert if needed.
95

    
96
  private int normalizeScrambleQuat(Static4D quat)
97
    {
98
    float x = quat.get0();
99
    float y = quat.get1();
100
    float z = quat.get2();
101
    float w = quat.get3();
102
    float xd,yd,zd,wd;
103
    float diff, mindiff = Float.MAX_VALUE;
104
    int ret=0;
105
    int num_quats = mParent.mObjectQuats.length;
106
    Static4D qt;
107

    
108
    for(int q=0; q<num_quats; q++)
109
      {
110
      qt = mParent.mObjectQuats[q];
111

    
112
      xd = x - qt.get0();
113
      yd = y - qt.get1();
114
      zd = z - qt.get2();
115
      wd = w - qt.get3();
116

    
117
      diff = xd*xd + yd*yd + zd*zd + wd*wd;
118

    
119
      if( diff < mindiff )
120
        {
121
        ret = q;
122
        mindiff = diff;
123
        }
124

    
125
      xd = x + qt.get0();
126
      yd = y + qt.get1();
127
      zd = z + qt.get2();
128
      wd = w + qt.get3();
129

    
130
      diff = xd*xd + yd*yd + zd*zd + wd*wd;
131

    
132
      if( diff < mindiff )
133
        {
134
        ret = q;
135
        mindiff = diff;
136
        }
137
      }
138

    
139
    return ret;
140
    }
141

    
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143

    
144
  void computeRotationRow()
145
    {
146
    for(int i=0; i<mNumAxis; i++)
147
      {
148
      mRotationRow[i] = mParent.computeRow(mCurrentPosition,i,mCubitType,mCurrentPuzzleFace);
149
      }
150
    }
151

    
152
///////////////////////////////////////////////////////////////////////////////////////////////////
153

    
154
  int computeAssociation()
155
    {
156
    int result = 0, accumulativeShift = 0;
157

    
158
    for(int axis=0; axis<mNumAxis; axis++)
159
      {
160
      result += (mRotationRow[axis]<<accumulativeShift);
161
      accumulativeShift += mParent.mMaxNumLayers;
162
      }
163

    
164
    return result;
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  private String createKey(String key)
170
    {
171
    return key+"_"+mCubitIndex+"_"+mOrigPosition[0]+"_"+mOrigPosition[1]+"_"+mOrigPosition[2];
172
    }
173

    
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175

    
176
  void savePreferences(String key, SharedPreferences.Editor editor)
177
    {
178
    editor.putInt(createKey(key), mQuatIndex);
179
    }
180

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

    
183
  void removePreferences(String key, SharedPreferences.Editor editor)
184
    {
185
    editor.remove(createKey(key));
186
    }
187

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

    
190
  int restorePreferences(String key, SharedPreferences preferences)
191
    {
192
    mQuatIndex = preferences.getInt(createKey(key), 0);
193
    return mQuatIndex;
194
    }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

    
198
  void rotateCubit(Static4D quat)
199
    {
200
    int len = mLen/3;
201

    
202
    for(int i=0; i<len; i++)
203
      {
204
      QuatHelper.rotateVectorByQuat( mTmp, mCurrentPosition[3*i], mCurrentPosition[3*i+1], mCurrentPosition[3*i+2], 0, quat);
205
      mCurrentPosition[3*i  ] = mTmp[0];
206
      mCurrentPosition[3*i+1] = mTmp[1];
207
      mCurrentPosition[3*i+2] = mTmp[2];
208
      mParent.clampPos(mCurrentPosition, 3*i);
209
      }
210

    
211
    if( mCubitType!=TYPE_NORMAL )
212
      {
213
      QuatHelper.rotateVectorByQuat( mTmp, mTrackingPoint[0], mTrackingPoint[1], mTrackingPoint[2], 0, quat);
214
      mTrackingPoint[0] = mTmp[0];
215
      mTrackingPoint[1] = mTmp[1];
216
      mTrackingPoint[2] = mTmp[2];
217
      mCurrentPuzzleFace = mParent.computeCurrentPuzzleFace(mCubitType,mTrackingPoint);
218
      }
219

    
220
    if( mCubitType==TYPE_DECIDER )
221
      {
222
      QuatHelper.rotateVectorByQuat( mTmp, mRowOffset[0], mRowOffset[1], mRowOffset[2], 0, quat);
223
      mRowOffset[0] = mTmp[0];
224
      mRowOffset[1] = mTmp[1];
225
      mRowOffset[2] = mTmp[2];
226
      }
227
    }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230

    
231
  int postRotateCubit(Static4D quat)
232
    {
233
    Static4D q = QuatHelper.quatMultiply(quat,mParent.mObjectQuats[mQuatIndex]);
234
    mQuatIndex = normalizeScrambleQuat(q);
235
    computeRotationRow();
236
    return mQuatIndex;
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

    
241
  void solve()
242
    {
243
    mQuatIndex = 0;
244
    mCurrentPuzzleFace = mOrigPuzzleFace;
245
    System.arraycopy(mOrigPosition, 0, mCurrentPosition, 0, mCurrentPosition.length);
246

    
247
    if( mCubitType!=TYPE_NORMAL )
248
      {
249
      mTrackingPoint = mParent.getTrackingPoint(mCubitIndex,mCubitType);
250
      if( mCubitType==TYPE_DECIDER )
251
        {
252
        mRowOffset[0] = mOrigOffsetX;
253
        mRowOffset[1] = mOrigOffsetY;
254
        mRowOffset[2] = mOrigOffsetZ;
255
        }
256
      }
257
    }
258

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

    
261
  void releaseResources()
262
    {
263
    mParent = null;
264
    }
265

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

    
268
  public int getType()
269
    {
270
    return mCubitType;
271
    }
272

    
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274

    
275
  public float[] getOffset()
276
    {
277
    return mRowOffset;
278
    }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

    
282
  public int getPuzzleFace()
283
    {
284
    return mCurrentPuzzleFace;
285
    }
286

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

    
289
  public int getRotRow(int axisIndex)
290
    {
291
    return mRotationRow[axisIndex];
292
    }
293
}
(1-1/13)