Yaw pitch and roll are the same as euler angles, which represent orientation by a combination of 3 rotations about the x, y, z axis.
The problem is that the order is important, you can get the same orientation with order xyz or zyx or xzy... but the angles would be different.
Something like xzx is also possible, but i'm not shure if my code can handle this and you'll not need it.
In my code the order is constant in both functions, defined by "int order", given as hexadezimal number.
That's a compressed way to store 3 indices, each 4 bits in a single 32 bit number.
I've commented and i hope you can read it, translate it to basic either using an array with 3 values or keep the bit logic style.
By trial and error you can find the order you want, 012, 210, 021...
The code operates on 4x4 matrices (16 values, same as newton, and same as illustrated in last topic).
It would work on 3x3 matrices too (9 values).
A 3x3 matrix can store orientation, but no position and is included in top left of a 4x4 matrix.
As noted the mtarices contain the 3 basis vectors (x,y,z Axis), mostly displayed as red, green and blue vectors form the center in 3D Modellers & Editors.
Thats the best way to imagine orientation.
Rotation is similar to orientation, as translation is similar to position (vector to point).
You can represent rotation like orientation an vice versa.
To avoid the order problem, the best way to imagine rotation is:
A direction vector and a single angle that rotates around this vector (called axis and angle rotation, which can represent any rotation).
That's where quaternions come handy, as they encode this axis and angle somehow in 4 values.
With quats it's easy for ex. to interpolate nicely between 2 or more orientations, which is horror using matrices.
You can convert between matrix and quat form.
What you need is a math library that contains 3d vectors, 3x3 Matrices, 4x4 Matrices, Quaternions.
I guess DirectX contains that all, Newton contains one,...
Most of them include the code below too, but mostly the order is hardcoded, so it might be useful.
- Code: Select all
void CalcOrientationMatrix (matrix4f &m, v3f rotation)
{
int order = 0x012;//xyz // 0x means hexadezimal
int a0 = (order>>8)&3; // extract 1st (0x0**) = 0
int a1 = (order>>4)&3; // extract 2nd (0x*1*) = 1
int a2 = (order>>0)&3; // extract 3rd (0x**2) = 2
matrix4f r[3];
r[0].XRot (DEG_TO_RAD(rotation.x)); // construct rotation matrix around x axis, deg to rad is simply degrees to radians
r[1].YRot (DEG_TO_RAD(rotation.y));
r[2].ZRot (DEG_TO_RAD(rotation.z));
m = r[a0];
m *= r[a1];
m *= r[a2];
}
v3f ToEulerAngles (matrix4f &m)
{
int order = 0x012;//xyz
int a0 = (order>>8)&3;
int a1 = (order>>4)&3;
int a2 = (order>>0)&3;
v3f euler;
// Assuming the angles are in radians.
if (m.m[a0][a2] > 0.998)
{ // singularity at north pole
euler[a0] = -atan2(m.m[a2][a1], m.m[a1][a1]);
euler[a1] = -PI/2;
euler[a2] = 0;
return euler;
}
if (m.m[a0][a2] < -0.998)
{ // singularity at south pole
euler[a0] = -atan2(m.m[a2][a1], m.m[a1][a1]);
euler[a1] = PI/2;
euler[a2] = 0;
return euler;
}
euler[a0] = -atan2(-m.m[a1][a2], m.m[a2][a2]);
euler[a1] = -asin ( m.m[a0][a2]);
euler[a2] = -atan2(-m.m[a0][a1], m.m[a0][a0]);
return euler;
}