Is there a way to redefine a nodes roll and pitch axis?

eddy

19-12-2011 21:27:52

So the title says it all. Perhaps I made grammatical mistake with the multiple of axis. But my question stays. Can I somehow redefine those darn things. I had to make some changes to my program and it all went down the drain. Please don't tell me the only way is to use quaternions and the like.

McDonte

20-12-2011 02:23:10

Actually I do not know but I really doubt there is a way to redefine these axis. Even if there is one this would be really bad coding style since the whole model of your three dimensional world would not be unique anymore... I am sure there is a better solution, probably using quaternions, sorry :( :wink:

Pyritie

20-12-2011 02:38:21

So the title says it all. Perhaps I made grammatical mistake with the multiple of axis. But my question stays. Can I somehow redefine those darn things. I had to make some changes to my program and it all went down the drain. Please don't tell me the only way is to use quaternions and the like.
A single node or every node?

If it's just a single node, a crude workaround is to just add another node to the scene graph so it kinda "comes between" your old parent and old child. Then rotate that node's axis to be correct.

But if it's every node then as far as I'm aware you can't change it.

You might want to try asking on the regular ogre forums though, since they're a lot more active than here.

Tubulii

01-01-2012 20:08:03

If it's just a single node, a crude workaround is to just add another node to the scene graph so it kinda "comes between" your old parent and old child. Then rotate that node's axis to be correct.
I think that is the "How to create a camera system". It is explained in the Ogre Wiki.


But you could set the Orientation back to ZERO (mynode.Orientation = Orientation.Zero) [sorry, quaternions ;)]. That should reset any rotation. If you want to rotate your camera, I higly recommend to read the wiki and look at the CameraMan(ager) class in the Mogre sample project.

Beauty

15-01-2012 16:44:28

Yes, the camera tutorial explains a good suggestion by usage of "helper nodes". Then you can manage your nodes by Euler Angles very well.

Here is the link:
http://www.ogre3d.org/tikiwiki/3rd+pers ... m+tutorial

But keep in mind that Euler Angles can cause problems in relation to the Gimbal Lock.
Further information and a video tutorial you find here:
http://www.ogre3d.org/tikiwiki/-Gimbal+Lock


For my application I also need an other coordinate system.
My solution: I wrote a converter class which converts coordinates from my custom coordinate system to the Ogre coordinate system (in Euler angles).
As second step I converted the Ogre related Euler Angles to Ogre quaternions.
Well, this would not work for all kinds of applications, but for my needs it's fine.

More difficult is to convert Ogre quaternions back to Euler Angles. In general it works, but the angles can be different than you expect. (Because one quaternion state can be created by different combinations of Euler Angles. When you read out the Euler Angles from Quaternions, you will get ONE combination. But this could be different to your "wanted" combination.)


Also important:
When you read Euler Angles from quaternions, you will get different value combination by Mogre in comparison to Ogre (C++). Also there is a bug (Mogre only) that in special cases a returned value is null.
The reason is, that Mogre currently uses System.Math instead of Mogre.Math for math functions like Sin().
All needed knowledge I found out and reported it long time ago. Unfortunately this bug wasn't fixed until today.
As long as you know about this and add a null check, you don't need to care about.

Details I added to the Mogre bugtracker (including links to further details/solutions).
  1. Mogre.Math.Sin() has problems [/*:m]
  2. Quaternion.Yaw returns NaN (not defined) in 2 special cases [/*:m]
  3. wrap/improve Quaternion.GetYaw() -- support parameter[/*:m][/list:u]

Beauty

16-01-2012 01:06:31

@ eddy
Is there a way to redefine a nodes roll and pitch axis?

So the title says it all. Perhaps I made grammatical mistake with the multiple of axis. But my question stays. Can I somehow redefine those darn things. I had to make some changes to my program and it all went down the drain. Please don't tell me the only way is to use quaternions and the like.


Perhaps the Euler Angle Class of user Kojack is useful for you:
http://www.ogre3d.org/tikiwiki/Euler+Angle+Class

The Euler class allows you to directly set/get absolute pitch, yaw or roll values without affecting each other, for example setting the orientation to face east while preserving the pitch and roll.

update
I looked to the source code of the class now.
It should work even with the unfixed Mogre bug, because the related functions (getYaw() etc.) are not used by the class.
You just need to port the code to C#. (In this case, please publish the result.)
But before you should search in the forums. Maybe somebody still created a C# clone. :wink:

Beauty

17-01-2012 12:48:51

The topic I splitted now:
Common Euler Angles discussions are here new:
Euler angles - current bugs + improved Euler Angle Class

Beauty

17-01-2012 12:59:39

@ eddie
Here I quote 2 posts of the splitted topic, which could be useful for your problem. (If you don't want to follow the whole splitted discussion.)

Maybe somebody still created a C# clone.
Ahm, *looking for it*... there it is:
(the old version, i will it update in the next days)
(VB.Net)
Imports Mogre
Public Class Euler
' ConstrucTor which takes yaw, pitch and roll values.
Public Sub New()
MyClass.New(New Radian(0.0F), New Radian(0.0F), New Radian(0.0F))
End Sub
Public Sub New(ByVal yaw As Radian)
MyClass.New(yaw, New Radian(0.0F), New Radian(0.0F))

End Sub
Public Sub New(ByVal yaw As Radian, ByVal pitch As Radian)
MyClass.New(yaw, pitch, New Radian(0.0F))

End Sub
Public Sub New(ByVal Oriantation As Quaternion)
MyClass.New(Oriantation.Yaw, Oriantation.Pitch, Oriantation.Roll)
End Sub
Public Sub New(ByVal Euler As Euler)
MyClass.New(Euler.m_yaw, Euler.m_pitch, Euler.m_roll)
End Sub
Public Sub New(ByVal yaw As Radian, ByVal pitch As Radian, ByVal roll As Radian)
m_yaw = yaw
m_pitch = pitch
m_roll = roll
m_changed = True
End Sub
''' <summary>
''' Get the Yaw angle.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetYaw() As Radian
Return m_yaw
End Function
''' <summary>
''' Get the Pitch angle.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetPitch() As Radian
Return m_pitch
End Function

''' <summary>
''' Get the Roll angle.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetRoll() As Radian
Return m_roll
End Function

''' <summary>
''' Apply a relative yaw. (Adds angle To current yaw)
''' Angles wrap around within the range 0 To 2*PI radians (0 To 360 degrees)
''' </summary>
''' <param name="y"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function yaw(ByVal y As Radian) As Euler
m_yaw += y
If m_yaw.ValueRadians() < 0.0F Then
m_yaw = System.Math.IEEERemainder(m_yaw.ValueRadians(), Math.PI * 2.0F) + Math.PI * 2.0F
ElseIf m_yaw.ValueRadians() > Math.PI Then
m_yaw = System.Math.IEEERemainder(m_yaw.ValueRadians(), Math.PI * 2.0F)
End If
m_changed = True
Return Me
End Function
''' <summary>
''' Apply a relative pitch. (Adds angle To current pitch)
''' </summary>
''' <param name="p"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function pitch(ByVal p As Radian) As Euler
m_pitch += p
m_changed = True
Return Me
End Function
''' <summary>
''' Apply a relative roll. (Adds angle To current roll)
''' </summary>
''' <param name="r"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function roll(ByVal r As Radian) As Euler
m_roll += r
m_changed = True
Return Me
End Function
''' <summary>
''' Set the yaw.
''' </summary>
''' <param name="y"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function SetYaw(ByVal y As Radian) As Euler
m_yaw = y
m_changed = True
Return Me
End Function

''' <summary>
''' Set the pitch.
''' </summary>
''' <param name="p"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function SetPitch(ByVal p As Radian) As Euler
m_pitch = p
m_changed = True
Return Me
End Function

''' <summary>
''' Set the roll.
''' </summary>
''' <param name="r"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function SetRoll(ByVal r As Radian) As Euler
m_roll = r
m_changed = True
Return Me
End Function

''' <summary>
''' Get a vector pointing forwards.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetForward() As Vector3
Return ToQuaternion() * Vector3.NEGATIVE_UNIT_Z
End Function
''' <summary>
''' Get a vector pointing To the right.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetRight() As Vector3
Return ToQuaternion() * Vector3.UNIT_X
End Function

''' <summary>
''' Get a vector pointing up.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetUp() As Vector3
Return ToQuaternion() * Vector3.UNIT_Y
End Function

''' <summary>
''' Calculate the quaternion of a euler object.
''' The result is cached, it is only recalculated when the component euler angles are changed.
''' </summary>
''' <returns></returns>
''' <remarks></remarks>
Public Function ToQuaternion() As Quaternion
If m_changed Then
m_cachedQuaternion = New Quaternion(m_yaw, Vector3.NEGATIVE_UNIT_Y) * New Quaternion(m_pitch, Vector3.UNIT_X) * New Quaternion(m_roll, Vector3.NEGATIVE_UNIT_Z)
m_changed = False
End If
Return m_cachedQuaternion
End Function
'Public Shared OperaTor Quaternion(ByVal ImpliedObject As Euler)
' Return ToQuaternion()
' End OperaTor
''' <summary>
''' Casting operaTor. This allows any ogre function that wants a Quaternion To accept a Euler instead
''' </summary>
''' <param name="ImpliedObject"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Shared Widening Operator CType(ByVal ImpliedObject As Euler) As Quaternion
Return ImpliedObject.ToQuaternion
End Operator

''' <summary>
''' Set the yaw and pitch To face in the given direction.
''' The direction doesn't need To be normalised.
''' Roll is unaffected.
''' </summary>
''' <param name="v"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function SetDirection(ByVal v As Vector3) As Euler
Dim d As Vector3 = v.NormalisedCopy
m_pitch = Math.ASin(d.y)
m_yaw = Math.ATan2(d.z, d.x) + New Radian((Math.PI / 2.0))
m_changed = True

Return Me
End Function

''' <summary>
''' Get the angular difference between the current yaw and the specified yaw.
''' Only yaw is considered, pitch and roll are ignored.
''' </summary>
''' <param name="a"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetYawToDirection(ByVal a As Radian) As Radian
Dim angle As Single = (a - m_yaw).ValueRadians()
If angle > Math.PI Then
angle = -Math.PI * 2.0F + angle
ElseIf angle < -Math.PI Then
angle = Math.PI * 2.0F + angle
End If
Return New Radian(angle)
End Function

''' <summary>
''' Get the angular difference between the current yaw and the specified direction vector.
''' Only yaw is considered, pitch and roll are ignored.
''' </summary>
''' <param name="v"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetYawToDirection(ByVal v As Vector3) As Radian
Return GetYawToDirection(New Radian(Math.ATan2(v.z, v.x) + New Radian(Math.PI / 2.0F)))
End Function

''' <summary>
''' Get the angular difference between the current yaw and the specified euler object.
''' Only yaw is considered, pitch and roll are ignored.
''' </summary>
''' <param name="e"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function GetYawToDirection(ByVal e As Euler) As Radian
Return GetYawToDirection(e.m_yaw)
End Function


''' <summary>
''' Change the yaw To face in the direction of the vector.
''' Only yaw is changed, pitch and roll are ignored.
''' </summary>
''' <param name="v"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function yawToDirection(ByVal v As Vector3) As Euler
m_yaw = GetYawToDirection(v)
m_changed = True
Return Me
End Function



''' <summary>
''' Change the yaw To face in the direction of the euler object.
''' Only yaw is changed, pitch and roll are ignored.
''' </summary>
''' <param name="e"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Function yawToDirection(ByVal e As Euler) As Euler
'C++ TO VB CONVERTER WARNING: The following line was determined To be a copy construcTor call - this should be verified and a copy construcTor should be created if it does not yet exist:
'ORIGINAL LINE: m_yaw = GetYawToDirection(e);
m_yaw = GetYawToDirection(New Euler(e))
m_changed = True
Return Me
End Function
Public Function ToDisplayString() As String
Return String.Format("X: {0:00}° Y: {1:00}° Z: {2:00}°", GetPitch.ValueDegrees, GetYaw.ValueDegrees, GetRoll.ValueDegrees)
End Function
Public Shared Function ParseDisplayString(ByVal str As String) As Euler
Dim data = str.Split(" ")
If data.Length = 6 Then
Dim roll = Single.Parse(data(5))
Dim pitch = Single.Parse(data(1))
Dim yaw = Single.Parse(data(3))
Return New Euler(New Degree(yaw), New Degree(pitch), New Degree(roll))
Else
Return Nothing
End If
End Function
'' stream operaTor, for printing the euler component angles To a stream
' Public Shared OperaTor <<(ByVal o As IO.Stream, ByVal e As Euler) As IO.Stream
' o << "<Y:" << e.m_yaw << ", P:" << e.m_pitch << ", R:" << e.m_roll << ">"
' Return o
' End OperaTor
Protected m_yaw As Radian = New Radian ' Rotation around the Y axis.
Protected m_pitch As Radian = New Radian ' Rotation around the X axis.
Protected m_roll As Radian = New Radian ' Rotation around the Z axis.
Protected m_cachedQuaternion As Quaternion = New Quaternion() ' Cached quaternion equivalent of this euler object.
Protected m_changed As Boolean ' Is the cached quaternion out of date?

End Class


What do you think about?
You are correct, but I am not a Mogre Developer... but it is possible.



I looked to the source code of the class now.
It should work even with the unfixed Mogre bug, because the related functions (getYaw() etc.) are not used by the class.

Important:
This is only related to the OLD class.

By my motivation Kojack published his new improved class in the wiki today.
BUT: It seems so that his new class uses the methods/properties, which returns "buggy" values.
So I suppose we can't use the NEW class for Mogre as long as the Orientation bug is not fixed.

The link to the old Euler Angle Class you grabb from the history of the wiki page:
http://www.ogre3d.org/tikiwiki/tiki-pag ... &preview=4

Ahm, *looking for it*... there it is
Nice.
I think it should be easy create C# code from it by usage of a VB-C# converter.
For example this one:
http://www.developerfusion.com/tools/co ... harp-to-vb