TurnEntity - Quaternion Example

BlitzMax Modules Forums/MiniB3D/TurnEntity - Quaternion Example

The Forum Archive is locked. These are the original blitzbasic.com forums, kept so their posts can still be read and searched. No new topics, replies or edits can be made here. To join the conversation, head over to the Blitz3D+ forums.

OK, this works the same as Blitz3D's TurnEntity with the global flag set to false:

Import "../MiniB3D.bmx"

' TurnEntity quaternion example - mimics the effect of Blitz3D's TurnEntity with the global flag set to false

Strict

Graphics3D 640,480

Local camera:TCamera=CreateCamera()
PositionEntity camera,0,0,-5

Local light:TLight=CreateLight()

Local cone:TMesh=CreateCone(4) ' create cone
Local cone_x#=0,cone_y#=0,cone_z#=0,cone_sx#=1.0,cone_sy#=1.0,cone_sz#=1.0

Local quat:TQuaternion=EulerToQuat(0.0,0.0,0.0) ' create cone quat
Local turn_quat:TQuaternion=EulerToQuat(0.0,0.0,0.0) ' create turn quat

Local p#=0,y#=0,r#=0 ' pitch, yaw, roll TurnEntity values

Local pitch#,yaw#,roll# ' pitch, yaw, roll, RotateEntity values

While Not KeyDown(KEY_ESCAPE)

	p=0; y=0; r=0 ' reset pitch, yaw, roll values

	' Change rotation values depending on the key pressed
	If KeyDown( KEY_UP )=True Then p=-1
	If KeyDown( KEY_DOWN )=True Then p=1
	If KeyDown( KEY_LEFT )=True Then y=-1
	If KeyDown( KEY_RIGHT )=True Then y=1
	If KeyDown( KEY_Z )=True Then r=-1
	If KeyDown( KEY_X )=True Then r=1
	
	quat=EulerToQuat(EntityPitch(cone,True),EntityYaw(cone,True),EntityRoll(cone,True)) ' set cone quat

	turn_quat=EulerToQuat(p,y,r) ' set turn quat

	quat=MultiplyQuats(quat,turn_quat) ' multiply cone quat with turn quat

	quat=NormalizeQuat(quat) ' normalise quat

	QuatToEuler2(quat.x,quat.y,quat.z,quat.w,pitch#,yaw#,roll#) ' cone quat to euler

	RotateEntity cone,pitch#,yaw#,roll# ' rotate cone
	
	RenderWorld
	
	Flip

Wend

' Leadwerks function
Function EulerToQuat:TQuaternion(pitch#,yaw#,roll#)
	Local cr#=Cos(-roll#/2.0)
	Local cp#=Cos(pitch#/2.0)
	Local cy#=Cos(yaw#/2.0)
	Local sr#=Sin(-roll#/2.0)
	Local sp#=Sin(pitch#/2.0)
	Local sy#=Sin(yaw#/2.0)
	Local cpcy#=cp#*cy#
	Local spsy#=sp#*sy#
	Local spcy#=sp#*cy#
	Local cpsy#=cp#*sy#
	Local q:TQuaternion=New TQuaternion
	q.w#=cr#*cpcy#+sr#*spsy#
	q.x#=sr#*cpcy#-cr#*spsy#
	q.y#=cr#*spcy#+sr#*cpsy#
	q.z#=cr#*cpsy#-sr#*spcy#
	Return q
End Function

' Leadwerks function
Const QuatToEulerAccuracy#=0.001
Function QuatToEuler2(x#,y#,z#,w#,pitch# Var,yaw# Var,roll# Var)
	Local sint#=(2.0*w*y)-(2.0*x*z)
	Local cost_temp#=1.0-(sint#*sint#)
	Local cost#
	If Abs(cost_temp#)>QuatToEulerAccuracy
		cost#=Sqr(cost_temp#)
		Else
		cost#=0.0
	EndIf
	Local sinv#,cosv#,sinf#,cosf#
	If Abs(cost#)>QuatToEulerAccuracy
		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
	pitch#=ATan2(sint#,cost#)
	yaw#=ATan2(sinf#,cosf#)
	roll#=-ATan2(sinv#,cosv#)
End Function

Function MultiplyQuats:TQuaternion(q1:TQuaternion,q2:TQuaternion)

	Local q:TQuaternion=New TQuaternion
	
	q.w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z
	q.x = q1.w*q2.x + q1.x*q2.w + q1.y*q2.z - q1.z*q2.y
	q.y = q1.w*q2.y + q1.y*q2.w + q1.z*q2.x - q1.x*q2.z
	q.z = q1.w*q2.z + q1.z*q2.w + q1.x*q2.y - q1.y*q2.x

	Return q

End Function

Function NormalizeQuat:TQuaternion(q:TQuaternion)

	Local uv#=Sqr(q.w*q.w+q.x*q.x+q.y*q.y+q.z*q.z)

	q.w=q.w/uv
	q.x=q.x/uv
	q.y=q.y/uv
	q.z=q.z/uv

	Return q

End Function

Is that what you want?