Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / main / Cubit.java @ 3a0a23bf

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 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.objectlib.main;
21

    
22
import android.content.SharedPreferences;
23

    
24
import org.distorted.library.main.QuatHelper;
25
import org.distorted.library.type.Static4D;
26

    
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28

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

    
35
  private final float[] mTmp;
36
  private final float[] mOrigPosition;
37
  private final float[] mCurrentPosition;
38
  private final float[] mRowOffset;
39
  private final float mOrigOffsetX, mOrigOffsetY, mOrigOffsetZ;
40
  private final int mNumAxis;
41
  private final int mLen;
42
  private final int[] mRotationRow;
43
  private final int mCubitType;
44
  private final int mOrigPuzzleFace;
45
  private final int mCubitIndex;
46

    
47
  private float[] mTrackingPoint;
48
  private int mCurrentPuzzleFace;
49
  private TwistyObject mParent;
50

    
51
  int mQuatIndex;
52

    
53
///////////////////////////////////////////////////////////////////////////////////////////////////
54

    
55
  Cubit(TwistyObject parent, float[] position, int numAxis, int cubitIndex)
56
    {
57
    mQuatIndex= 0;
58
    mParent   = parent;
59
    mLen      = position.length;
60

    
61
    mCubitType    = mParent.getCubitRotationType(cubitIndex);
62
    mRowOffset    = mParent.getCubitRowOffset(cubitIndex);
63
    mTrackingPoint= mParent.getTrackingPoint(cubitIndex,mCubitType);
64
    int face      = mParent.computeCurrentPuzzleFace(mCubitType,mTrackingPoint);
65

    
66
    if( mRowOffset!=null )
67
      {
68
      mOrigOffsetX = mRowOffset[0];
69
      mOrigOffsetY = mRowOffset[1];
70
      mOrigOffsetZ = mRowOffset[2];
71
      if( mCubitType==TYPE_DECIDER ) mParent.setRotationRowOffset(face,mRowOffset);
72
      }
73
    else
74
      {
75
      mOrigOffsetX = 0;
76
      mOrigOffsetY = 0;
77
      mOrigOffsetZ = 0;
78
      }
79

    
80
    mCubitIndex       = cubitIndex;
81
    mOrigPuzzleFace   = face;
82
    mCurrentPuzzleFace= face;
83
    mOrigPosition     = new float[mLen];
84
    mCurrentPosition  = new float[mLen];
85
    mTmp              = new float[4];
86

    
87
    for(int i=0; i<mLen; i++)
88
      {
89
      mOrigPosition[i]    = position[i];
90
      mCurrentPosition[i] = position[i];
91
      }
92

    
93
    mNumAxis     = numAxis;
94
    mRotationRow = new int[mNumAxis];
95
    computeRotationRow();
96
    }
97

    
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99
// Because of quatMultiplication, errors can accumulate - so to avoid this, we
100
// correct the value of the 'scramble' quat to what it should be - one of the legal quats from the
101
// list QUATS.
102
//
103
// We also have to remember that the group of unit quaternions is a double-cover of rotations
104
// in 3D ( q represents the same rotation as -q ) - so invert if needed.
105

    
106
  private int normalizeScrambleQuat(Static4D quat)
107
    {
108
    float x = quat.get0();
109
    float y = quat.get1();
110
    float z = quat.get2();
111
    float w = quat.get3();
112
    float xd,yd,zd,wd;
113
    float diff, mindiff = Float.MAX_VALUE;
114
    int ret=0;
115
    int num_quats = mParent.mObjectQuats.length;
116
    Static4D qt;
117

    
118
    for(int q=0; q<num_quats; q++)
119
      {
120
      qt = mParent.mObjectQuats[q];
121

    
122
      xd = x - qt.get0();
123
      yd = y - qt.get1();
124
      zd = z - qt.get2();
125
      wd = w - qt.get3();
126

    
127
      diff = xd*xd + yd*yd + zd*zd + wd*wd;
128

    
129
      if( diff < mindiff )
130
        {
131
        ret = q;
132
        mindiff = diff;
133
        }
134

    
135
      xd = x + qt.get0();
136
      yd = y + qt.get1();
137
      zd = z + qt.get2();
138
      wd = w + qt.get3();
139

    
140
      diff = xd*xd + yd*yd + zd*zd + wd*wd;
141

    
142
      if( diff < mindiff )
143
        {
144
        ret = q;
145
        mindiff = diff;
146
        }
147
      }
148

    
149
    return ret;
150
    }
151

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

    
154
  void computeRotationRow()
155
    {
156
    for(int i=0; i<mNumAxis; i++)
157
      {
158
      mRotationRow[i] = mParent.computeRow(mCurrentPosition,i,mCubitType,mCurrentPuzzleFace);
159
      }
160
    }
161

    
162
///////////////////////////////////////////////////////////////////////////////////////////////////
163

    
164
  int computeAssociation()
165
    {
166
    int result = 0, accumulativeShift = 0;
167

    
168
    for(int axis=0; axis<mNumAxis; axis++)
169
      {
170
      result += (mRotationRow[axis]<<accumulativeShift);
171
      accumulativeShift += mParent.mMaxNumLayers;
172
      }
173

    
174
    return result;
175
    }
176

    
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178

    
179
  void savePreferences(String key, SharedPreferences.Editor editor)
180
    {
181
    String k = key+"_"+mOrigPosition[0]+"_"+mOrigPosition[1]+"_"+mOrigPosition[2];
182
    editor.putInt(k, mQuatIndex);
183
    }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186

    
187
  void removePreferences(String key, SharedPreferences.Editor editor)
188
    {
189
    String k = key+"_"+mOrigPosition[0]+"_"+mOrigPosition[1]+"_"+mOrigPosition[2];
190
    editor.remove(k);
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
  int restorePreferences(String key, SharedPreferences preferences)
196
    {
197
    String k = key+"_"+mOrigPosition[0]+"_"+mOrigPosition[1]+"_"+mOrigPosition[2];
198
    mQuatIndex = preferences.getInt(k, 0);
199
    return mQuatIndex;
200
    }
201

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
  void rotateCubit(Static4D quat)
205
    {
206
    int len = mLen/3;
207

    
208
    for(int i=0; i<len; i++)
209
      {
210
      QuatHelper.rotateVectorByQuat( mTmp, mCurrentPosition[3*i], mCurrentPosition[3*i+1], mCurrentPosition[3*i+2], 0, quat);
211
      mCurrentPosition[3*i  ] = mTmp[0];
212
      mCurrentPosition[3*i+1] = mTmp[1];
213
      mCurrentPosition[3*i+2] = mTmp[2];
214
      mParent.clampPos(mCurrentPosition, 3*i);
215
      }
216

    
217
    if( mCubitType!=TYPE_NORMAL )
218
      {
219
      QuatHelper.rotateVectorByQuat( mTmp, mTrackingPoint[0], mTrackingPoint[1], mTrackingPoint[2], 0, quat);
220
      mTrackingPoint[0] = mTmp[0];
221
      mTrackingPoint[1] = mTmp[1];
222
      mTrackingPoint[2] = mTmp[2];
223
      mCurrentPuzzleFace = mParent.computeCurrentPuzzleFace(mCubitType,mTrackingPoint);
224
      }
225

    
226
    if( mCubitType==TYPE_DECIDER )
227
      {
228
      QuatHelper.rotateVectorByQuat( mTmp, mRowOffset[0], mRowOffset[1], mRowOffset[2], 0, quat);
229
      mRowOffset[0] = mTmp[0];
230
      mRowOffset[1] = mTmp[1];
231
      mRowOffset[2] = mTmp[2];
232
      }
233
    }
234

    
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236

    
237
  int postRotateCubit(Static4D quat)
238
    {
239
    Static4D q = QuatHelper.quatMultiply(quat,mParent.mObjectQuats[mQuatIndex]);
240
    mQuatIndex = normalizeScrambleQuat(q);
241
    computeRotationRow();
242
    return mQuatIndex;
243
    }
244

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

    
247
  void solve()
248
    {
249
    mQuatIndex = 0;
250
    mCurrentPuzzleFace = mOrigPuzzleFace;
251
    System.arraycopy(mOrigPosition, 0, mCurrentPosition, 0, mCurrentPosition.length);
252

    
253
    if( mCubitType!=TYPE_NORMAL )
254
      {
255
      mTrackingPoint = mParent.getTrackingPoint(mCubitIndex,mCubitType);
256
      if( mCubitType==TYPE_DECIDER )
257
        {
258
        mRowOffset[0] = mOrigOffsetX;
259
        mRowOffset[1] = mOrigOffsetY;
260
        mRowOffset[2] = mOrigOffsetZ;
261
        }
262
      }
263
    }
264

    
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266

    
267
  void releaseResources()
268
    {
269
    mParent = null;
270
    }
271

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273

    
274
  public int getType()
275
    {
276
    return mCubitType;
277
    }
278

    
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280

    
281
  public float[] getOffset()
282
    {
283
    return mRowOffset;
284
    }
285

    
286
///////////////////////////////////////////////////////////////////////////////////////////////////
287

    
288
  public int getPuzzleFace()
289
    {
290
    return mCurrentPuzzleFace;
291
    }
292

    
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294

    
295
  public int getRotRow(int axisIndex)
296
    {
297
    return mRotationRow[axisIndex];
298
    }
299
}
(1-1/13)