Home > C++ Classes, Programming > Quaternion Class

Quaternion Class

August 1st, 2009 Leave a comment Go to comments

To download:

1
bzr branch http://bazaar.enseed.com/lib/Generic/ look under Geometry/Quaternion.h

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.

1
2
3
4
5
6
7
8
9
10
11
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);
}

Executing the above code, you should obtain:

1
2
3
4
5
6
7
8
9
(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 3×3 or 4×4 matrix:

1
2
3
4
5
6
7
8
9
10
11
12
13
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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.

Categories: C++ Classes, Programming Tags:
  1. No comments yet.
  1. No trackbacks yet.
*

Please leave these two fields as-is:

Protected by Invisible Defender. Showed 403 to 153,475 bad guys.