Revision 7aa4c349
Added by Leszek Koltunski over 3 years ago
src/main/java/org/distorted/control/RubikControl.java | ||
---|---|---|
23 | 23 |
import org.distorted.library.main.DistortedNode; |
24 | 24 |
import org.distorted.library.main.DistortedScreen; |
25 | 25 |
import org.distorted.library.message.EffectListener; |
26 |
import org.distorted.library.type.Static4D; |
|
26 | 27 |
import org.distorted.main.RubikActivity; |
27 | 28 |
import org.distorted.main.RubikSurfaceView; |
28 | 29 |
import org.distorted.objects.TwistyObject; |
... | ... | |
57 | 58 |
return act!=null ? act.getObject() : null; |
58 | 59 |
} |
59 | 60 |
|
61 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
62 |
|
|
63 |
Static4D getCurrQuat() |
|
64 |
{ |
|
65 |
RubikActivity act = mRefAct.get(); |
|
66 |
return act!=null ? act.getCurrQuat() : null; |
|
67 |
} |
|
68 |
|
|
60 | 69 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
61 | 70 |
|
62 | 71 |
RubikSurfaceView getSurfaceView() |
src/main/java/org/distorted/control/RubikControlRotate.java | ||
---|---|---|
55 | 55 |
|
56 | 56 |
private void computeInitQuat() |
57 | 57 |
{ |
58 |
final double alphaZ = Math.PI/8; |
|
59 |
final double alphaY = Math.PI/16; |
|
58 |
double alphaZ = -Math.PI* 0.1250f; |
|
59 |
double alphaY = -Math.PI* 0.0625f; |
|
60 |
|
|
61 |
alphaY /= 2; |
|
62 |
alphaZ /= 2; |
|
60 | 63 |
|
61 | 64 |
float sinZ = (float)Math.sin(alphaZ); |
62 | 65 |
float cosZ = (float)Math.cos(alphaZ); |
... | ... | |
70 | 73 |
} |
71 | 74 |
|
72 | 75 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
76 |
// Take 3D vector 'ax', rotate it by quaternion 'objQuat' to get vector V1. |
|
77 |
// Take 3D vector (1,0,0) and rotate it by INIT_QUAT to get vector V2. |
|
78 |
// Return a quaternion Q such that if we rotate V1 by Q, we get V2. |
|
73 | 79 |
|
74 |
private Static4D computeQuat(Static3D ax) |
|
80 |
private Static4D computeQuat(Static3D ax, Static4D objQuat, float x, float y, float z)
|
|
75 | 81 |
{ |
76 |
return null; |
|
82 |
Static4D ax4D = new Static4D( ax.get0(), ax.get1(), ax.get2(), 0); |
|
83 |
Static4D axRo = QuatHelper.rotateVectorByQuat(ax4D,objQuat); |
|
84 |
return QuatHelper.retRotationQuat(axRo.get0(),axRo.get1(),axRo.get2(),x,y,z); |
|
77 | 85 |
} |
78 | 86 |
|
79 | 87 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
82 | 90 |
{ |
83 | 91 |
TwistyObject object = mControl.getObject(); |
84 | 92 |
Static3D[] axis = object.getRotationAxis(); |
93 |
int chosen=-1,numAxis = axis.length; |
|
85 | 94 |
float cos,maxCos = -1.0f; |
86 | 95 |
Static4D quat; |
87 | 96 |
|
88 |
for (Static3D axi : axis) |
|
97 |
Static4D objCurrQuat = mControl.getCurrQuat(); |
|
98 |
Static4D axisX = new Static4D(1,0,0,0); |
|
99 |
Static4D rotAxisX = QuatHelper.rotateVectorByQuat(axisX,INIT_QUAT); |
|
100 |
|
|
101 |
float axX = rotAxisX.get0(); |
|
102 |
float axY = rotAxisX.get1(); |
|
103 |
float axZ = rotAxisX.get2(); |
|
104 |
|
|
105 |
for (int a=0; a<numAxis; a++) |
|
89 | 106 |
{ |
90 |
quat = computeQuat(axi); |
|
107 |
quat = computeQuat(axis[a],objCurrQuat,axX,axY,axZ);
|
|
91 | 108 |
cos = quat.get3(); |
92 | 109 |
|
93 | 110 |
if (cos > maxCos) |
94 | 111 |
{ |
95 | 112 |
maxCos = cos; |
113 |
chosen = a; |
|
96 | 114 |
mObjRotQuat = quat; |
97 | 115 |
} |
98 | 116 |
} |
117 |
|
|
118 |
android.util.Log.e("D", "axis chosen: "+chosen); |
|
99 | 119 |
} |
100 | 120 |
|
101 | 121 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
110 | 130 |
|
111 | 131 |
private void setObjectEffectsStage1() |
112 | 132 |
{ |
113 |
// TODO |
|
133 |
mDynamic.resetToBeginning(); |
|
134 |
mScale.notifyWhenFinished(mControl); |
|
114 | 135 |
} |
115 | 136 |
|
116 | 137 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
... | ... | |
186 | 207 |
mObjectQuad = new MeshQuad(); |
187 | 208 |
} |
188 | 209 |
|
189 |
if( INIT_QUAT==null ) |
|
190 |
{ |
|
191 |
computeInitQuat(); |
|
192 |
computeRotQuat(); |
|
193 |
} |
|
210 |
if( INIT_QUAT==null ) computeInitQuat(); |
|
211 |
|
|
212 |
computeRotQuat(); |
|
194 | 213 |
|
195 | 214 |
DistortedTexture texture = new DistortedTexture(); |
196 | 215 |
texture.setColorARGB(0xff00ff00); |
src/main/java/org/distorted/helpers/FactoryCubit.java | ||
---|---|---|
368 | 368 |
return ft; |
369 | 369 |
} |
370 | 370 |
|
371 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
372 |
|
|
373 |
private double computeCos(double oldX, double oldY, double newX, double newY, double len1, double len2) |
|
374 |
{ |
|
375 |
double ret= (oldX*newX+oldY*newY) / (len1*len2); |
|
376 |
if( ret<-1.0 ) return -1.0; |
|
377 |
if( ret> 1.0 ) return 1.0; |
|
378 |
|
|
379 |
return ret; |
|
380 |
} |
|
381 |
|
|
382 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
383 |
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise! |
|
384 |
|
|
385 |
private double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2) |
|
386 |
{ |
|
387 |
double ret= (newX*oldY-oldX*newY) / (len1*len2); |
|
388 |
if( ret<-1.0 ) return -1.0; |
|
389 |
if( ret> 1.0 ) return 1.0; |
|
390 |
|
|
391 |
return ret; |
|
392 |
} |
|
393 |
|
|
394 | 371 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
395 | 372 |
|
396 | 373 |
private void rotateAllVertices(double[] result, int len, double[] vertices, double sin, double cos) |
... | ... | |
550 | 527 |
double newX = newVert[2*vertex ]; |
551 | 528 |
double newY = newVert[2*vertex+1]; |
552 | 529 |
double lenIthNew = Math.sqrt(newX*newX + newY*newY); |
553 |
double cos = computeCos( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld); |
|
554 |
double sin = computeSin( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld); |
|
530 |
double cos = QuatHelper.computeCos( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
|
|
531 |
double sin = QuatHelper.computeSin( oldVert[0], oldVert[1], newX, newY, lenIthNew, lenFirstOld);
|
|
555 | 532 |
|
556 | 533 |
rotateAllVertices(buffer,len,newVert,sin,cos); |
557 | 534 |
|
src/main/java/org/distorted/helpers/QuatHelper.java | ||
---|---|---|
28 | 28 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
29 | 29 |
// return quat1*quat2 |
30 | 30 |
|
31 |
public static Static4D quatMultiply( Static4D quat1, Static4D quat2 )
|
|
32 |
{
|
|
33 |
float qx = quat1.get0();
|
|
34 |
float qy = quat1.get1();
|
|
35 |
float qz = quat1.get2();
|
|
36 |
float qw = quat1.get3();
|
|
37 |
|
|
38 |
float rx = quat2.get0();
|
|
39 |
float ry = quat2.get1();
|
|
40 |
float rz = quat2.get2();
|
|
41 |
float rw = quat2.get3();
|
|
42 |
|
|
43 |
float tx = rw*qx - rz*qy + ry*qz + rx*qw;
|
|
44 |
float ty = rw*qy + rz*qx + ry*qw - rx*qz;
|
|
45 |
float tz = rw*qz + rz*qw - ry*qx + rx*qy;
|
|
46 |
float tw = rw*qw - rz*qz - ry*qy - rx*qx;
|
|
47 |
|
|
48 |
return new Static4D(tx,ty,tz,tw);
|
|
49 |
}
|
|
31 |
public static Static4D quatMultiply( Static4D quat1, Static4D quat2 ) |
|
32 |
{ |
|
33 |
float qx = quat1.get0(); |
|
34 |
float qy = quat1.get1(); |
|
35 |
float qz = quat1.get2(); |
|
36 |
float qw = quat1.get3(); |
|
37 |
|
|
38 |
float rx = quat2.get0(); |
|
39 |
float ry = quat2.get1(); |
|
40 |
float rz = quat2.get2(); |
|
41 |
float rw = quat2.get3(); |
|
42 |
|
|
43 |
float tx = rw*qx - rz*qy + ry*qz + rx*qw; |
|
44 |
float ty = rw*qy + rz*qx + ry*qw - rx*qz; |
|
45 |
float tz = rw*qz + rz*qw - ry*qx + rx*qy; |
|
46 |
float tw = rw*qw - rz*qz - ry*qy - rx*qx; |
|
47 |
|
|
48 |
return new Static4D(tx,ty,tz,tw); |
|
49 |
} |
|
50 | 50 |
|
51 | 51 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
52 | 52 |
// rotate 'vector' by quat ( i.e. return quat*vector*(quat^-1) ) |
53 | 53 |
|
54 |
public static Static4D rotateVectorByQuat(Static4D vector, Static4D quat)
|
|
55 |
{
|
|
56 |
float qx = quat.get0();
|
|
57 |
float qy = quat.get1();
|
|
58 |
float qz = quat.get2();
|
|
59 |
float qw = quat.get3();
|
|
54 |
public static Static4D rotateVectorByQuat(Static4D vector, Static4D quat) |
|
55 |
{ |
|
56 |
float qx = quat.get0(); |
|
57 |
float qy = quat.get1(); |
|
58 |
float qz = quat.get2(); |
|
59 |
float qw = quat.get3(); |
|
60 | 60 |
|
61 |
Static4D quatInverted= new Static4D(-qx,-qy,-qz,qw);
|
|
62 |
Static4D tmp = quatMultiply(quat,vector);
|
|
61 |
Static4D quatInverted= new Static4D(-qx,-qy,-qz,qw); |
|
62 |
Static4D tmp = quatMultiply(quat,vector); |
|
63 | 63 |
|
64 |
return quatMultiply(tmp,quatInverted);
|
|
65 |
}
|
|
64 |
return quatMultiply(tmp,quatInverted); |
|
65 |
} |
|
66 | 66 |
|
67 | 67 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
68 | 68 |
// rotate 'vector' by quat^(-1) ( i.e. return (quat^-1)*vector*quat ) |
69 | 69 |
|
70 |
public static Static4D rotateVectorByInvertedQuat(Static4D vector, Static4D quat) |
|
70 |
public static Static4D rotateVectorByInvertedQuat(Static4D vector, Static4D quat) |
|
71 |
{ |
|
72 |
float qx = quat.get0(); |
|
73 |
float qy = quat.get1(); |
|
74 |
float qz = quat.get2(); |
|
75 |
float qw = quat.get3(); |
|
76 |
|
|
77 |
Static4D quatInverted= new Static4D(-qx,-qy,-qz,qw); |
|
78 |
Static4D tmp = quatMultiply(quatInverted,vector); |
|
79 |
|
|
80 |
return quatMultiply(tmp,quat); |
|
81 |
} |
|
82 |
|
|
83 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
84 |
|
|
85 |
public static Static4D quatFromDrag(float dragX, float dragY) |
|
86 |
{ |
|
87 |
float axisX = dragY; // inverted X and Y - rotation axis is perpendicular to (dragX,dragY) |
|
88 |
float axisY = dragX; // Why not (-dragY, dragX) ? because Y axis is also inverted! |
|
89 |
float axisZ = 0; |
|
90 |
float axisL = (float)Math.sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ); |
|
91 |
|
|
92 |
if( axisL>0 ) |
|
71 | 93 |
{ |
72 |
float qx = quat.get0(); |
|
73 |
float qy = quat.get1(); |
|
74 |
float qz = quat.get2(); |
|
75 |
float qw = quat.get3(); |
|
94 |
axisX /= axisL; |
|
95 |
axisY /= axisL; |
|
96 |
axisZ /= axisL; |
|
97 |
|
|
98 |
float ratio = axisL; |
|
99 |
ratio = ratio - (int)ratio; // the cos() is only valid in (0,Pi) |
|
76 | 100 |
|
77 |
Static4D quatInverted= new Static4D(-qx,-qy,-qz,qw);
|
|
78 |
Static4D tmp = quatMultiply(quatInverted,vector);
|
|
101 |
float cosA = (float)Math.cos(Math.PI*ratio);
|
|
102 |
float sinA = (float)Math.sqrt(1-cosA*cosA);
|
|
79 | 103 |
|
80 |
return quatMultiply(tmp,quat);
|
|
104 |
return new Static4D(axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
|
|
81 | 105 |
} |
82 | 106 |
|
107 |
return new Static4D(0f, 0f, 0f, 1f); |
|
108 |
} |
|
109 |
|
|
83 | 110 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
84 | 111 |
|
85 |
public static Static4D quatFromDrag(float dragX, float dragY) |
|
86 |
{ |
|
87 |
float axisX = dragY; // inverted X and Y - rotation axis is perpendicular to (dragX,dragY) |
|
88 |
float axisY = dragX; // Why not (-dragY, dragX) ? because Y axis is also inverted! |
|
89 |
float axisZ = 0; |
|
90 |
float axisL = (float)Math.sqrt(axisX*axisX + axisY*axisY + axisZ*axisZ); |
|
112 |
public static double computeCos(double oldX, double oldY, double newX, double newY, double len1, double len2) |
|
113 |
{ |
|
114 |
double ret= (oldX*newX+oldY*newY) / (len1*len2); |
|
115 |
if( ret<-1.0 ) return -1.0; |
|
116 |
if( ret> 1.0 ) return 1.0; |
|
117 |
|
|
118 |
return ret; |
|
119 |
} |
|
120 |
|
|
121 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
122 |
// sin of (signed!) angle between vectors 'old' and 'new', counterclockwise! |
|
91 | 123 |
|
92 |
if( axisL>0 )
|
|
93 |
{
|
|
94 |
axisX /= axisL;
|
|
95 |
axisY /= axisL;
|
|
96 |
axisZ /= axisL;
|
|
124 |
public static double computeSin(double oldX, double oldY, double newX, double newY, double len1, double len2)
|
|
125 |
{ |
|
126 |
double ret= (newX*oldY-oldX*newY) / (len1*len2);
|
|
127 |
if( ret<-1.0 ) return -1.0;
|
|
128 |
if( ret> 1.0 ) return 1.0;
|
|
97 | 129 |
|
98 |
float ratio = axisL;
|
|
99 |
ratio = ratio - (int)ratio; // the cos() is only valid in (0,Pi)
|
|
130 |
return ret;
|
|
131 |
}
|
|
100 | 132 |
|
101 |
float cosA = (float)Math.cos(Math.PI*ratio); |
|
102 |
float sinA = (float)Math.sqrt(1-cosA*cosA); |
|
133 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
134 |
// return quat Q that turns 3D vector A=(ax,ay,az) to another 3D vector B=(bx,by,bz) |
|
135 |
// take care of double-cover by ensuring that always Q.get3() >=0 |
|
136 |
|
|
137 |
public static Static4D retRotationQuat(float ax, float ay, float az, float bx, float by, float bz) |
|
138 |
{ |
|
139 |
float nx = ay*bz - az*by; |
|
140 |
float ny = az*bx - ax*bz; |
|
141 |
float nz = ax*by - ay*bx; |
|
103 | 142 |
|
104 |
return new Static4D(axisX*sinA, axisY*sinA, axisZ*sinA, cosA);
|
|
105 |
}
|
|
143 |
float sin = (float)Math.sqrt(nx*nx + ny*ny + nz*nz);
|
|
144 |
float cos = ax*bx + ay*by + az*bz;
|
|
106 | 145 |
|
107 |
return new Static4D(0f, 0f, 0f, 1f); |
|
146 |
if( sin!=0 ) |
|
147 |
{ |
|
148 |
nx /= sin; |
|
149 |
ny /= sin; |
|
150 |
nz /= sin; |
|
108 | 151 |
} |
152 |
|
|
153 |
// Why sin<=0 and cos>=0 ? |
|
154 |
// 0<angle<180 -> 0<halfAngle<90 -> both sin and cos are positive. |
|
155 |
// But1: quats work counterclockwise -> negate cos. |
|
156 |
// But2: double-cover, we prefer to have the cos positive (so that unit=(0,0,0,1)) |
|
157 |
// so negate again both cos and sin. |
|
158 |
float sinHalf =-(float)Math.sqrt((1-cos)/2); |
|
159 |
float cosHalf = (float)Math.sqrt((1+cos)/2); |
|
160 |
|
|
161 |
return new Static4D(nx*sinHalf,ny*sinHalf,nz*sinHalf,cosHalf); |
|
162 |
} |
|
109 | 163 |
} |
src/main/java/org/distorted/main/RubikActivity.java | ||
---|---|---|
44 | 44 |
import org.distorted.library.main.DistortedLibrary; |
45 | 45 |
|
46 | 46 |
import org.distorted.library.main.DistortedScreen; |
47 |
import org.distorted.library.type.Static4D; |
|
47 | 48 |
import org.distorted.objects.TwistyObject; |
48 | 49 |
import org.distorted.network.RubikScores; |
49 | 50 |
import org.distorted.network.RubikNetwork; |
... | ... | |
602 | 603 |
play.setLockState(this); |
603 | 604 |
} |
604 | 605 |
|
606 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
607 |
|
|
608 |
public Static4D getCurrQuat() |
|
609 |
{ |
|
610 |
RubikSurfaceView view = findViewById(R.id.rubikSurfaceView); |
|
611 |
return view.getQuat(); |
|
612 |
} |
|
613 |
|
|
605 | 614 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
606 | 615 |
|
607 | 616 |
public void switchTutorial(String url, ObjectList object, int size) |
Also available in: Unified diff
Progress with RubikControl.