Project

General

Profile

Download (7.39 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / objectlib / Cubit.java @ 588ace55

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;
21

    
22
import android.content.SharedPreferences;
23

    
24
import org.distorted.library.type.Static4D;
25

    
26
///////////////////////////////////////////////////////////////////////////////////////////////////
27

    
28
public class Cubit
29
  {
30
  private final float[] mOrigPosition;
31
  private final float[] mCurrentPosition;
32
  private final int mNumAxis;
33
  private final int mLen;
34
  private final int[] mRotationRow;
35
  private TwistyObject mParent;
36

    
37
  int mQuatIndex;
38

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

    
41
  Cubit(TwistyObject parent, float[] position, int numAxis)
42
    {
43
    mQuatIndex= 0;
44
    mParent   = parent;
45
    mLen      = position.length;
46

    
47
    mOrigPosition    = new float[mLen];
48
    mCurrentPosition = new float[mLen];
49

    
50
    for(int i=0; i<mLen; i++)
51
      {
52
      mOrigPosition[i]    = position[i];
53
      mCurrentPosition[i] = position[i];
54
      }
55

    
56
    mNumAxis     = numAxis;
57
    mRotationRow = new int[mNumAxis];
58
    computeRotationRow();
59
    }
60

    
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62
// Because of quatMultiplication, errors can accumulate - so to avoid this, we
63
// correct the value of the 'scramble' quat to what it should be - one of the legal quats from the
64
// list QUATS.
65
//
66
// We also have to remember that the group of unit quaternions is a double-cover of rotations
67
// in 3D ( q represents the same rotation as -q ) - so invert if needed.
68

    
69
  private int normalizeScrambleQuat(Static4D quat)
70
    {
71
    float x = quat.get0();
72
    float y = quat.get1();
73
    float z = quat.get2();
74
    float w = quat.get3();
75
    float xd,yd,zd,wd;
76
    float diff, mindiff = Float.MAX_VALUE;
77
    int ret=0;
78
    int num_quats = mParent.OBJECT_QUATS.length;
79
    Static4D qt;
80

    
81
    for(int q=0; q<num_quats; q++)
82
      {
83
      qt = mParent.OBJECT_QUATS[q];
84

    
85
      xd = x - qt.get0();
86
      yd = y - qt.get1();
87
      zd = z - qt.get2();
88
      wd = w - qt.get3();
89

    
90
      diff = xd*xd + yd*yd + zd*zd + wd*wd;
91

    
92
      if( diff < mindiff )
93
        {
94
        ret = q;
95
        mindiff = diff;
96
        }
97

    
98
      xd = x + qt.get0();
99
      yd = y + qt.get1();
100
      zd = z + qt.get2();
101
      wd = w + qt.get3();
102

    
103
      diff = xd*xd + yd*yd + zd*zd + wd*wd;
104

    
105
      if( diff < mindiff )
106
        {
107
        ret = q;
108
        mindiff = diff;
109
        }
110
      }
111

    
112
    return ret;
113
    }
114

    
115
///////////////////////////////////////////////////////////////////////////////////////////////////
116

    
117
  private void computeRotationRow()
118
    {
119
    for(int i=0; i<mNumAxis; i++)
120
      {
121
      mRotationRow[i] = mParent.computeRow(mCurrentPosition,i);
122
      }
123
    }
124

    
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126

    
127
  void modifyCurrentPosition(Static4D quat)
128
    {
129
    Static4D cubitCenter;
130
    Static4D rotatedCenter;
131
    int len = mLen/3;
132

    
133
    for(int i=0; i<len; i++)
134
      {
135
      cubitCenter =  new Static4D(mCurrentPosition[3*i], mCurrentPosition[3*i+1], mCurrentPosition[3*i+2], 0);
136
      rotatedCenter = QuatHelper.rotateVectorByQuat( cubitCenter, quat);
137

    
138
      mCurrentPosition[3*i  ] = rotatedCenter.get0();
139
      mCurrentPosition[3*i+1] = rotatedCenter.get1();
140
      mCurrentPosition[3*i+2] = rotatedCenter.get2();
141

    
142
      mParent.clampPos(mCurrentPosition, 3*i);
143
      }
144

    
145
    computeRotationRow();
146
    }
147

    
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

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

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

    
160
    return result;
161
    }
162

    
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164

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

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172

    
173
  int restorePreferences(SharedPreferences preferences)
174
    {
175
    String number = mOrigPosition[0]+"_"+mOrigPosition[1]+"_"+mOrigPosition[2];
176
    mQuatIndex = preferences.getInt("q_"+number, 0);
177
    return mQuatIndex;
178
    }
179

    
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181

    
182
  int removeRotationNow(Static4D quat)
183
    {
184
    Static4D q = QuatHelper.quatMultiply(quat,mParent.OBJECT_QUATS[mQuatIndex]);
185
    mQuatIndex = normalizeScrambleQuat(q);
186

    
187
    modifyCurrentPosition(quat);
188

    
189
    return mQuatIndex;
190
    }
191

    
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

    
194
  void solve()
195
    {
196
    mQuatIndex = 0;
197
    System.arraycopy(mOrigPosition, 0, mCurrentPosition, 0, mCurrentPosition.length);
198
    computeRotationRow();
199
    }
200

    
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202

    
203
  void releaseResources()
204
    {
205
    mParent = null;
206
    }
207

    
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209
// this is only needed for MODE_REPLACE objects (i.e. - currently - CUBE_3), so it is enough to only
210
// take into consideration the first position.
211

    
212
  float getDistSquared(float[] point)
213
    {
214
    float dx = mCurrentPosition[0] - point[0];
215
    float dy = mCurrentPosition[1] - point[1];
216
    float dz = mCurrentPosition[2] - point[2];
217

    
218
    return dx*dx + dy*dy + dz*dz;
219
    }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

    
223
  public int getRotRow(int index)
224
    {
225
    return mRotationRow[index];
226
    }
227
}
(1-1/21)