Quaternion Class [download]
[view
Quat.{h,inline.h,cpp}
]
depends on:
nothing (but likes Matrix and Point)
I used quaternions mainly for rotations around an axis (for example, to implement a trackball that doesn't suffer from the gimbal lock like matrix-based trackballs do).
Rotation of Points Around an Axis
Rotation around an axis is done in three steps. First you create a quaternion q based on the axis and angle of rotation that you want. Then, you create a quaternion pt that will act as the point that you want to rotate. Finally, you multiply: q*pt*q.inverse().
You have to take extra care that the axis that you supply is a unit vector. You will then obtain a unit quaternion, and instead of taking q.inverse(), you can use q.unitInverse() which is faster.
Point3d axis = Point3d(1.0, 1.0, 0.0).normalized();
Quatd q(axis, 2*M_PI/9); // 40 degrees
Quatd pt(0, 1, 0, 0); // w = 0, x = 1, y =0, z = 0
// do a 360 around the axis
for (int i = 0; i < 9; ++i)
{
pt = q*pt*q.unitInverse();
printf("(%f %f %f)\n", pt.x, pt.y, pt.z);
}
|
In this case, you will get the following output:
(0.883022 0.116978 -0.454519) (0.586824 0.413176 -0.696364) (0.250000 0.750000 -0.612372) (0.030154 0.969846 -0.241845) (0.030154 0.969846 0.241845) (0.250000 0.750000 0.612372) (0.586824 0.413176 0.696364) (0.883022 0.116978 0.454519) (1.000000 0.000000 -0.000000) |
Obtaining a Rotation Matrix from a Quaternion
You can also choose to work with matrices instead and convert a quaternion to a 3x3 or 4x4 matrix:
Point3d axis = Point3d(1.0, 1.0, 0.0).normalized();
Quatd q(axis, 2*M_PI/9);
Point4d pt(1.0, 0.0, 0.0, 1.0); // x = 1, y = 0, z = 0 (homogeneous w = 1)
Matrix4d m;
q.to4x4Matrix(&m);
printf("rotation matrix:\n %s\n", m.serialize().c_str());
for (int i = 0; i < 9; ++i)
{
pt = m*pt;
printf("(%f %f %f)\n", pt.x, pt.y, pt.z);
}
|
And you obtain the following output
rotation matrix :
{
{ 0.8830221891, 0.1169777811, -0.4545194805, 0.0000000000 }
{ 0.1169777811, 0.8830221891, 0.4545194805, 0.0000000000 }
{ 0.4545194805, -0.4545194805, 0.7660444379, 0.0000000000 }
{ 0.0000000000, 0.0000000000, 0.0000000000, 1.0000000000 }
}
(0.883022 0.116978 0.454519)
(0.586824 0.413176 0.696364)
(0.250000 0.750000 0.612372)
(0.030154 0.969846 0.241845)
(0.030154 0.969846 -0.241845)
(0.250000 0.750000 -0.612372)
(0.586824 0.413176 -0.696364)
(0.883022 0.116978 -0.454519)
(1.000000 -0.000000 0.000000)
|
Concatenating Several Multiplications
You can concatenate several multiplcations by simply multiplicating your rotation quaternions together. It's important to make sure that each quaternion is a unit quaternion though. If you created them with a unit axis, it should always be the case.
[TextCounter Fatal Error: Could Not Write to File __petitg_cpp_quat_html]

