| 29 |
29 |
{
|
| 30 |
30 |
int mRotationVect, mLastTouchedAxis;
|
| 31 |
31 |
|
| 32 |
|
private float[] mPoint, mCamera, mDiff, mTouch, m2Dpoint;
|
|
32 |
private float[] mPoint, mCamera, mDiff, mTouch;
|
|
33 |
private float[] mPoint2D, mMove2D;
|
|
34 |
private float[][][] mCastAxis;
|
| 33 |
35 |
private int mLastTouchedLR;
|
| 34 |
36 |
private int mNumAxis, mNumFacesPerAxis;
|
| 35 |
37 |
private int[] mPossible;
|
| 36 |
|
private float mDistanceCenterFace;
|
|
38 |
private float mDistanceCenterFace3D, mDistanceCenterFace2D;
|
| 37 |
39 |
private Static3D[] mAxis;
|
| 38 |
40 |
|
| 39 |
41 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| 40 |
42 |
|
| 41 |
43 |
abstract boolean isInsideFace(float[] point);
|
| 42 |
|
abstract float fillUpRotationVectAndOffset(float[] vect, float[] touch, int[] possible);
|
| 43 |
44 |
abstract float returnAngle(float[] vect, int[] possible);
|
| 44 |
45 |
abstract void fillPossibleRotations(int axis, int[] output);
|
| 45 |
46 |
|
| 46 |
47 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| 47 |
48 |
|
| 48 |
|
RubikObjectMovement(Static3D[] axis, int numFacesPerAxis, float distance)
|
|
49 |
RubikObjectMovement(Static3D[] axis, int numFacesPerAxis, float distance3D, float distance2D)
|
| 49 |
50 |
{
|
| 50 |
51 |
mPoint = new float[3];
|
| 51 |
52 |
mCamera= new float[3];
|
| 52 |
53 |
mDiff = new float[3];
|
| 53 |
54 |
mTouch = new float[3];
|
| 54 |
55 |
|
| 55 |
|
m2Dpoint = new float[2];
|
|
56 |
mPoint2D = new float[2];
|
|
57 |
mMove2D = new float[2];
|
| 56 |
58 |
|
| 57 |
59 |
mAxis = axis;
|
| 58 |
60 |
mNumAxis = mAxis.length;
|
| 59 |
61 |
mNumFacesPerAxis = numFacesPerAxis;
|
| 60 |
|
mDistanceCenterFace = distance;
|
|
62 |
mDistanceCenterFace3D = distance3D; // distance from the center of the object to each of its faces
|
|
63 |
mDistanceCenterFace2D = distance2D; // distance from the center of a face to its edge
|
| 61 |
64 |
mPossible = new int[mNumAxis-1];
|
|
65 |
|
|
66 |
// mCastAxis[1][2]{0,1} are the 2D coords of the 2nd axis cast onto the face defined by the
|
|
67 |
// 1st pair (axis,lr)
|
|
68 |
mCastAxis = new float[mNumAxis*mNumFacesPerAxis][mNumAxis][2];
|
|
69 |
|
|
70 |
for( int casted=0; casted<mNumAxis; casted++)
|
|
71 |
{
|
|
72 |
Static3D a = mAxis[casted];
|
|
73 |
mPoint[0]= a.get0();
|
|
74 |
mPoint[1]= a.get1();
|
|
75 |
mPoint[2]= a.get2();
|
|
76 |
|
|
77 |
for( int surface=0; surface<mNumAxis; surface++)
|
|
78 |
for(int lr=0; lr<mNumFacesPerAxis; lr++)
|
|
79 |
{
|
|
80 |
int index = surface*mNumFacesPerAxis + lr;
|
|
81 |
|
|
82 |
if( casted!=surface )
|
|
83 |
{
|
|
84 |
convertTo2Dcoords( mPoint, mAxis[surface], lr, mPoint2D);
|
|
85 |
mCastAxis[index][casted][0] = mPoint2D[0];
|
|
86 |
mCastAxis[index][casted][1] = mPoint2D[1];
|
|
87 |
normalize2D(mCastAxis[index][casted]);
|
|
88 |
}
|
|
89 |
else
|
|
90 |
{
|
|
91 |
mCastAxis[index][casted][0] = 0;
|
|
92 |
mCastAxis[index][casted][1] = 0;
|
|
93 |
}
|
|
94 |
}
|
|
95 |
}
|
|
96 |
}
|
|
97 |
|
|
98 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
99 |
|
|
100 |
private void normalize2D(float[] vect)
|
|
101 |
{
|
|
102 |
float len = (float)Math.sqrt(vect[0]*vect[0] + vect[1]*vect[1]);
|
|
103 |
vect[0] /= len;
|
|
104 |
vect[1] /= len;
|
|
105 |
}
|
|
106 |
|
|
107 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
108 |
// find the casted axis with which our move2D vector forms an angle closest to 90 deg.
|
|
109 |
|
|
110 |
private int computeRotationVect(int axis, int lr, float[] move2D)
|
|
111 |
{
|
|
112 |
float cosAngle, minCosAngle = Float.MAX_VALUE;
|
|
113 |
int minIndex=-1;
|
|
114 |
int index = axis*mNumFacesPerAxis + lr;
|
|
115 |
float m0 = move2D[0];
|
|
116 |
float m1 = move2D[1];
|
|
117 |
float len = (float)Math.sqrt(m0*m0 + m1*m1);
|
|
118 |
m0 /= len;
|
|
119 |
m1 /= len;
|
|
120 |
|
|
121 |
for(int i=0; i<mNumAxis; i++)
|
|
122 |
{
|
|
123 |
if( axis != i )
|
|
124 |
{
|
|
125 |
cosAngle = m0*mCastAxis[index][i][0] + m1*mCastAxis[index][i][1];
|
|
126 |
if( cosAngle<0 ) cosAngle = -cosAngle;
|
|
127 |
|
|
128 |
if( cosAngle<minCosAngle )
|
|
129 |
{
|
|
130 |
minCosAngle=cosAngle;
|
|
131 |
minIndex = i;
|
|
132 |
}
|
|
133 |
}
|
|
134 |
}
|
|
135 |
|
|
136 |
return minIndex;
|
|
137 |
}
|
|
138 |
|
|
139 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
140 |
|
|
141 |
private float computeOffset(float[] point, float[] axis)
|
|
142 |
{
|
|
143 |
return point[0]*axis[0] + point[1]*axis[1] + mDistanceCenterFace2D;
|
| 62 |
144 |
}
|
| 63 |
145 |
|
| 64 |
146 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| ... | ... | |
| 66 |
148 |
private boolean faceIsVisible(Static3D axis, int lr)
|
| 67 |
149 |
{
|
| 68 |
150 |
float castCameraOnAxis = mCamera[0]*axis.get0() + mCamera[1]*axis.get1() + mCamera[2]*axis.get2();
|
| 69 |
|
return (2*lr-1)*castCameraOnAxis > mDistanceCenterFace;
|
|
151 |
return (2*lr-1)*castCameraOnAxis > mDistanceCenterFace3D;
|
| 70 |
152 |
}
|
| 71 |
153 |
|
| 72 |
154 |
///////////////////////////////////////////////////////////////////////////////////////////////////
|
| ... | ... | |
| 93 |
175 |
if( denom != 0.0f )
|
| 94 |
176 |
{
|
| 95 |
177 |
float axisCam = a0*mCamera[0] + a1*mCamera[1] + a2*mCamera[2];
|
| 96 |
|
float distance = (2*lr-1)*mDistanceCenterFace;
|
|
178 |
float distance = (2*lr-1)*mDistanceCenterFace3D;
|
| 97 |
179 |
float alpha = (distance-axisCam)/denom;
|
| 98 |
180 |
|
| 99 |
181 |
output[0] = mCamera[0] + d0*alpha;
|
| ... | ... | |
| 162 |
244 |
{
|
| 163 |
245 |
switch(axis)
|
| 164 |
246 |
{
|
| 165 |
|
case 0: return "yellow ";
|
| 166 |
|
case 1: return "green ";
|
| 167 |
|
case 2: return "blue ";
|
| 168 |
|
case 3: return "red ";
|
|
247 |
case 0: return "yellow (bottom) ";
|
|
248 |
case 1: return "green (back) ";
|
|
249 |
case 2: return "blue (right) ";
|
|
250 |
case 3: return "red (left) ";
|
| 169 |
251 |
}
|
| 170 |
252 |
|
| 171 |
253 |
return null;
|
| ... | ... | |
| 192 |
274 |
if( faceIsVisible(mAxis[mLastTouchedAxis], mLastTouchedLR) )
|
| 193 |
275 |
{
|
| 194 |
276 |
castTouchPointOntoFace(mAxis[mLastTouchedAxis], mLastTouchedLR, mTouch);
|
| 195 |
|
convertTo2Dcoords(mTouch, mAxis[mLastTouchedAxis], mLastTouchedLR, m2Dpoint);
|
|
277 |
convertTo2Dcoords(mTouch, mAxis[mLastTouchedAxis], mLastTouchedLR, mPoint2D);
|
| 196 |
278 |
|
| 197 |
|
if( isInsideFace(m2Dpoint) )
|
|
279 |
if( isInsideFace(mPoint2D) )
|
| 198 |
280 |
{
|
| 199 |
|
android.util.Log.e("move", "face "+getFaceColor(mLastTouchedAxis)+" ("+m2Dpoint[0]+","+m2Dpoint[1]+")");
|
|
281 |
android.util.Log.e("move", "face "+getFaceColor(mLastTouchedAxis)+" ("+mPoint2D[0]+","+mPoint2D[1]+")");
|
| 200 |
282 |
|
| 201 |
283 |
fillPossibleRotations(mLastTouchedAxis, mPossible);
|
| 202 |
284 |
return true;
|
| ... | ... | |
| 216 |
298 |
mPoint[1] = rotatedTouchPoint.get1()/RubikObject.OBJECT_SCREEN_RATIO;
|
| 217 |
299 |
mPoint[2] = rotatedTouchPoint.get2()/RubikObject.OBJECT_SCREEN_RATIO;
|
| 218 |
300 |
|
| 219 |
|
castTouchPointOntoFace(mAxis[mLastTouchedAxis], mLastTouchedLR, mDiff);
|
|
301 |
castTouchPointOntoFace(mAxis[mLastTouchedAxis], mLastTouchedLR, mTouch);
|
|
302 |
convertTo2Dcoords(mTouch, mAxis[mLastTouchedAxis], mLastTouchedLR, mMove2D);
|
|
303 |
|
|
304 |
mMove2D[0] -= mPoint2D[0];
|
|
305 |
mMove2D[1] -= mPoint2D[1];
|
|
306 |
|
|
307 |
mRotationVect= computeRotationVect(mLastTouchedAxis, mLastTouchedLR, mMove2D);
|
|
308 |
int index = mLastTouchedAxis*mNumFacesPerAxis+mLastTouchedLR;
|
|
309 |
float offset = computeOffset(mPoint2D, mCastAxis[index][mRotationVect]);
|
| 220 |
310 |
|
| 221 |
|
mDiff[0] -= mTouch[0];
|
| 222 |
|
mDiff[1] -= mTouch[1];
|
| 223 |
|
mDiff[2] -= mTouch[2];
|
|
311 |
android.util.Log.d("move", "new rot: face "+getFaceColor(mLastTouchedAxis)+" vect: "+mRotationVect+" offset: "+offset);
|
| 224 |
312 |
|
| 225 |
|
float offset = fillUpRotationVectAndOffset(mDiff, mTouch, mPossible);
|
| 226 |
313 |
return new Static2D(mRotationVect,offset);
|
| 227 |
314 |
}
|
| 228 |
315 |
|
Progress with object Movement. Assigning new Rotations works now, independently of object type.