Has anyone fixed TurnEntity and RotateEntity?

BlitzMax Modules Forums/MiniB3D/Has anyone fixed TurnEntity and RotateEntity?

Fixed with source code further down

No, TurnEntity behaviour is still the same. As I said before, this requires a substantial rewrite due to TurnEntity using quaternions - it's not worth it right now.

RotateEntity behaviour is exactly the same as Blitz3D.

Hmm when using rotateentity I got the same results as turnentity, will check me code again :)

Yes, TurnEntity works the same as RotateEntity in MiniB3D. RotateEntity in MiniB3D works the same as RotateEntity in Blitz3D.

Ah right, I just wanted a Blitz3d turnentity routine :)

Does anyone have a simple one I could use not very hot on quoterions etc, thanks in advance :)

This threads may be useful to you:

http://www.blitzbasic.com/Community/posts.php?topic=66809
http://www.blitzbasic.com/Community/posts.php?topic=68943

Thanks when I have a working TurnEntity function (that works like Blitz3d) I will post it :)

Updated source code further down

EdzUp: With global set to false, it seems to 'stick' when it pitches too far up or down.

With global set to true, what you've written works like RotateEntity rather than TurnEntity.
(edit: And because it bypasses so much of the normal functionality, it plays badly with the other Entity commands.)

looks like alot of code for a turn entity function. maybe its just me though.

Ninjacat basically its the same as the code provided by simonh im trying to work it into a usable turnentity function. After I have it working as it should I will try to fix the locking problem

It would be nice if there was a proper TurnEntity function in Minib3d but im working with what I have.

Plash this is also a demo the function is not much of the source code provided.

EdzUp: I just want to say Thank You for doing this. Every time I looked at quats I got a headache...

Plash: Are you volunteering to write a shorter one? :)

EdzUp: I didn't mean to sound like I was criticising. Anyone who wants to tackle this is a saint in my book. :)

I took a shot at it myself (with much head scratching and hair-pulling) but had mixed luck. I got the basic B3D functionality, so you could look and move in any direction and parented entities behaved correctly. But that broke PointEntity and EntityPitch and a dozen other things... I suspect that simon might be right, and it's not possible without effectively rewiting the entire engine to use quats.

I could post my code if you'd like, but it might be more harm than help.

EdzUp: On second thoughts! I had a second look at the 'global==false' part of your code. And... it does stick if you get within about 3 degrees of the north or south poles.

But on the other hand... in a real life situation, 3 degrees is a pretty small target to hit. And in a fast-paced space action game, which is what I was originally trying to work this out for, you're probably moving more than 3 degrees per frame anyway. You'd bounce right over the 'pothole' without seeing it. This is videogames, not rocket science!

So I might just nick what you've got there a run with it. Thank you, Ed, you really were a saint! :)

Actually its simonh who should take the credit for this, I just packaged up his code that he posted elsewhere and im making a TurnEntity function out of it :)

> Actually its simonh who should take the credit for this

True, but I saw that code and still had no idea what to do, so thanks to both of you!

Well I have no understanding of Quaternions TBH I just adjusted his code so its wrapped in a function (makes it easier to use and understand) :)

Here is another version that should complete the function (still have a few bugs to fix but well its getting there). This one rotates with global flag true or false and should be like Blitz3d's function :). The source an example the actual function is a small segment of the source code.

Import sidesign.minib3d'"..\minib3d.bmx"					'include the 

minib3d system

' TurnEntity quaternion example - mimics the effect of Blitz3D's TurnEntity with the global 

flag set to false

Strict

Graphics3D 640,480, 32

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

Local light:TLight=CreateLight()

Local cone:TMesh=CreateCone(4) ' create cone

While Not KeyDown( KEY_ESCAPE )
	If KeyDown( KEY_UP )=True Then EdzUpTurnEntity( Cone, -1, 0, 0, True )
	If KeyDown( KEY_DOWN )=True Then EdzUpTurnEntity( Cone, 1, 0, 0, True )
	If KeyDown( KEY_LEFT )=True Then EdzUpTurnEntity( Cone, 0, -1, 0, True )
	If KeyDown( KEY_RIGHT )=True Then EdzUpTurnEntity( Cone, 0, 1, 0, True )
	If KeyDown( KEY_Z )=True Then EdzUpTurnEntity( Cone, 0, 0, -1, True )
	If KeyDown( KEY_X )=True Then EdzUpTurnEntity( Cone, 0, 0, 1, True )
	
	RenderWorld
	Flip
Wend
End

Function EdzUpTurnEntity( Ent:TEntity, X:Float, Y:Float, Z:Float, Glob:Int = False )
'	Local P:Float = 0.0
'	Local Y:Float = 0.0
'	Local R:Float = 0.0
	Local Pitch:Float = 0.0
	Local Yaw:Float = 0.0
	Local Roll:Float = 0.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
	
	If Glob=False
		Quat = EulerToQuat( EntityPitch( Ent, True ), EntityYaw( Ent, True ), EntityRoll( Ent, True ) )	'Set Ent Quat
		Turn_Quat = EulerToQuat( X, Y, Z )		'Set turn quat
		Quat = MultiplyQuats( Quat, Turn_Quat )	'Multiply Entity quat with turn quat
		Quat = NormalizeQuat( Quat )			'normalise quat
		QuatToEuler2( Quat.x, Quat.y, Quat.z, Quat.w, Pitch, Yaw, Roll )	'Entity quat to euler
		RotateEntity Ent, Pitch, Yaw, Roll
	Else
		RotateEntity Ent, EntityPitch( Ent )+X, EntityYaw( Ent )+Y, EntityRoll( Ent )+Z
	EndIf
End Function

' 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