pfQuat - Set and operate on quaternions
void pfQuat::makeRot(float angle, float x, float y, float z);
void pfQuat::getRot(float *angle, float *x, float *y, float *z);
float pfQuat::length(void);
void pfQuat::conj(const pfQuat &q);
void pfQuat::exp(const pfQuat &q);
void pfQuat::log(const pfQuat &q);
void pfQuat::mult(const pfQuat &q1, const pfQuat &q2);
void pfQuat::div(const pfQuat &q1, const pfQuat &q2);
void pfQuat::invert(const pfQuat &q);
int pfQuat::equal(const pfQuat &q1, const pfQuat &q2);
void pfQuat::slerp(float t, const pfQuat &q1, const pfQuat &q2);
pfQuat & pfQuat::operator *(const pfQuat &m);
pfQuat pfQuat::operator *=(const pfQuat &m);
pfQuat pfQuat::operator /(const pfQuat &v);
pfQuat & pfQuat::operator /=(const pfQuat &v);
The IRIS Performer class pfQuat is derived from the parent class pfVec4, so each of these member functions of class pfVec4 are also directly usable with objects of class pfQuat. This is also true for ancestor classes of class pfVec4.
void* pfVec4::operator new(size_t); void* pfVec4::operator new(size_t, void *arena); void pfVec4::addScaled(pfVec3& dst, const pfVec3& v1, float s, const pfVec3& v2); void pfVec4::add(const pfVec4& v1, const pfVec4& v2); int pfVec4::almostEqual(const pfVec4& v2, float tol); void pfVec4::combine(float s1, const pfVec4& v1, float s2, const pfVec4& v2); void pfVec4::copy(const pfVec4& v); float pfVec4::distance(const pfVec4& pt2); float pfVec4::dot(const pfVec4& v2); int pfVec4::equal(const pfVec4& v2); float pfVec4::length(void); void pfVec4::negate(const pfVec4& v); float pfVec4::normalize(void); void pfVec4::scale(float s, const pfVec4& v); void pfVec4::set(float x, float y, float z, float w); float pfVec4::sqrDistance(const pfVec4& pt2); void pfVec4::sub(const pfVec4& v1, const pfVec4& v2); void pfVec4::xform(const pfVec4& v, const pfMatrix& m); float& pfVec4::operator [](int i); const float& pfVec4::operator [](int i); int pfVec4::operator ==(const pfVec4& v); pfVec4 pfVec4::operator -() const; pfVec4 pfVec4::operator +(const pfVec4& v); pfVec4 pfVec4::operator -(const pfVec4& v); pfVec4& pfVec4::operator =(const pfVec4& v); pfVec4& pfVec4::operator *=(float d); pfVec4& pfVec4::operator /=(float d); pfVec4& pfVec4::operator +=(const pfVec4& v); pfVec4& pfVec4::operator -=(const pfVec4& v); pfVec4 pfVec4::operator *(const pfVec4& v, float d); pfVec4 pfVec4::operator *(float d, const pfVec4& v); pfVec4 pfVec4::operator /(const pfVec4& v, float d); pfVec4 pfVec4::operator *(const pfVec4& v, const pfMatrix& m);
pfQuat represents a quaternion as the four floating point values (x, y, z, w) of a pfVec4.
The default constructor pfQuat() is empty and does no initialization. new(arena) allocates a pfQuat from the specified memory arena, or from the heap if arena is NULL. new allocates a pfQuat from the default memory arena (see pfGetSharedArena). pfQuats can also be created automatically on the stack or statically. pfQuats allocated with new can be deleted with delete or pfDelete.
pfQuat::makeRot converts an axis and angle rotation representation to a quaternion. pfQuat::getRot is the inverse operation. It produces the axis (as a unit length direction vector) and angle equivalent to the given quaternion. Also see pfMatrix::makeQuat and pfMatrix::getOrthoQuat.
Several monadic quaternion operators are provided. pfQuat::conj produces the complex conjugate dst of q by negating only the complex components (x, y, and z) which results in an inverse rotation. pfQuat::exp and pfQuat::log perform complex exponentiation and logarithm functions respectively. The length of a quaternion is computed by pfQuat::length and is defined as the norm of all four quaternion components. Macro equivalents are PFCONJ_QUAT and PFLENGTH_QUAT. For negation, use the pfVec4 routine, pfVec4::negate.
pfQuat::mult and pfQuat::div are dyadic quaternion operations which provide the product, and quotient of two quaternions. When quaternions are used to represent rotations, multiplication of two quaternions is equivalent, but more efficient, than the multiplication of the two correspondinging rotation matrices.
pfQuat::invert computes the multiplicative inverse of a quaternion. These operations are the basis from which the other quaternion capabilities have been derived. Macro equivalents are PFMULT_QUAT, PFDIV_QUAT, and PFINVERT_QUAT. For addition and scalar multiplication, use the pfVec4 routines pfVec4::add, pfVec4::sub, and pfVec4::scale. Comparisons can be made with the pfVec4 member functions pfVec4::equal and pfVec4::almostEqual, since pfQuat is derived from pfVec4.
pfQuat & operator *(const pfQuat &m) pfQuat operator *=(const pfQuat &m) Performs multiplication with anther pfQuat.
pfQuat operator /(const pfQuat &v) pfQuat & operator /=(const pfQuat &v) Performs division with anther pfQuat.
Interpolation of quaternions (as presented by Ken Shoemake) is an effective technique for rotation interpolation. Spherical linear interpolation is performed with pfQuat::slerp, which produces a pfQuat that is t of the way between q1 and q2.
Spherical quadratic interpolation is provided by pfQuat::squad and its helper function, pfQuat::meanTangent.
These functions use a pfVec4 to represent quaternions and store the imaginary part first, thus the array contents q = {x,y,z,w} are a representation of the quaternion w + xi + yj+ zk.
Because both q and -q represent the same rotation (quaternions have a rotation range of [-360,360] degrees) conversions such as pfMatrix::getOrthoQuat make an arbitrary choice of the sign of the
returned quaternion. To prevent the arbitrary sign from introducing large, unintended rotations, pfQuat::slerp checks the angle theta between q1 and q2. If theta exceeds 180 degrees, q2 is negated changing the interpolations range from [0,theta] to [0, theta-360 degrees].
When using overloaded operators in C++, assignment operators, e.g. "+=", are somewhat more efficient than the corresponding binary operators, e.g. "+", because the latter construct a temporary intermediate object. Use assignment operators or macros for binary operations where optimal speed is important.
C++ does not support array deletion (i.e. delete[]) for arrays of objects allocated new operators that take additional arguments. Hence, the array deletion operator delete[] should not be used on arrays of objects created with new(arena) pfVec4[n].
For more information on quaternions, see the article by Sir William Rowan Hamilton "On quaternions; or on a new system of imaginaries in algebra," in the Philosophical Magazine, xxv, pp. 10-13 (July 1844). More recent references include "Animating Rotation with Quaternion Curves," SIGGRAPH Proceedings Vol 19, Number 3, 1985, and "Quaternion Calculus For Animation," in "Math for SIGGRAPH", Course Notes, #23, SIGGRAPH 1989, both by Ken Shoemake. An introductory tutorial is available on the Internet at ftp://ftp.cis.upenn.edu/pub/graphics/shoemake/quatut.ps.Z. Note that for consistency with Performer's transformation order, pfQuats are the conjugates of the quaternions described in these references.
pfVec4, pfMatrix