Jamma Tino Schwarze
cQuaternion.hh

  • Willkommen
  • Wer ich bin
  • Was ich tue
  • Was ich tat (Archiv)
    • Abitur
    • Studium
      • Arbeiten
      • Computergrafik
    • Aktivitäten
    • Software
    • Wohnen
    • Sonstiges
  • Links
  • Kontakt / Impressum
/* (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... const GLfloat c2XY = 2*v.GetX ()*v.GetY (); const GLfloat c2XZ = 2*v.GetX ()*v.GetZ (); const GLfloat c2YZ = 2*v.GetY ()*v.GetZ (); const GLfloat c2sX = 2*s*v.GetX (); const GLfloat c2sY = 2*s*v.GetY (); const GLfloat c2sZ = 2*s*v.GetZ (); tmp.mMatrix[0][0] = sqr (s) + sqr (v.GetX ()) - sqr (v.GetY()) - sqr (v.GetZ ()); tmp.mMatrix[0][1] = c2XY + c2sZ; tmp.mMatrix[0][2] = c2XZ - c2sY; tmp.mMatrix[0][3] = 0; tmp.mMatrix[1][0] = c2XY - c2sZ; tmp.mMatrix[1][1] = sqr(s) - sqr (v.GetX ()) + sqr (v.GetY ()) - sqr (v.GetZ ()); tmp.mMatrix[1][2] = c2YZ + c2sX; tmp.mMatrix[1][3] = 0; tmp.mMatrix[2][0] = c2XZ + c2sY; tmp.mMatrix[2][1] = c2YZ - c2sX; tmp.mMatrix[2][2] = sqr (s) - sqr (v.GetX ()) - sqr (v.GetY ()) + sqr (v.GetZ ()); tmp.mMatrix[2][3] = 0; tmp.mMatrix[3][0] = 0; tmp.mMatrix[3][1] = 0; tmp.mMatrix[3][2] = 0; tmp.mMatrix[3][3] = sqr (s) + sqr (v.GetX ()) + sqr (v.GetY ()) + sqr (v.GetZ ()); #if DEBUG cerr << "rotation matrix is " << tmp << endl; #endif } private: /* I chose the representation (s, v) = (scalar, complex[3]) * of the quaternion. */ GLfloat s; cVertex v; }; #endif // ifndef cQuaternion_hh /* vim:ts=4:smartindent: */
Copyright © 2025 Jamma Tino Schwarze