/* (c) 1999-2000 Tino Schwarze, see COPYING for details */
/**@pkg math*/
/**
* class cQuaternion
*/
#ifndef cQuaternion_hh
#define cQuaternion_hh
#include "common.hh"
#include "cVertex.hh" // aquire class cVertex
#include "cMatrix.hh" // aquire class cMatrix
#if DEBUG
#include "iocMatrix.hh"
#endif
/**
* A class for representing a quaternion and its operations.
*
* Contains a class representing a quaternion and allowing
* operations like multiplying quaternions, transforming vertices
* and generating a matrix from a quaternion.
* @see cMatrix
* @see cVertex
*/
class cQuaternion {
public:
/**
* default constructor
*/
cQuaternion ()
{
// initialize quaternion to identity
SetIdentity ();
};
// use copy constructor provided by compiler
// use destructor provided by compiler
/**
* constructor w/ hard initialization of quaternion
* @param cw scalar value of quaternion
* @param cx x component of complex value
* @param cy y component of complex value
* @param cz z component of complex value
*
* @note used by GetInverse()
*/
cQuaternion (const GLfloat cw,
const GLfloat cx, const GLfloat cy, const GLfloat cz)
: s(cw), v(cx, cy, cz) {};
/**
* constructor w/ initialization
* @param angle angle in degree
* @param axis vector to rotate around
*/
cQuaternion (const GLfloat angle, const cVertex &axis)
{
SetRotation (angle, axis);
}
// OPERATORS
/**
* operator * for two quaternions (multiply two quaternions)
* @param q quaternion to multiply with
*
* @return resulting cQuaternion object
*/
cQuaternion operator * (const cQuaternion &q) const
{
// q1*q2 = (s1*s2 - v1*v2 , s1*v2 + s2*v1 + v1 x v2)
return cQuaternion (s*q.s - v*q.v,
q.v*s + v*q.s + v.CrossProd(q.v));
}
/**
* operator *= for quaternions (multiply two quaternions)
* @param q quaternion to multiply with
*
* @return reference to cQuaternion
*/
cQuaternion &operator *= (const cQuaternion &q)
{
GLfloat sn;
sn = s*q.s - v*q.v;
v = q.v*s + v*q.s + v.CrossProd(q.v);
s = sn;
return (*this);
}
/**
* operator * for vertices (applies quaternion to vertex)
* @param v cVertex to transform
*
* @return the transformed vertex as cVertex object
*/
cVertex operator * (const cVertex &v)
{
/*
// create quaternion representation of vertex
cQuaternion tmp (0, v);
// v_rotated = q * v * q^-1
// = q * v * q'
return ((*this) * tmp * GetInverse ()).v;
*/
// looks a lot easier than above and requires less
// temporary cVertex objects but therefore a Matrix
return GetAsMatrix()*v;
}
// OPERATIONS
/**
* set quaternion to identity (no transformation/rotation)
*/
void SetIdentity ()
{
s = 1.0;
v.SetZero ();
}
/**
* set quaternion to represent given rotation
* (angle in degree)
* @param angle in degree
* @param axis to turn around
*/
void SetRotation (const GLfloat angle, const cVertex &axis)
{
const GLfloat rad = M_PI*angle/180.0;
s = cos(rad/2.0);
// we need to make axis a unit vector to make some
// things easier
v = axis * (sin(rad/2.0)/axis.GetLength ());
}
/**
* normalize the quaternion (make it length 1)
*/
void Normalize ()
{
const GLfloat abs_value = GetLength ();
s /= abs_value;
v *= 1.0/abs_value;
}
// ACCESS
/**
* return s component of quaternion
* @return GLfloat value of s
*/
GLfloat GetS () const
{
return s;
}
/**
* return v component of quaternion
* @return cVertex object with value of v
*/
cVertex GetV () const
{
return v;
}
/**
* return "length" of quaternion
* @returns GLfloat
*/
GLfloat GetLength () const
{
return sqrt (s*s + v*v);
}
/**
* return the inverse of the quaternion
* @returns inverse quaternion
*/
cQuaternion GetInverse () {
// caution: this _only_ works with unit quaternions!
return cQuaternion (s, -v.GetX(), -v.GetY(), -v.GetZ());
}
/**
* return the matrix representation of the quaternion
* @returns cMatrix object representing quaternion
*/
cMatrix GetAsMatrix () {
cMatrix tmp;
GetAsMatrix (tmp);
return tmp;
}
/**
* shortcut for retrieving the quaternion in matrix representation
* prevents allocating temporary on stack
* @param tmp reference to cMatrix object
*/
void GetAsMatrix (cMatrix &tmp)
{
// help optimizing a bit...
|