Oh my... been there done that... I actually took the Euler angle approach
first too, and it actually started to work until I started to do rolls
starting from a position where the tail to nose was no longer in orientation
alignment. Many hours were spent getting Euler to work... now perhaps you
need not work with true 3d roll controls, and it may work out. But
ultimately I had to keep things stored as quats until the last moment when I
extracted a frame's slice of delta offsets. Good luck, and I hope you do
not fall in the same pitfalls as I.
I have included all my Euler work in text attachment... it was not a
success, but is a good learning experience and probably worth a look:
James Killian
----- Original Message -----
From: "Christian Sam" <[email protected]>
To: <[email protected]>
Sent: Wednesday, June 03, 2009 7:15 PM
Subject: Re: [osg-users] get the x-axis angle of a rotation
Hi,
i had to do a little further research on the web because first i didn't
understand what your code-snippet is doing. i found a website which
describes the whole topic:
"http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToEuler/index.htm"
thank you james and max for posting the clues/code.
Christian
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=13462#13462
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
/*
http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/index.htm
heading = atan2(2*qy*qw-2*qx*qz , 1 - 2*qy^2 - 2*qz^2)
attitude = asin(2*qx*qy + 2*qz*qw)
bank = atan2(2*qx*qw-2*qy*qz , 1 - 2*qx^2 - 2*qz^2)
except when qx*qy + qz*qw = 0.5 (north pole)
which gives:
heading = 2 * atan2(x,w)
bank = 0
and when qx*qy + qz*qw = -0.5 (south pole)
which gives:
heading = -2 * atan2(x,w)
bank = 0
*/
void QuatToEulerAngles (const osg::Quat &q,double &heading,double &attitude,double &bank)
{
const osg::Quat q1(q.z(),q.y(),q.x(),q.w());
double test = q1.x()*q1.y() + q1.z()*q1.w();
if (test > 0.499)
{ // singularity at north pole
//heading = 2 * atan2(q1.x(),q1.w());
heading = atan2(q1.x(),q1.w());
attitude = M_PI/2;
bank = 0;
return;
}
if (test < -0.499)
{ // singularity at south pole
//heading = -2 * atan2(q1.x(),q1.w());
heading = atan2(q1.x(),q1.w());
attitude = - M_PI/2;
bank = 0;
return;
}
double sqw = q1.w()*q1.w();
double sqx = q1.x()*q1.x();
double sqy = q1.y()*q1.y();
double sqz = q1.z()*q1.z();
double unit = sqx + sqy + sqz + sqw; // if normalised is one, otherwise
is correction factor
#if 0 //This is the original
heading = atan2(2*q1.y()*q1.w()-2*q1.x()*q1.z() , 1 - 2*sqy - 2*sqz);
attitude = asin(2*test);
bank = atan2(2*q1.x()*q1.w()-2*q1.y()*q1.z() , 1 - 2*sqx - 2*sqz);
#else //This one is optimized
heading = atan2(2*q1.y()*q1.w()-2*q1.x()*q1.z() , sqx - sqy - sqz +
sqw);
attitude = asin(2*test/unit);
//attitude = asin(2*qx*qy + 2*qz*qw)
//attitude = asin((2*q1.x()*q1.y()) + (2*q1.z()*q1.w()));
bank = atan2(2*q1.x()*q1.w()-2*q1.y()*q1.z() , -sqx + sqy - sqz + sqw);
#endif
}
//This does some minor variation of the result to conform to how I work with
the Vec3
osg::Vec3d QuatToEulerAngles (const osg::Quat &q1)
{
double heading,attitude,bank;
QuatToEulerAngles(q1,heading,attitude,bank);
//attitude hack...
//Not sure why attitude gives a smaller range so I'm scaling it here: :(
attitude*=2;
//Not sure why these are shuffled around
return osg::Vec3d(bank+M_PI,attitude+M_PI,heading+M_PI);
}
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org