|
Quaternions are an alternate way to represent the rotation part of a
transformation, and can be easier to manipulate than matrices. As with a
matrix, you can encode a geometric transformations in one, concatenate
several of them to merge multiple transformations, and apply them to a
vector, but they can only store pure rotations. The big advantage is that
you can accurately interpolate between two quaternions to get a part-way
rotation, avoiding the gimbal problems of the more conventional euler angle
interpolation.
Quaternions only have floating point versions, without any _f suffix. Other
than that, most of the quaternion functions correspond with a matrix
function that performs a similar operation.
Quaternion means 'of four parts', and that's exactly what it is. Here is the
structure:
typedef struct QUAT
{
float w, x, y, z;
}
You will have lots of fun figuring out what these numbers actually mean, but
that is beyond the scope of this documentation. Quaternions do work -- trust
me.
extern QUAT identity_quat;
Global variable containing the 'do nothing' identity quaternion.
Multiplying by the identity quaternion has no effect.
void get_x_rotate_quat(QUAT *q, float r);
void get_y_rotate_quat(QUAT *q, float r);
void get_z_rotate_quat(QUAT *q, float r);
Construct axis rotation quaternions, storing them in q. When applied to a
point, these quaternions will rotate it about the relevant axis by the
specified angle (given in binary, 256 degrees to a circle format).
void get_rotation_quat(QUAT *q, float x, float y, float z);
Constructs a quaternion that will rotate points around all three axis by
the specified amounts (given in binary, 256 degrees to a circle format).
void get_vector_rotation_quat(QUAT *q, float x, y, z, float a);
Constructs a quaternion that will rotate points around the specified
x,y,z vector by the specified angle (given in binary, 256 degrees to a
circle format).
void quat_to_matrix(const QUAT *q, MATRIX_f *m);
Constructs a rotation matrix from a quaternion.
void matrix_to_quat(const MATRIX_f *m, QUAT *q);
Constructs a quaternion from a rotation matrix. Translation is discarded
during the conversion. Use get_align_matrix_f() if the matrix is not
orthonormalized, because strange things may happen otherwise.
void quat_mul(const QUAT *p, const QUAT *q, QUAT *out);
Multiplies two quaternions, storing the result in out. The resulting
quaternion will have the same effect as the combination of p and q, ie.
when applied to a point, (point * out) = ((point * p) * q). Any number of
rotations can be concatenated in this way. Note that quaternion
multiplication is not commutative, ie. quat_mul(p, q) != quat_mul(q, p).
void apply_quat(const QUAT *q, float x, y, z, *xout, *yout, *zout);
Multiplies the point (x, y, z) by the quaternion q, storing the result in
(*xout, *yout, *zout). This is quite a bit slower than apply_matrix_f(),
so only use it to translate a few points. If you have many points, it is
much more efficient to call quat_to_matrix() and then use
apply_matrix_f().
void quat_interpolate(const QUAT *from, *to, float t, QUAT *out);
Constructs a quaternion that represents a rotation between from and to.
The argument t can be anything between 0 and 1 and represents where
between from and to the result will be. 0 returns from, 1 returns to, and
0.5 will return a rotation exactly in between. The result is copied to
out. This function will create the short rotation (less than 180 degrees)
between from and to.
void quat_slerp(const QUAT *from, *to, float t, QUAT *out, int how);
The same as quat_interpolate(), but allows more control over how the
rotation is done. The how parameter can be any one of the values:
QUAT_SHORT - like quat_interpolate(), use shortest path
QUAT_LONG - rotation will be greater than 180 degrees
QUAT_CW - rotate clockwise when viewed from above
QUAT_CCW - rotate counterclockwise when viewed from above
QUAT_USER - the quaternions are interpolated exactly as given
|