Revision efef689c
Added by Leszek Koltunski almost 5 years ago
src/main/java/org/distorted/effect/scramble/ScrambleEffect.java | ||
---|---|---|
23 | 23 |
import org.distorted.library.effect.Effect; |
24 | 24 |
import org.distorted.library.main.DistortedEffects; |
25 | 25 |
import org.distorted.library.message.EffectListener; |
26 |
import org.distorted.library.type.Static3D; |
|
27 | 26 |
import org.distorted.magic.RubikRenderer; |
28 | 27 |
import org.distorted.object.RubikObject; |
29 | 28 |
|
... | ... | |
52 | 51 |
private static final int FAKE_EFFECT_ID = -3; |
53 | 52 |
private static final Type[] types; |
54 | 53 |
|
55 |
private static final Static3D VECTX = new Static3D(1,0,0); |
|
56 |
private static final Static3D VECTY = new Static3D(0,1,0); |
|
57 |
private static final Static3D VECTZ = new Static3D(0,0,1); |
|
58 |
private static final Static3D VECTU = new Static3D(0,0,0); |
|
59 |
|
|
60 |
private static final Static3D[] VECTORS = { VECTX, VECTY, VECTZ, VECTZ }; |
|
61 |
|
|
62 | 54 |
static |
63 | 55 |
{ |
64 | 56 |
int i=0; |
... | ... | |
156 | 148 |
android.util.Log.e("effect", "ERROR: "+mNumDoubleScramblesLeft); |
157 | 149 |
} |
158 | 150 |
|
159 |
mCurrentBaseEffectID = mObject.addNewRotation(VECTORS[mLastVector], row, angle*90, durationMillis, this );
|
|
151 |
mCurrentBaseEffectID = mObject.addNewRotation(mLastVector, row, angle*90, durationMillis, this );
|
|
160 | 152 |
} |
161 | 153 |
else |
162 | 154 |
{ |
src/main/java/org/distorted/magic/RubikSurfaceView.java | ||
---|---|---|
265 | 265 |
Static4D touchPoint2 = new Static4D(x, y, 0, 0); |
266 | 266 |
Static4D rotatedTouchPoint2= rotateVectorByInvertedQuat(touchPoint2, mQuatAccumulated); |
267 | 267 |
|
268 |
Static4D rot = mMovement.newRotation(rotatedTouchPoint2);
|
|
268 |
Static2D rot = mMovement.newRotation(rotatedTouchPoint2);
|
|
269 | 269 |
RubikObject object = mRenderer.getObject(); |
270 | 270 |
|
271 |
object.beginNewRotation( new Static3D(rot.get0(),rot.get1(),rot.get2()), (int)(object.getSize()*rot.get3()) );
|
|
271 |
object.beginNewRotation( (int)rot.get0(), (int)(object.getSize()*rot.get1()) );
|
|
272 | 272 |
|
273 | 273 |
if( RubikState.getCurrentState()==RubikState.SOLV ) |
274 | 274 |
{ |
src/main/java/org/distorted/object/Cubit.java | ||
---|---|---|
231 | 231 |
|
232 | 232 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
233 | 233 |
|
234 |
Static4D returnRotationQuat( Static3D axis)
|
|
234 |
Static4D returnRotationQuat(int axis)
|
|
235 | 235 |
{ |
236 | 236 |
int pointNum = mRotationAngle.getNumPoints(); |
237 | 237 |
|
238 | 238 |
if( pointNum>=1 ) |
239 | 239 |
{ |
240 |
float axisX = mParent.ROTATION_AXIS[axis].get0(); |
|
241 |
float axisY = mParent.ROTATION_AXIS[axis].get1(); |
|
242 |
float axisZ = mParent.ROTATION_AXIS[axis].get2(); |
|
243 |
|
|
240 | 244 |
float startingAngle = mRotationAngle.getPoint(pointNum-1).get0(); |
241 | 245 |
int nearestAngleInDegrees = computeNearestAngle(startingAngle); |
242 | 246 |
double nearestAngleInRadians = nearestAngleInDegrees*Math.PI/180; |
243 | 247 |
float sinA =-(float)Math.sin(nearestAngleInRadians*0.5); |
244 | 248 |
float cosA = (float)Math.cos(nearestAngleInRadians*0.5); |
245 |
return new Static4D( axis.get0()*sinA, axis.get1()*sinA, axis.get2()*sinA, cosA);
|
|
249 |
return new Static4D( axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
|
|
246 | 250 |
} |
247 | 251 |
|
248 | 252 |
return null; |
... | ... | |
279 | 283 |
|
280 | 284 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
281 | 285 |
|
282 |
void beginNewRotation(Static3D axis)
|
|
286 |
void beginNewRotation(int axis)
|
|
283 | 287 |
{ |
284 |
mRotationAxis.set(axis);
|
|
288 |
mRotationAxis.set( mParent.ROTATION_AXIS[axis] );
|
|
285 | 289 |
mRotationAngle.add(mParent.mRotationAngleStatic); |
286 | 290 |
} |
287 | 291 |
|
288 | 292 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
289 | 293 |
|
290 |
void addNewRotation(Static3D axis, long durationMillis, int angle)
|
|
294 |
void addNewRotation(int axis, long durationMillis, int angle)
|
|
291 | 295 |
{ |
292 |
mRotationAxis.set(axis);
|
|
296 |
mRotationAxis.set( mParent.ROTATION_AXIS[axis] );
|
|
293 | 297 |
mRotationAngle.setDuration(durationMillis); |
294 | 298 |
mRotationAngle.resetToBeginning(); |
295 | 299 |
mRotationAngle.add(new Static1D(0)); |
src/main/java/org/distorted/object/RubikCube.java | ||
---|---|---|
38 | 38 |
|
39 | 39 |
class RubikCube extends RubikObject |
40 | 40 |
{ |
41 |
private static final float SQ2 = 0.5f*((float)Math.sqrt(2)); |
|
42 |
private static final float[] LEGAL = new float[] { 0.0f , 0.5f , -0.5f , 1.0f , -1.0f , SQ2 , -SQ2 }; |
|
43 |
|
|
44 |
// axisXright (right-YELLOW) axisXleft (left-WHITE) axisYright (top-BLUE) axisYleft (bottom-GREEN) axisZright (front-RED) axisZleft (back-BROWN) |
|
45 |
private static final int[] FACE_COLORS = new int[] { 0xffffff00, 0xffffffff, 0xff0000ff, 0xff00ff00, 0xffff0000, 0xffb5651d }; |
|
41 |
// the three rotation axis of a RubikCube |
|
42 |
private static final Static3D[] AXIS = new Static3D[] |
|
43 |
{ |
|
44 |
new Static3D(1,0,0), |
|
45 |
new Static3D(0,1,0), |
|
46 |
new Static3D(0,0,1) |
|
47 |
}; |
|
48 |
|
|
49 |
private static final int[] FACE_COLORS = new int[] |
|
50 |
{ |
|
51 |
0xffffff00, 0xffffffff, // AXIS[0]right (right-YELLOW) AXIS[0]left (left -WHITE) |
|
52 |
0xff0000ff, 0xff00ff00, // AXIS[1]right (top -BLUE ) AXIS[1]left (bottom-GREEN) |
|
53 |
0xffff0000, 0xffb5651d // AXIS[2]right (front-RED ) AXIS[2]left (back -BROWN) |
|
54 |
}; |
|
55 |
|
|
56 |
// All legal rotation quats of a RubikCube of any size must have all four of their components |
|
57 |
// equal to either 0, +-1, +-0.5 or +-sqrt(2)/2. |
|
58 |
// Here's how to compute this: |
|
59 |
// 1) compute how many rotations there are (RubikCube of any size = 24) |
|
60 |
// 2) take the AXIS, angles of rotation (90 in RubikCube's case) compute the basic quaternions |
|
61 |
// (i.e. rotations of 1 basic angle along each of the axis) and from there start semi-randomly |
|
62 |
// multiplying them and eventually you'll find all (24) legal rotations. |
|
63 |
// 3) linear scan through those shows that the only floats in those 24 quats are those 7 given |
|
64 |
// below. |
|
65 |
private static final float[] LEGALQUATS = new float[] |
|
66 |
{ |
|
67 |
0.0f , |
|
68 |
0.5f , |
|
69 |
-0.5f , |
|
70 |
1.0f , |
|
71 |
-1.0f , |
|
72 |
0.5f*((float)Math.sqrt(2)) , |
|
73 |
-0.5f*((float)Math.sqrt(2)) |
|
74 |
}; |
|
46 | 75 |
|
47 | 76 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
48 | 77 |
|
... | ... | |
86 | 115 |
} |
87 | 116 |
|
88 | 117 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
89 |
// All legal rotation quats of a RubikCube of any size must have all four of their components |
|
90 |
// equal to either 0, 1, -1, 0.5, -0.5 or +-sqrt(2)/2. |
|
91 | 118 |
|
92 | 119 |
float[] getLegalQuats() |
93 | 120 |
{ |
94 |
return LEGAL; |
|
121 |
return LEGALQUATS;
|
|
95 | 122 |
} |
96 | 123 |
|
97 | 124 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
101 | 128 |
return FACE_COLORS.length; |
102 | 129 |
} |
103 | 130 |
|
131 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
132 |
|
|
133 |
Static3D[] getRotationAxis() |
|
134 |
{ |
|
135 |
return AXIS; |
|
136 |
} |
|
137 |
|
|
104 | 138 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
105 | 139 |
|
106 | 140 |
void createFaceTexture(Canvas canvas, Paint paint, int face) |
... | ... | |
151 | 185 |
|
152 | 186 |
return new MeshJoined(meshes); |
153 | 187 |
} |
154 |
|
|
155 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
156 |
|
|
157 |
boolean belongsToRotation( Static3D currentPosition, Static3D axis, int row) |
|
158 |
{ |
|
159 |
if( axis.get0()!=0 ) return currentPosition.get0()==row; |
|
160 |
if( axis.get1()!=0 ) return currentPosition.get1()==row; |
|
161 |
if( axis.get2()!=0 ) return currentPosition.get2()==row; |
|
162 |
|
|
163 |
return false; |
|
164 |
} |
|
165 |
|
|
166 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
167 |
|
|
168 |
private static final Static4D mapFront, mapBack, mapLeft, mapRight, mapTop, mapBottom, mapBlack; |
|
169 |
|
|
170 |
static |
|
171 |
{ |
|
172 |
// axisXright (right-YELLOW) axisXleft (left-WHITE) axisYright (top-BLUE) axisYleft (bottom-GREEN) axisZright (front-RED) axisZleft (back-BROWN) |
|
173 |
|
|
174 |
mapRight = new Static4D( 0*(1/7.0f), 0.0f, 1/7.0f, 1.0f); |
|
175 |
mapLeft = new Static4D( 1*(1/7.0f), 0.0f, 1/7.0f, 1.0f); |
|
176 |
mapTop = new Static4D( 2*(1/7.0f), 0.0f, 1/7.0f, 1.0f); |
|
177 |
mapBottom= new Static4D( 3*(1/7.0f), 0.0f, 1/7.0f, 1.0f); |
|
178 |
mapFront = new Static4D( 4*(1/7.0f), 0.0f, 1/7.0f, 1.0f); |
|
179 |
mapBack = new Static4D( 5*(1/7.0f), 0.0f, 1/7.0f, 1.0f); |
|
180 |
mapBlack = new Static4D( 6*(1/7.0f), 0.0f, 1/7.0f, 1.0f); |
|
181 |
} |
|
182 |
|
|
183 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
184 |
|
|
185 |
void textureCubitMesh(MeshBase mesh, int x, int y, int z) |
|
186 |
{ |
|
187 |
Static4D tmpRight = (x== mSize-1 ? mapRight :mapBlack); |
|
188 |
Static4D tmpLeft = (x== 0 ? mapLeft :mapBlack); |
|
189 |
Static4D tmpTop = (y== mSize-1 ? mapTop :mapBlack); |
|
190 |
Static4D tmpBottom= (y== 0 ? mapBottom:mapBlack); |
|
191 |
Static4D tmpFront = (z== mSize-1 ? mapFront :mapBlack); |
|
192 |
Static4D tmpBack = (z== 0 ? mapBack :mapBlack); |
|
193 |
|
|
194 |
Static4D[] maps = new Static4D[] { tmpRight, tmpLeft, tmpTop, tmpBottom, tmpFront, tmpBack}; |
|
195 |
|
|
196 |
mesh.setTextureMap(maps); |
|
197 |
} |
|
198 | 188 |
} |
src/main/java/org/distorted/object/RubikCubeMovement.java | ||
---|---|---|
19 | 19 |
|
20 | 20 |
package org.distorted.object; |
21 | 21 |
|
22 |
import org.distorted.library.type.Static2D; |
|
22 | 23 |
import org.distorted.library.type.Static4D; |
23 | 24 |
|
24 | 25 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
191 | 192 |
|
192 | 193 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
193 | 194 |
|
194 |
public Static4D newRotation(Static4D rotatedTouchPoint)
|
|
195 |
public Static2D newRotation(Static4D rotatedTouchPoint)
|
|
195 | 196 |
{ |
196 | 197 |
float cubeHalfSize= RubikObject.OBJECT_SCREEN_RATIO*0.5f; |
197 | 198 |
|
... | ... | |
214 | 215 |
mTouch[1] = mPoint[1]; |
215 | 216 |
mTouch[2] = mPoint[2]; |
216 | 217 |
|
217 |
Static4D result=null; |
|
218 |
|
|
219 |
switch(mRotationVect) |
|
220 |
{ |
|
221 |
case VECTX: result = new Static4D(1,0,0,offset); break; |
|
222 |
case VECTY: result = new Static4D(0,1,0,offset); break; |
|
223 |
case VECTZ: result = new Static4D(0,0,1,offset); break; |
|
224 |
} |
|
225 |
|
|
226 |
return result; |
|
218 |
return new Static2D(mRotationVect,offset); |
|
227 | 219 |
} |
228 | 220 |
|
229 | 221 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
src/main/java/org/distorted/object/RubikObject.java | ||
---|---|---|
48 | 48 |
static final int TEXTURE_HEIGHT = 128; |
49 | 49 |
static final float OBJECT_SCREEN_RATIO = 0.5f; |
50 | 50 |
final float[] LEGAL_QUATS; |
51 |
final Static3D[] ROTATION_AXIS; |
|
51 | 52 |
|
52 | 53 |
private static final int POST_ROTATION_MILLISEC = 500; |
53 | 54 |
private final int NUM_CUBITS; |
54 | 55 |
private int mRotRow; |
55 |
private Static3D mRotAxis;
|
|
56 |
private int mRotAxis;
|
|
56 | 57 |
private Static3D mScale, mNodeScale; |
57 | 58 |
private Static4D mQuatAccumulated; |
58 | 59 |
private Cubit[] mCubits; |
... | ... | |
77 | 78 |
|
78 | 79 |
LEGAL_QUATS = getLegalQuats(); |
79 | 80 |
NUM_CUBITS = getNumCubits(size); |
81 |
ROTATION_AXIS = getRotationAxis(); |
|
80 | 82 |
|
81 | 83 |
mSize = size; |
82 | 84 |
|
... | ... | |
108 | 110 |
|
109 | 111 |
for(int i=0; i<NUM_CUBITS; i++) |
110 | 112 |
{ |
111 |
int x = positions[i][0]; |
|
112 |
int y = positions[i][1]; |
|
113 |
int z = positions[i][2]; |
|
113 |
Static3D pos = new Static3D(positions[i][0],positions[i][1],positions[i][2]); |
|
114 |
MeshBase cubitMesh = createCubitMesh(vertices); |
|
115 |
mCubits[i] = new Cubit(this,cubitMesh,pos); |
|
116 |
textureCubitMesh(cubitMesh,i); |
|
114 | 117 |
|
115 |
MeshBase cubit = createCubitMesh(vertices); |
|
116 |
textureCubitMesh(cubit,x,y,z); |
|
117 |
|
|
118 |
mCubits[i] = new Cubit( this , cubit, new Static3D(x,y,z) ); |
|
119 | 118 |
attach(mCubits[i].mNode); |
120 | 119 |
} |
121 | 120 |
} |
122 | 121 |
|
122 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
123 |
|
|
124 |
private void textureCubitMesh(MeshBase mesh, int cubit) |
|
125 |
{ |
|
126 |
boolean belongs; |
|
127 |
final int numFaces = getNumFaces(); |
|
128 |
final Static4D[] maps = new Static4D[numFaces]; |
|
129 |
final float ratio = 1.0f/(numFaces+1); |
|
130 |
|
|
131 |
if( 2*ROTATION_AXIS.length == numFaces ) |
|
132 |
{ |
|
133 |
for(int i=0; i<numFaces; i++) |
|
134 |
{ |
|
135 |
belongs = belongsToRotation(cubit, i/2, i%2==0 ? mSize-1:0 ); |
|
136 |
maps[i] = new Static4D( (belongs?i:6)*ratio, 0.0f, ratio, 1.0f); |
|
137 |
} |
|
138 |
} |
|
139 |
else if( ROTATION_AXIS.length == numFaces ) |
|
140 |
{ |
|
141 |
for(int i=0; i<numFaces; i++) |
|
142 |
{ |
|
143 |
belongs = belongsToRotation(cubit, i, mSize-1 ); |
|
144 |
maps[i] = new Static4D( (belongs?i:6)*ratio, 0.0f, ratio, 1.0f); |
|
145 |
} |
|
146 |
} |
|
147 |
|
|
148 |
mesh.setTextureMap(maps); |
|
149 |
} |
|
150 |
|
|
151 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
152 |
// TODO: only works for RubikCube |
|
153 |
|
|
154 |
private boolean belongsToRotation( int cubit, int axis, int row) |
|
155 |
{ |
|
156 |
Static3D position = mCubits[cubit].mCurrentPosition; |
|
157 |
|
|
158 |
if( axis==0 ) return position.get0()==row; |
|
159 |
if( axis==1 ) return position.get1()==row; |
|
160 |
if( axis==2 ) return position.get2()==row; |
|
161 |
|
|
162 |
return false; |
|
163 |
} |
|
164 |
|
|
123 | 165 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
124 | 166 |
|
125 | 167 |
private void resetRotationAngle(Dynamic1D rotationAngle) |
... | ... | |
229 | 271 |
|
230 | 272 |
for(int i=0; i<NUM_CUBITS; i++) |
231 | 273 |
{ |
232 |
if( belongsToRotation(mCubits[i].mCurrentPosition,mRotAxis,mRotRow) )
|
|
274 |
if( belongsToRotation(i,mRotAxis,mRotRow) )
|
|
233 | 275 |
{ |
234 | 276 |
if( first ) |
235 | 277 |
{ |
... | ... | |
296 | 338 |
|
297 | 339 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
298 | 340 |
|
299 |
public void beginNewRotation(Static3D axis, int row )
|
|
341 |
public void beginNewRotation(int axis, int row )
|
|
300 | 342 |
{ |
301 | 343 |
mRotAxis = axis; |
302 | 344 |
mRotRow = row; |
... | ... | |
304 | 346 |
mRotationAngleStatic.set0(0.0f); |
305 | 347 |
|
306 | 348 |
for(int i=0; i<NUM_CUBITS; i++) |
307 |
if( belongsToRotation( mCubits[i].mCurrentPosition,axis,mRotRow) )
|
|
349 |
if( belongsToRotation(i,mRotAxis,mRotRow) )
|
|
308 | 350 |
{ |
309 | 351 |
mCubits[i].beginNewRotation(axis); |
310 | 352 |
} |
... | ... | |
312 | 354 |
|
313 | 355 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
314 | 356 |
|
315 |
public long addNewRotation( Static3D axis, int row, int angle, long durationMillis, EffectListener listener )
|
|
357 |
public long addNewRotation( int axis, int row, int angle, long durationMillis, EffectListener listener )
|
|
316 | 358 |
{ |
317 | 359 |
long effectID=0; |
318 | 360 |
boolean first = true; |
... | ... | |
323 | 365 |
mRotationAngleStatic.set0(0.0f); |
324 | 366 |
|
325 | 367 |
for(int i=0; i<NUM_CUBITS; i++) |
326 |
if( belongsToRotation(mCubits[i].mCurrentPosition,axis,mRotRow) )
|
|
368 |
if( belongsToRotation(i,mRotAxis,mRotRow) )
|
|
327 | 369 |
{ |
328 | 370 |
mCubits[i].addNewRotation(axis,durationMillis,angle); |
329 | 371 |
|
... | ... | |
345 | 387 |
Static4D quat = null; |
346 | 388 |
|
347 | 389 |
for(int i=0; i<NUM_CUBITS; i++) |
348 |
if( belongsToRotation(mCubits[i].mCurrentPosition,mRotAxis,mRotRow) )
|
|
390 |
if( belongsToRotation(i,mRotAxis,mRotRow) )
|
|
349 | 391 |
{ |
350 | 392 |
if( first ) |
351 | 393 |
{ |
... | ... | |
367 | 409 |
abstract int getNumFaces(); |
368 | 410 |
abstract void createFaceTexture(Canvas canvas, Paint paint, int face); |
369 | 411 |
abstract MeshBase createCubitMesh(int vertices); |
370 |
|
|
371 |
abstract boolean belongsToRotation(Static3D position, Static3D axis, int row); |
|
372 |
abstract void textureCubitMesh(MeshBase mesh, int x, int y, int z); |
|
412 |
abstract Static3D[] getRotationAxis(); |
|
373 | 413 |
} |
src/main/java/org/distorted/object/RubikObjectMovement.java | ||
---|---|---|
19 | 19 |
|
20 | 20 |
package org.distorted.object; |
21 | 21 |
|
22 |
import org.distorted.library.type.Static2D; |
|
22 | 23 |
import org.distorted.library.type.Static4D; |
23 | 24 |
|
24 | 25 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
26 | 27 |
public abstract class RubikObjectMovement |
27 | 28 |
{ |
28 | 29 |
public abstract boolean faceTouched(Static4D rotatedTouchPoint, Static4D rotatedCamera); |
29 |
public abstract Static4D newRotation(Static4D rotatedTouchPoint);
|
|
30 |
public abstract Static2D newRotation(Static4D rotatedTouchPoint);
|
|
30 | 31 |
public abstract float continueRotation(Static4D rotatedTouchPoint); |
31 | 32 |
} |
Also available in: Unified diff
Progress towards generalizing belongsToRotation()