Project

General

Profile

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

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

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 int mNumAxis;
39
  private final int mLen;
40
  private final int[] mRotationRow;
41
  private final int mCubitType;
42
  private final float[] mRowOffset;
43
  private final float[] mTrackingPoint;
44
  private final int mOrigPuzzleFace;
45

    
46
  private int mCurrentPuzzleFace;
47
  private TwistyObject mParent;
48

    
49
  int mQuatIndex;
50

    
51
///////////////////////////////////////////////////////////////////////////////////////////////////
52

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

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

    
64
    if( mCubitType==TYPE_DECIDER ) mParent.setRotationRowOffset(face,mRowOffset);
65

    
66
    mOrigPuzzleFace   = face;
67
    mCurrentPuzzleFace= face;
68
    mOrigPosition     = new float[mLen];
69
    mCurrentPosition  = new float[mLen];
70
    mTmp              = new float[4];
71

    
72
    for(int i=0; i<mLen; i++)
73
      {
74
      mOrigPosition[i]    = position[i];
75
      mCurrentPosition[i] = position[i];
76
      }
77

    
78
    mNumAxis     = numAxis;
79
    mRotationRow = new int[mNumAxis];
80
    computeRotationRow();
81
    }
82

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

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

    
103
    for(int q=0; q<num_quats; q++)
104
      {
105
      qt = mParent.mObjectQuats[q];
106

    
107
      xd = x - qt.get0();
108
      yd = y - qt.get1();
109
      zd = z - qt.get2();
110
      wd = w - qt.get3();
111

    
112
      diff = xd*xd + yd*yd + zd*zd + wd*wd;
113

    
114
      if( diff < mindiff )
115
        {
116
        ret = q;
117
        mindiff = diff;
118
        }
119

    
120
      xd = x + qt.get0();
121
      yd = y + qt.get1();
122
      zd = z + qt.get2();
123
      wd = w + qt.get3();
124

    
125
      diff = xd*xd + yd*yd + zd*zd + wd*wd;
126

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

    
134
    return ret;
135
    }
136

    
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

    
139
  void computeRotationRow()
140
    {
141
    for(int i=0; i<mNumAxis; i++)
142
      {
143
      mRotationRow[i] = mParent.computeRow(mCurrentPosition,i,mCubitType,mCurrentPuzzleFace);
144
      }
145
    }
146

    
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148

    
149
  int computeAssociation()
150
    {
151
    int result = 0, accumulativeShift = 0;
152

    
153
    for(int axis=0; axis<mNumAxis; axis++)
154
      {
155
      result += (mRotationRow[axis]<<accumulativeShift);
156
      accumulativeShift += mParent.mMaxNumLayers;
157
      }
158

    
159
    return result;
160
    }
161

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

    
164
  void savePreferences(String key, SharedPreferences.Editor editor)
165
    {
166
    String k = key+"_"+mOrigPosition[0]+"_"+mOrigPosition[1]+"_"+mOrigPosition[2];
167
    editor.putInt(k, mQuatIndex);
168
    }
169

    
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171

    
172
  void removePreferences(String key, SharedPreferences.Editor editor)
173
    {
174
    String k = key+"_"+mOrigPosition[0]+"_"+mOrigPosition[1]+"_"+mOrigPosition[2];
175
    editor.remove(k);
176
    }
177

    
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

    
180
  int restorePreferences(String key, SharedPreferences preferences)
181
    {
182
    String k = key+"_"+mOrigPosition[0]+"_"+mOrigPosition[1]+"_"+mOrigPosition[2];
183
    mQuatIndex = preferences.getInt(k, 0);
184
    return mQuatIndex;
185
    }
186

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

    
189
  void rotateCubit(Static4D quat)
190
    {
191
    int len = mLen/3;
192

    
193
    for(int i=0; i<len; i++)
194
      {
195
      QuatHelper.rotateVectorByQuat( mTmp, mCurrentPosition[3*i], mCurrentPosition[3*i+1], mCurrentPosition[3*i+2], 0, quat);
196

    
197
      mCurrentPosition[3*i  ] = mTmp[0];
198
      mCurrentPosition[3*i+1] = mTmp[1];
199
      mCurrentPosition[3*i+2] = mTmp[2];
200

    
201
      mParent.clampPos(mCurrentPosition, 3*i);
202
      }
203

    
204
    if( mCubitType!=TYPE_NORMAL )
205
      {
206
      QuatHelper.rotateVectorByQuat( mTmp, mTrackingPoint[0], mTrackingPoint[1], mTrackingPoint[2], 0, quat);
207
      mTrackingPoint[0] = mTmp[0];
208
      mTrackingPoint[1] = mTmp[1];
209
      mTrackingPoint[2] = mTmp[2];
210
      mCurrentPuzzleFace = mParent.computeCurrentPuzzleFace(mCubitType,mTrackingPoint);
211
      }
212

    
213
    if( mCubitType==TYPE_DECIDER )
214
      {
215
      QuatHelper.rotateVectorByQuat( mTmp, mRowOffset[0], mRowOffset[1], mRowOffset[2], 0, quat);
216
      mRowOffset[0] = mTmp[0];
217
      mRowOffset[1] = mTmp[1];
218
      mRowOffset[2] = mTmp[2];
219
      mParent.setRotationRowOffset(mCurrentPuzzleFace,mRowOffset);
220
      }
221
    }
222

    
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224

    
225
  int postRotateCubit(Static4D quat)
226
    {
227
    Static4D q = QuatHelper.quatMultiply(quat,mParent.mObjectQuats[mQuatIndex]);
228
    mQuatIndex = normalizeScrambleQuat(q);
229
    computeRotationRow();
230
    return mQuatIndex;
231
    }
232

    
233

    
234
///////////////////////////////////////////////////////////////////////////////////////////////////
235
// a DECIDER cubit (e.g. Crazy 3x3 Planet face center) has just moved. We need to re-adjust the
236
// RotRows of all the Follower cubits, even those that do not belong to the rotation.
237

    
238
  void adjustRotRowPostRotateADecider()
239
    {
240
    computeRotationRow();
241
    }
242

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244

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

    
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

    
255
  void releaseResources()
256
    {
257
    mParent = null;
258
    }
259

    
260
///////////////////////////////////////////////////////////////////////////////////////////////////
261

    
262
  public int getCubitType()
263
    {
264
    return mCubitType;
265
    }
266

    
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268

    
269
  public int getRotRow(int axisIndex)
270
    {
271
    return mRotationRow[axisIndex];
272
    }
273
}
(1-1/13)