Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / main / TwistyObjectCubit.java @ 59d4ca91

1 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6 4c87f159 Leszek Koltunski
// 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 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10
package org.distorted.objectlib.main;
11
12
import android.content.SharedPreferences;
13
14 a706f8e0 Leszek Koltunski
import org.distorted.library.main.QuatHelper;
15 29b82486 Leszek Koltunski
import org.distorted.library.type.Static4D;
16
17
///////////////////////////////////////////////////////////////////////////////////////////////////
18
19 5618c5a9 Leszek Koltunski
public class TwistyObjectCubit
20 29b82486 Leszek Koltunski
  {
21 fbd18fc7 Leszek Koltunski
  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 4135693b Leszek Koltunski
  private final float[] mTmp;
26 29b82486 Leszek Koltunski
  private final float[] mOrigPosition;
27
  private final float[] mCurrentPosition;
28 7d2fe403 Leszek Koltunski
  private final float[] mRowOffset;
29
  private final float mOrigOffsetX, mOrigOffsetY, mOrigOffsetZ;
30 29b82486 Leszek Koltunski
  private final int mNumAxis;
31
  private final int mLen;
32
  private final int[] mRotationRow;
33 fbd18fc7 Leszek Koltunski
  private final int mCubitType;
34
  private final int mOrigPuzzleFace;
35 7d2fe403 Leszek Koltunski
  private final int mCubitIndex;
36 d85de775 Leszek Koltunski
  private final int mMaxLayers;
37 fbd18fc7 Leszek Koltunski
38 7d2fe403 Leszek Koltunski
  private float[] mTrackingPoint;
39 fbd18fc7 Leszek Koltunski
  private int mCurrentPuzzleFace;
40 29b82486 Leszek Koltunski
  private TwistyObject mParent;
41
42
  int mQuatIndex;
43
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45
46 5618c5a9 Leszek Koltunski
  TwistyObjectCubit(TwistyObject parent, float[] position, int numAxis, int maxLayers, int cubitIndex)
47 29b82486 Leszek Koltunski
    {
48
    mQuatIndex= 0;
49
    mParent   = parent;
50
    mLen      = position.length;
51 d85de775 Leszek Koltunski
    mMaxLayers= maxLayers;
52 29b82486 Leszek Koltunski
53 d844220f Leszek Koltunski
    mCubitType    = mParent.getCubitRotationType(cubitIndex);
54
    mRowOffset    = mParent.getCubitRowOffset(cubitIndex);
55
    mTrackingPoint= mParent.getTrackingPoint(cubitIndex,mCubitType);
56 1f329dcc Leszek Koltunski
    int face      = mParent.computeCurrentPuzzleFace(mCubitType,mTrackingPoint);
57 fbd18fc7 Leszek Koltunski
58 3a0a23bf Leszek Koltunski
    if( mRowOffset!=null )
59
      {
60
      mOrigOffsetX = mRowOffset[0];
61
      mOrigOffsetY = mRowOffset[1];
62
      mOrigOffsetZ = mRowOffset[2];
63
      if( mCubitType==TYPE_DECIDER ) mParent.setRotationRowOffset(face,mRowOffset);
64
      }
65
    else
66
      {
67
      mOrigOffsetX = 0;
68
      mOrigOffsetY = 0;
69
      mOrigOffsetZ = 0;
70
      }
71 fbd18fc7 Leszek Koltunski
72 7d2fe403 Leszek Koltunski
    mCubitIndex       = cubitIndex;
73 fbd18fc7 Leszek Koltunski
    mOrigPuzzleFace   = face;
74
    mCurrentPuzzleFace= face;
75
    mOrigPosition     = new float[mLen];
76
    mCurrentPosition  = new float[mLen];
77
    mTmp              = new float[4];
78 29b82486 Leszek Koltunski
79
    for(int i=0; i<mLen; i++)
80
      {
81
      mOrigPosition[i]    = position[i];
82
      mCurrentPosition[i] = position[i];
83
      }
84
85
    mNumAxis     = numAxis;
86
    mRotationRow = new int[mNumAxis];
87
    computeRotationRow();
88
    }
89
90
///////////////////////////////////////////////////////////////////////////////////////////////////
91
// Because of quatMultiplication, errors can accumulate - so to avoid this, we
92
// correct the value of the 'scramble' quat to what it should be - one of the legal quats from the
93
// list QUATS.
94
//
95
// We also have to remember that the group of unit quaternions is a double-cover of rotations
96
// in 3D ( q represents the same rotation as -q ) - so invert if needed.
97
98
  private int normalizeScrambleQuat(Static4D quat)
99
    {
100
    float x = quat.get0();
101
    float y = quat.get1();
102
    float z = quat.get2();
103
    float w = quat.get3();
104
    float xd,yd,zd,wd;
105
    float diff, mindiff = Float.MAX_VALUE;
106
    int ret=0;
107 d55d2c6a Leszek Koltunski
    int num_quats = mParent.mObjectQuats.length;
108 29b82486 Leszek Koltunski
    Static4D qt;
109
110
    for(int q=0; q<num_quats; q++)
111
      {
112 d55d2c6a Leszek Koltunski
      qt = mParent.mObjectQuats[q];
113 29b82486 Leszek Koltunski
114
      xd = x - qt.get0();
115
      yd = y - qt.get1();
116
      zd = z - qt.get2();
117
      wd = w - qt.get3();
118
119
      diff = xd*xd + yd*yd + zd*zd + wd*wd;
120
121
      if( diff < mindiff )
122
        {
123
        ret = q;
124
        mindiff = diff;
125
        }
126
127
      xd = x + qt.get0();
128
      yd = y + qt.get1();
129
      zd = z + qt.get2();
130
      wd = w + qt.get3();
131
132
      diff = xd*xd + yd*yd + zd*zd + wd*wd;
133
134
      if( diff < mindiff )
135
        {
136
        ret = q;
137
        mindiff = diff;
138
        }
139
      }
140
141
    return ret;
142
    }
143
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145
146 fbd18fc7 Leszek Koltunski
  void computeRotationRow()
147 29b82486 Leszek Koltunski
    {
148
    for(int i=0; i<mNumAxis; i++)
149
      {
150 fbd18fc7 Leszek Koltunski
      mRotationRow[i] = mParent.computeRow(mCurrentPosition,i,mCubitType,mCurrentPuzzleFace);
151 29b82486 Leszek Koltunski
      }
152
    }
153
154
///////////////////////////////////////////////////////////////////////////////////////////////////
155
156
  int computeAssociation()
157
    {
158
    int result = 0, accumulativeShift = 0;
159
160
    for(int axis=0; axis<mNumAxis; axis++)
161
      {
162
      result += (mRotationRow[axis]<<accumulativeShift);
163 d85de775 Leszek Koltunski
      accumulativeShift += mMaxLayers;
164 29b82486 Leszek Koltunski
      }
165
166
    return result;
167
    }
168
169 7cd287b9 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
170
171
  private String createKey(String key)
172
    {
173
    return key+"_"+mCubitIndex+"_"+mOrigPosition[0]+"_"+mOrigPosition[1]+"_"+mOrigPosition[2];
174
    }
175
176 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
177
178 405b22da Leszek Koltunski
  void savePreferences(String key, SharedPreferences.Editor editor)
179 29b82486 Leszek Koltunski
    {
180 7cd287b9 Leszek Koltunski
    editor.putInt(createKey(key), mQuatIndex);
181 29b82486 Leszek Koltunski
    }
182
183 ea739ec8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
184
185
  void removePreferences(String key, SharedPreferences.Editor editor)
186
    {
187 7cd287b9 Leszek Koltunski
    editor.remove(createKey(key));
188 ea739ec8 Leszek Koltunski
    }
189
190 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
191
192 405b22da Leszek Koltunski
  int restorePreferences(String key, SharedPreferences preferences)
193 29b82486 Leszek Koltunski
    {
194 7cd287b9 Leszek Koltunski
    mQuatIndex = preferences.getInt(createKey(key), 0);
195 29b82486 Leszek Koltunski
    return mQuatIndex;
196
    }
197
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199 1f329dcc Leszek Koltunski
// only for debugging
200 29b82486 Leszek Koltunski
201 1f329dcc Leszek Koltunski
  float[] getTrackingPoint()
202 fbd18fc7 Leszek Koltunski
    {
203 1f329dcc Leszek Koltunski
    return mTrackingPoint;
204
    }
205
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207
208
  boolean rotateCubit(Static4D quat)
209
    {
210
    boolean result = true;
211 fbd18fc7 Leszek Koltunski
    int len = mLen/3;
212
213
    for(int i=0; i<len; i++)
214
      {
215
      QuatHelper.rotateVectorByQuat( mTmp, mCurrentPosition[3*i], mCurrentPosition[3*i+1], mCurrentPosition[3*i+2], 0, quat);
216
      mCurrentPosition[3*i  ] = mTmp[0];
217
      mCurrentPosition[3*i+1] = mTmp[1];
218
      mCurrentPosition[3*i+2] = mTmp[2];
219
      mParent.clampPos(mCurrentPosition, 3*i);
220
      }
221
222
    if( mCubitType!=TYPE_NORMAL )
223
      {
224 d844220f Leszek Koltunski
      QuatHelper.rotateVectorByQuat( mTmp, mTrackingPoint[0], mTrackingPoint[1], mTrackingPoint[2], 0, quat);
225
      mTrackingPoint[0] = mTmp[0];
226
      mTrackingPoint[1] = mTmp[1];
227
      mTrackingPoint[2] = mTmp[2];
228 1f329dcc Leszek Koltunski
      mCurrentPuzzleFace = mParent.computeCurrentPuzzleFace(mCubitType,mTrackingPoint);
229
230
      if( mCurrentPuzzleFace<0 )  // unexpected error
231
        {
232
        mCurrentPuzzleFace = 0;
233
        result = false;
234
        }
235 fbd18fc7 Leszek Koltunski
      }
236
237
    if( mCubitType==TYPE_DECIDER )
238
      {
239
      QuatHelper.rotateVectorByQuat( mTmp, mRowOffset[0], mRowOffset[1], mRowOffset[2], 0, quat);
240
      mRowOffset[0] = mTmp[0];
241
      mRowOffset[1] = mTmp[1];
242
      mRowOffset[2] = mTmp[2];
243
      }
244 1f329dcc Leszek Koltunski
245
    return result;
246 fbd18fc7 Leszek Koltunski
    }
247
248
///////////////////////////////////////////////////////////////////////////////////////////////////
249
250
  int postRotateCubit(Static4D quat)
251 29b82486 Leszek Koltunski
    {
252 d55d2c6a Leszek Koltunski
    Static4D q = QuatHelper.quatMultiply(quat,mParent.mObjectQuats[mQuatIndex]);
253 29b82486 Leszek Koltunski
    mQuatIndex = normalizeScrambleQuat(q);
254 fbd18fc7 Leszek Koltunski
    computeRotationRow();
255 59d4ca91 Leszek Koltunski
256
 //   if( mCubitIndex==5 )
257
 //     android.util.Log.e("D", "index="+mCubitIndex+" quat: "+mQuatIndex);
258
259 fbd18fc7 Leszek Koltunski
    return mQuatIndex;
260
    }
261 29b82486 Leszek Koltunski
262
///////////////////////////////////////////////////////////////////////////////////////////////////
263
264
  void solve()
265
    {
266
    mQuatIndex = 0;
267 fbd18fc7 Leszek Koltunski
    mCurrentPuzzleFace = mOrigPuzzleFace;
268 29b82486 Leszek Koltunski
    System.arraycopy(mOrigPosition, 0, mCurrentPosition, 0, mCurrentPosition.length);
269 7d2fe403 Leszek Koltunski
270
    if( mCubitType!=TYPE_NORMAL )
271
      {
272
      mTrackingPoint = mParent.getTrackingPoint(mCubitIndex,mCubitType);
273
      if( mCubitType==TYPE_DECIDER )
274
        {
275
        mRowOffset[0] = mOrigOffsetX;
276
        mRowOffset[1] = mOrigOffsetY;
277
        mRowOffset[2] = mOrigOffsetZ;
278
        }
279
      }
280 29b82486 Leszek Koltunski
    }
281
282
///////////////////////////////////////////////////////////////////////////////////////////////////
283
284
  void releaseResources()
285
    {
286
    mParent = null;
287
    }
288
289 fbd18fc7 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
290
291 7aae846c Leszek Koltunski
  public int getType()
292 fbd18fc7 Leszek Koltunski
    {
293
    return mCubitType;
294
    }
295
296 7aae846c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
297
298
  public float[] getOffset()
299
    {
300
    return mRowOffset;
301
    }
302
303 5a20f7a1 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
304
305
  public int getPuzzleFace()
306
    {
307
    return mCurrentPuzzleFace;
308
    }
309
310 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
311
312 92a6fc8b Leszek Koltunski
  public int getRotRow(int axisIndex)
313 29b82486 Leszek Koltunski
    {
314 92a6fc8b Leszek Koltunski
    return mRotationRow[axisIndex];
315 29b82486 Leszek Koltunski
    }
316
}