Here are some functions found on the forum, and modified for easier use.
But, I have a problem with the conversions, axes seem to be false.
As, i 'm not really understanding quaternions, i really thonk i made a mistake, but i can't point on this...
If anyone could help ^^
I have to use it to get the rotation of B3D files
=> getting w,x,y,z from the parse of a b3d, and then i build the scene using createpivot and createmesh command.
All works fine, but I can't turn entitys like it should.
But, I have a problem with the conversions, axes seem to be false.
As, i 'm not really understanding quaternions, i really thonk i made a mistake, but i can't point on this...
If anyone could help ^^
Graphics3D 800,600,0,2 SetBuffer BackBuffer() ;demo QUA_EulerToQuat(45,0,0) w1#=QUA_Get_QuatW() x1#=QUA_Get_QuatX() y1#=QUA_Get_QuatY() z1#=QUA_Get_QuatZ() QUA_EulerToQuat(45,0,0) w2#=QUA_Get_QuatW() x2#=QUA_Get_QuatX() y2#=QUA_Get_QuatY() z2#=QUA_Get_QuatZ() QUA_MultiplyQuat#(w1,x1,y1,z1,w2,x2,y2,z2) w#=QUA_Get_QuatW() x#=QUA_Get_QuatX() y#=QUA_Get_QuatY() z#=QUA_Get_QuatZ() Color 0,255,0 Print " ===== Quat Multiply =====" Print " 2 * Conversion de (45,0,0) en Quat" Print " puis multiplication des deux Quats pour ajouter les angles d'Euler" Print Color 255,255,0:Print "rw="+w+" - rx="+x+" - ry="+y+" - rz="+z:Print:Print Color 0,255,0 Print " ===== Quat to Euler ===== ":Print "==============================================" Write " => methode 1 :" QUA_QuatToEuler1(w,x,y,z) xf#=QUA_Get_EulerX() yf#=QUA_Get_EulerY() zf#=QUA_Get_EulerZ() Color 255,255,0 Print " rx="+xf Color 255,0,0 Print " ry="+yf+" <= mauvais axe..." Color 255,255,0 Print " rz="+zf:Print Color 0,255,0:Print "==================================" Write " => methode 2 :" QUA_QuatToEuler2(w,x,y,z) xf#=QUA_Get_EulerX() yf#=QUA_Get_EulerY() zf#=QUA_Get_EulerZ() Color 255,255,0 Print " rx="+xf+" <= ... chelou non ?" Color 255,0,0 Print " ry="+yf+" <= mauvais axe..." Color 255,255,0 Print " rz="+zf+" <= ... idem que pour X :-s":Print Color 0,255,0:Print "==================================" Write " => methode 3 :" QUA_QuatToEuler3(w,x,y,z) xf#=QUA_Get_EulerX() yf#=QUA_Get_EulerY() zf#=QUA_Get_EulerZ() Color 255,255,0 Print " rx="+xf Color 255,0,0 Print " ry="+yf+" <= mauvais axe..." Color 255,255,0 Print " rz="+zf:Print Color 0,255,0:Print "==============================================" WaitKey End Const QuatToEulerAccuracy# = 0.001 Const QuatSlerpAccuracy# = 0.0001 Type QUA_Euler Field x#,y#,z# Field roll#,pitch#,yaw# End Type Type QUA_Quat Field w# Field x# Field Y# Field z# End Type Type QUA_matrix Field m00# Field m01# Field m02# Field m03# Field m10# Field m11# Field m12# Field m13# Field m20# Field m21# Field m22# Field m23# Field m30# Field m31# Field m32# Field m33# End Type Function QUA_Get_EulerX#() eul.QUA_Euler = Last QUA_Euler If eul=Null Return False Return eul\x End Function Function QUA_Get_EulerY#() eul.QUA_Euler = Last QUA_Euler If eul=Null Return False Return eul\y End Function Function QUA_Get_EulerZ#() eul.QUA_Euler = Last QUA_Euler If eul=Null Return False Return eul\z End Function Function QUA_Get_QuatW#() qua.QUA_Quat = Last QUA_Quat If qua=Null Return False Return qua\w End Function Function QUA_Get_QuatX#() qua.QUA_Quat = Last QUA_Quat If qua=Null Return False Return qua\x End Function Function QUA_Get_QuatY#() qua.QUA_Quat = Last QUA_Quat If qua=Null Return False Return qua\y End Function Function QUA_Get_QuatZ#() qua.QUA_Quat = Last QUA_Quat If qua=Null Return False Return qua\z End Function Function QUA_EulerToQuat(npitch#,nyaw#,nroll#) Local cr#,cp#,cy# Local sr#,sp#,sy# Local cpcy#,spyc# Local spcy#,cpsy# Local spsy# cr#=Cos(-nroll#/2.0) cp#=Cos(npitch#/2.0) cy#=Cos(nyaw#/2.0) sr#=Sin(-nroll#/2.0) sp#=Sin(npitch#/2.0) sy#=Sin(nyaw#/2.0) cpcy#=cp#*cy# spsy#=sp#*sy# spcy#=sp#*cy# cpsy#=cp#*sy# q.QUA_Quat=Last QUA_Quat If q=Null q=New QUA_Quat q\w=cr#*cpcy#+sr#*spsy# q\x=sr#*cpcy#-cr#*spsy# q\y=cr#*spcy#+sr#*cpsy# q\z=cr#*cpsy#-sr#*spcy# End Function Function QUA_QuatToEuler1(w#,x#,y#,z#) lx# = -z ly# = -x lz# = y x=lx y=ly z=lz Local sint#=(2.0*w*y)-(2.0*x*z) Local cost_temp#=1.0-sint*sint Local cost# If Abs(cost_temp#)>0.001 cost#=Sqr(cost_temp) Else cost#=0.0 EndIf Local sinw#,cosw#,sinf#,cosf#,sinv#,cosv# If Abs(cost#)>0.001 sinv#=((2.0*y*z)+(2.0*w*x))/cost cosv#=(1.0-(2.0*x*x)-(2.0*y*y))/cost sinf#=((2.0*x*y)+(2.0*w*z))/cost cosf#=(1.0-(2.0*y*y)-(2.0*z*z))/cost Else sinv=(2.0*w*x)-(2.0*y*z) cosv=1.0-(2.0*x*x)-(2.0*z*z) sinf=0.0 cosf=1.0 EndIf eul.QUA_Euler = Last QUA_Euler If eul=Null eul.QUA_Euler = New QUA_Euler EndIf eul\z#=-ATan2(sinv,cosv) eul\x#=ATan2(sint,cost) eul\y#=ATan2(sinf,cosf) End Function Function QUA_QuatToEuler2(w#,x#,y#,z#) q.QUA_Quat=Last QUA_Quat If q=Null q=New QUA_Quat q\w=w:q\x=x:q\y=y:q\z=z Local lx#, ly#, lz# eul.QUA_Euler = Last QUA_Euler If eul=Null eul.QUA_Euler = New QUA_Euler EndIf lMat.QUA_matrix = New QUA_matrix QUA_QuatToMatrix(q,lMat) ly = lMat\m02 If (Abs(ly) > 1.0) If ly > 0.0 ly = 1.0 Else ly = -1.0 EndIf EndIf ly = ASin(ly) If radian lx = ATan2(-lMat\m12, lMat\m22) lz = ATan2(-lMat\m01, lMat\m00) eul\x = lx eul\y = ly eul\z = lz Else If (ly < 90 ) Then If (ly > -90) Then lx = ATan2(-lMat\m12, lMat\m22) lz = ATan2(-lMat\m01, lMat\m00) Else lx = -ATan2(lMat\m10, lMat\m11) lz = 0.0 EndIf Else lx = ATan2(lMat\m10, lMat\m11) lz = 0.0 EndIf eul\x = lx ; pitch eul\y = ly ; yaw eul\z = lz ; roll EndIf Return True End Function ; convert a Quat to a Rotation Function QUA_QuatToEuler3(w#,x#,y#,z#) Local sint#, cost#, sinv#, cosv#, sinf#, cosf# Local cost_temp# sint = (2 * w * y) - (2 * x * z) cost_temp = 1.0 - (sint * sint) If Abs(cost_temp) > QuatToEulerAccuracy cost = Sqr(cost_temp) Else cost = 0 EndIf If Abs(cost) > QuatToEulerAccuracy sinv = ((2 * y * z) + (2 * w * x)) / cost cosv = (1 - (2 * x * x) - (2 * y * y)) / cost sinf = ((2 * x * y) + (2 * w * z)) / cost cosf = (1 - (2 * y * y) - (2 * z * z)) / cost Else sinv = (2 * w * x) - (2 * y * z) cosv = 1 - (2 * x * x) - (2 * z * z) sinf = 0 cosf = 1 EndIf eul.QUA_Euler = Last QUA_Euler If eul=Null eul.QUA_Euler = New QUA_Euler EndIf ;Generate the output rotation eul\x = -ATan2(sinv, cosv) ; inverted due to change in handedness of coordinate system eul\y = ATan2(sint, cost) eul\z = ATan2(sinf, cosf) End Function ; result will be the same rotation as doing q1 then q2 (order matters!) Function QUA_MultiplyQuat#(Aw#,Ax#,Ay#,Az#,Bw#,Bx#,By#,Bz#) Local a#, b#, c#, d#, e#, f#, g#, h# a = (Aw + Ax) * (Bw + Bx) b = (Az - Ay) * (By - Bz) c = (Aw - Ax) * (By + Bz) d = (Ay + Az) * (Bw - Bx) e = (Ax + Az) * (Bx + By) f = (Ax - Az) * (Bx - By) g = (Aw + Ay) * (Bw - Bz) h = (Aw - Ay) * (Bw + Bz) q.QUA_Quat=Last QUA_Quat If q=Null q=New QUA_Quat q\w# = b + (-e - f + g + h) / 2 q\x# = a - ( e + f + g + h) / 2 q\y# = c + ( e - f + g - h) / 2 q\z# = d + ( e - f - g + h) / 2 Return q\w# End Function ;=================================================================================== ; ========== PRIVATE =================================================== ;=================================================================================== Function QUA_QuatToMatrix(q.QUA_Quat,m.QUA_matrix) Local a#, w#, x#, y#, z#; a = Sqr(q\w*q\w + q\x*q\x + q\y*q\y + q\z*q\z) If (a >= EPSILON) Then w = q\w *a x = q\x *a y = q\y *a z = q\z *a QUA_matrixIdentity(m) m\m00 = 1 - 2*(y*y + z*z) m\m01 = 2*(x*y + w*z) m\m02 = 2*(x*z - w*y) m\m10 = 2*(x*y - w*z) m\m11 = 1 - 2*(x*x + z*z) m\m12 = 2*(y*z + w*x) m\m20 = 2*(x*z + w*y) m\m21 = 2*(y*z - w*x) m\m22 = 1 - 2*(x*x + y*y) Else QUA_matrixIdentity(m) EndIf End Function Function QUA_matrixIdentity(m.QUA_matrix) m\m00 = 1 m\m01 = 0 m\m02 = 0 m\m03 = 0 m\m10 = 0 m\m11 = 1 m\m12 = 0 m\m13 = 0 m\m20 = 0 m\m21 = 0 m\m22 = 1 m\m23 = 0 m\m30 = 0 m\m31 = 0 m\m32 = 0 m\m33 = 1 Return True End Function
I have to use it to get the rotation of B3D files
=> getting w,x,y,z from the parse of a b3d, and then i build the scene using createpivot and createmesh command.
All works fine, but I can't turn entitys like it should.