Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / main / TwistyObjectCubit.java @ 2fa1601b

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