pitch/yaw/roll

Blitz3D Forums/Blitz3D Bug Reports/pitch/yaw/roll

Finally I was able to isolate my problem. It is this:
Graphics3D 800, 600, 0, 2
SetBuffer BackBuffer()

pivot = CreatePivot()

RotateEntity pivot, 90, 90, 0

Print EntityPitch(pivot)
Print EntityYaw(pivot)
Print EntityRoll(pivot)

The yaw returns zero. So instead of returning 90,90,0 it returns 90,0,0.
Is this a bug ? Is there a way around this ? Thanks in advance.

I think this is called gimbal lock:
http://en.wikipedia.org/wiki/Gimbal_lock

It is a known limitation when using Euler angles ie. it's not a bug. It happens when you try complex rotations. The known way around it is using quaterions. I've no idea how you do that though.

Definately Gimbal lock ... see this thread for possible solution.

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

Aha, so this is the infamous Gimbal lock. Thanks a lot, I used fredborgs solution and it works now.
I also tried getting the pitch/yaw/roll directly from the GetMatElement() matrix, with the help of a routine from leadwerks. For completion, I added both functions:
Thanks again, after hunting me all night, I hope this Gimbal demon is exorcised for good now. :)
Graphics3D 800, 600, 0, 2 
SetBuffer BackBuffer() 

pivot = CreatePivot() 
RotateEntity pivot, 90, 90, 0 

Print "standard:"
Print EntityPitch(pivot) 
Print EntityYaw(pivot) 
Print EntityRoll(pivot) 

Print "fredborgs:"
Print GlobalEntityPitch(pivot)
Print GlobalEntityYaw(pivot)
Print GlobalEntityRoll(pivot)

Print "matrix:"
Print mEntityPitch(pivot)
Print mEntityYaw(pivot)
Print mEntityRoll(pivot)


;fredborg
;post = www.blitzbasic.com/Community/posts.php?topic=31781 <http://www.blitzbasic.com/Community/posts.php?topic=31781> 

Const GIMBAL_LIMIT# = 89.98

Function GlobalEntityPitch#(entity)

	pit# = Int(EntityPitch(entity,True)*1000)/1000.0
	
	Return pit

End Function

Function GlobalEntityYaw#(entity)
	
	pit# = Int(EntityPitch(entity,True)*1000)/1000.0
	yaw# = Int(EntityYaw(entity,True)*1000)/1000.0
	
	If Abs(pit)>GIMBAL_LIMIT
		temp = CreatePivot(entity)
		TurnEntity temp,Sgn(pit)*-90.0,0,0
		yaw# = Int(EntityYaw(temp,True)*1000)/1000.0
		FreeEntity temp
	EndIf

	Return yaw
	
End Function

Function GlobalEntityRoll#(entity)

	pit# = Int(EntityPitch(entity,True)*1000)/1000.0
	rol# = Int(EntityRoll(entity,True)*1000)/1000.0

	If Abs(pit)>GIMBAL_LIMIT
		temp = CreatePivot(entity)
		TurnEntity temp,Sgn(pit)*-90.0,0,0
		rol# = Int(EntityRoll(temp,True)*1000)/1000.0
		FreeEntity temp
	EndIf

	Return rol

End Function

;leadwerks
;post = <a href="http://www.blitzbasic.co.nz/Community/posts.php?topic=21362" target="_blank">http://www.blitzbasic.co.nz/Community/posts.php?topic=21362</a>
Function mEntityPitch#(Entity) 
	Return -ASin(GetMatElement(Entity,2,1)) 
End Function 

Function mEntityYaw#(Entity) 
	Return -ATan2(GetMatElement(Entity,2,0),GetMatElement(Entity,2,2)) 
End Function 

Function mEntityRoll#(Entity) 
	Return ATan2(GetMatElement(Entity,0,1),GetMatElement(Entity,1,1)) ;-ATan2(m(1,0),m(1,1)) 
End Function 


(edit)
Because I needed the local angles too, I modified the FredBorg functions. As fas as I can tell they work, but I don't understand exactly how they work I just made them local (to the parent):
Const GIMBAL_LIMIT# = 89.98

Function GlobalEntityPitch#(entity)

	pit# = Int(EntityPitch(entity)*1000)/1000.0
	
	Return pit

End Function

Function GlobalEntityYaw#(entity)
	
	pit# = Int(EntityPitch(entity)*1000)/1000.0
	yaw# = Int(EntityYaw(entity)*1000)/1000.0
	
	If Abs(pit)>GIMBAL_LIMIT
		temp = CreatePivot(entity)
		EntityParent temp, GetParent(entity)
		TurnEntity temp,Sgn(pit)*-90.0,0,0
		yaw# = Int(EntityYaw(temp)*1000)/1000.0
		FreeEntity temp
	EndIf

	Return yaw
	
End Function

Function GlobalEntityRoll#(entity)

	pit# = Int(EntityPitch(entity)*1000)/1000.0
	rol# = Int(EntityRoll(entity)*1000)/1000.0

	If Abs(pit)>GIMBAL_LIMIT
		temp = CreatePivot(entity)
		EntityParent temp, GetParent(entity)
		TurnEntity temp,Sgn(pit)*-90.0,0,0
		rol# = Int(EntityRoll(temp)*1000)/1000.0
		FreeEntity temp
	EndIf

	Return rol

End Function