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