December 22, 2008 2

quaternion rotation

By in opengl, processing

quaternions have been plaguing my mind for months and their mystery has eluded me till now… finally figured the sucker out.

in short, they allow for intuitive rotation around each axis.
normally if you rotate around one axis and then around another, you get a combination of those two rotations and its not really where you want to be.
quaternions allow to rotate around each axis without effecting the rotation of the other axis, so imagine a orientating a aeroplane model in a 3D flying game…
an aeroplane can be rotated around each axis and these angles are referred to as roll (x-axis), pitch (y-axis) and yaw (z-axis).

roll is then the aeroplane direction moving up and down.
pitch is the aeroplane direction moving left to right.
and yaw is the aeroplane swaying from side to side.

so finally worked out the mathematics behind this by reverse engineering some existing arcball code.
below is the processing implementation done with pure opengl, it is using some handy classes in toxi’s geomutils.

the steps are,
1) work out the rotation vectors around each axis, simply by rotating the vector around an axis.
2) work out the rotation quaternion for each axis, by getting the dot and cross product of each rotation vector from its origin.
3) multiply the rotation quaternions of each axis. – this will give you the overall rotation quaternion.
4) convert the rotation quaternion into a matrix and apply that rotation matrix.
5) draw your aeroplane! done.

[sourcecode language='java']

float DEGTORAD = PI / 180;

Vec3D xrot, yrot, zrot;
Quaternion xrotQuat, yrotQuat, zrotQuat, rotQuat;
Matrix4x4 m;
float angleX, angleY, angleZ;

angleX = angleDegreesX * DEGTORAD;
angleY = angleDegreesY * DEGTORAD;
angleZ = angleDegreesZ * DEGTORAD;

xrot = Vec3D.Z_AXIS.copy().rotateX( angleX );
yrot = Vec3D.X_AXIS.copy().rotateY( angleY );
zrot = Vec3D.X_AXIS.copy().rotateZ( angleZ );

xrotQuat = new Quaternion( 1, new Vec3D( 0, 0, 0 ) );
xrotQuat.set( xrot.dot( Vec3D.Z_AXIS.copy() ), xrot.cross( Vec3D.Z_AXIS.copy() ) );

yrotQuat = new Quaternion( 1, new Vec3D( 0, 0, 0 ) );
yrotQuat.set( yrot.dot( Vec3D.X_AXIS.copy() ), yrot.cross( Vec3D.X_AXIS.copy() ) );

zrotQuat = new Quaternion( 1, new Vec3D( 0, 0, 0 ) );
zrotQuat.set( zrot.dot( Vec3D.X_AXIS.copy() ), zrot.cross( Vec3D.X_AXIS.copy() ) );

rotQuat = xrotQuat.multiply( yrotQuat ).multiply( zrotQuat );
m = rotQuat.getMatrix();

FloatBuffer rotMatrix;
rotMatrix = ByteBuffer.allocateDirect(4 * 4 * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
rotMatrix.put
(
new float[]
{
(float)m.matrix[0][0], (float)m.matrix[0][1], (float)m.matrix[0][2], (float)m.matrix[0][3],
(float)m.matrix[1][0], (float)m.matrix[1][1], (float)m.matrix[1][2], (float)m.matrix[1][3],
(float)m.matrix[2][0], (float)m.matrix[2][1], (float)m.matrix[2][2], (float)m.matrix[2][3],
(float)m.matrix[3][0], (float)m.matrix[3][1], (float)m.matrix[3][2], (float)m.matrix[3][3]
}
);
rotMatrix.flip();

gl.glPushMatrix();

gl.glTranslatef( loc.x, loc.y, loc.z );
gl.glMultMatrixf( rotMatrix );
gl.glTranslatef( -loc.x, -loc.y, -loc.z );

// draw here.

gl.glPopMatrix();

[/sourcecode]

Tags: , , , , , ,

2 Responses to “quaternion rotation”

  1. [...] bookmarks tagged rotation Julapy » Blog Archive » quaternion rotation saved by 4 others     nothinginteresting29 bookmarked on 12/23/08 | [...]

  2. ricardo says:

    Hi, where does the angleDegreesX, angleDegreesY and angleDegreesZ are coming from?

Leave a Reply