Shadowrun: Awakened 29 September 2011 - Build 871
Public Types | Public Member Functions | Protected Attributes | Friends
cat::Quaternion< Scalar, Double > Class Template Reference

#include <Quaternion.hpp>

List of all members.

Public Types

typedef Quaternion< Scalar,
Double > 
mytype
typedef Vector< 3, Scalar, Double > vectype

Public Member Functions

mytypeconjugate () const
Scalar getAngle ()
vectype getAxis ()
void getMatrix4x4 (Matrix< 4, 4, Scalar > &result)
mytype operator* (const mytype &u)
mytypeoperator*= (const mytype &u)
mytypeoperator= (const mytype &u)
mytype operator~ () const
mytypepostMultiply (const mytype &u)
 Quaternion ()
 Quaternion (const mytype &u)
 Quaternion (Scalar x, Scalar y, Scalar z, Scalar w)
 Quaternion (const vectype &v, Scalar w)
vectype Quaternion::getEulerAngles ()
void rotate (vectype &u)
void setFromAxisAngle (const vectype &axis, f32 angle)
void setFromEulerAngles (f32 xroll, f32 ypitch, f32 zyaw)

Protected Attributes

Vector< 4, Scalar, Double > _v

Friends

void nlerp (const mytype &q1, const mytype &q2, Scalar t, mytype &result)
void slerp (const mytype &q1, const mytype &q2, Scalar t, mytype &result)

Detailed Description

template<typename Scalar, typename Double>
class cat::Quaternion< Scalar, Double >

Definition at line 47 of file Quaternion.hpp.


Member Typedef Documentation

template<typename Scalar , typename Double >
typedef Quaternion<Scalar, Double> cat::Quaternion< Scalar, Double >::mytype

Definition at line 55 of file Quaternion.hpp.

template<typename Scalar , typename Double >
typedef Vector<3, Scalar, Double> cat::Quaternion< Scalar, Double >::vectype

Definition at line 58 of file Quaternion.hpp.


Constructor & Destructor Documentation

template<typename Scalar , typename Double >
cat::Quaternion< Scalar, Double >::Quaternion ( ) [inline]

Definition at line 61 of file Quaternion.hpp.

{ }
template<typename Scalar , typename Double >
cat::Quaternion< Scalar, Double >::Quaternion ( const mytype u) [inline]

Definition at line 64 of file Quaternion.hpp.

        : _v(u._v)
    {
    }
template<typename Scalar , typename Double >
cat::Quaternion< Scalar, Double >::Quaternion ( const vectype v,
Scalar  w 
) [inline]

Definition at line 70 of file Quaternion.hpp.

        : _v(v)
    {
    }
template<typename Scalar , typename Double >
cat::Quaternion< Scalar, Double >::Quaternion ( Scalar  x,
Scalar  y,
Scalar  z,
Scalar  w 
) [inline]

Definition at line 76 of file Quaternion.hpp.

        : _v(x, y, z, w)
    {
    }

Member Function Documentation

template<typename Scalar , typename Double >
mytype& cat::Quaternion< Scalar, Double >::conjugate ( ) const [inline]

Definition at line 134 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v.

    {
        _v(0) = -_v(0);
        _v(1) = -_v(1);
        _v(2) = -_v(2);

        return *this;
    }
template<typename Scalar , typename Double >
Scalar cat::Quaternion< Scalar, Double >::getAngle ( ) [inline]

Definition at line 291 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v.

    {
        return static_cast<Scalar>( 2 ) * static_cast<Scalar>( acos(_v(3)) );
    }
template<typename Scalar , typename Double >
vectype cat::Quaternion< Scalar, Double >::getAxis ( ) [inline]

Definition at line 297 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v.

    {
        return vectype(_v(0), _v(1), _v(2)).normalize();
    }
template<typename Scalar , typename Double >
void cat::Quaternion< Scalar, Double >::getMatrix4x4 ( Matrix< 4, 4, Scalar > &  result) [inline]

Definition at line 303 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v.

    {
        Double dx = _v(0);
        Double dy = _v(1);
        Double dz = _v(2);
        Double dw = _v(3);

        Double x2 = dx * dx;
        Double y2 = dy * dy;
        Double z2 = dz * dz;
        Double xy = dx * dy;
        Double yz = dy * dz;
        Double zx = dz * dx;
        Double xw = dx * dw;
        Double yw = dy * dw;
        Double zw = dz * dw;

        const Double ONE = static_cast<Double>( 1 );
        const Double TWO = static_cast<Double>( 2 );

        // Result is written in OpenGL column-major matrix order:
        result( 0) = static_cast<Scalar>( ONE - TWO * (y2 + z2) );
        result( 1) = static_cast<Scalar>( TWO * (xy - zw) );
        result( 2) = static_cast<Scalar>( TWO * (zx + yw) );
        result( 3) = static_cast<Scalar>( 0 );

        result( 4) = static_cast<Scalar>( TWO * (xy + zw) );
        result( 5) = static_cast<Scalar>( ONE - TWO * (x2 + z2) );
        result( 6) = static_cast<Scalar>( TWO * (yz - xw) );
        result( 7) = static_cast<Scalar>( 0 );

        result( 8) = static_cast<Scalar>( TWO * (zx - yw) );
        result( 9) = static_cast<Scalar>( TWO * (yz + xw) );
        result(10) = static_cast<Scalar>( ONE - TWO * (x2 + y2) );
        result(11) = static_cast<Scalar>( 0 );

        result(12) = static_cast<Scalar>( 0 );
        result(13) = static_cast<Scalar>( 0 );
        result(14) = static_cast<Scalar>( 0 );
        result(15) = static_cast<Scalar>( ONE );
    }
template<typename Scalar , typename Double >
mytype cat::Quaternion< Scalar, Double >::operator* ( const mytype u) [inline]

Definition at line 144 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v.

    {
        // Cache each of the elements since each is used 4 times
        Double x1 = _v(0), x2 = u._v(0);
        Double y1 = _v(1), y2 = u._v(1);
        Double z1 = _v(2), z2 = u._v(2);
        Double w1 = _v(3), w2 = u._v(3);

        // Quaternion multiplication formula:
        Scalar x3 = static_cast<Scalar>( w1*x2 + x1*w2 + y1*z2 - z1*y2 );
        Scalar y3 = static_cast<Scalar>( w1*y2 - x1*z2 + y1*w2 + z1*x2 );
        Scalar z3 = static_cast<Scalar>( w1*z2 + x1*y2 - y1*x2 + z1*w2 );
        Scalar w3 = static_cast<Scalar>( w1*w2 - x1*x2 - y1*y2 - z1*z2 );

        return mytype(x3, y3, z3, w3);
    }
template<typename Scalar , typename Double >
mytype& cat::Quaternion< Scalar, Double >::operator*= ( const mytype u) [inline]

Definition at line 162 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v.

    {
        // Cache each of the elements since each is used 4 times
        Double x1 = _v(0), x2 = u._v(0);
        Double y1 = _v(1), y2 = u._v(1);
        Double z1 = _v(2), z2 = u._v(2);
        Double w1 = _v(3), w2 = u._v(3);

        // Quaternion multiplication formula:
        _v(0) = static_cast<Scalar>( w1*x2 + x1*w2 + y1*z2 - z1*y2 );
        _v(1) = static_cast<Scalar>( w1*y2 - x1*z2 + y1*w2 + z1*x2 );
        _v(2) = static_cast<Scalar>( w1*z2 + x1*y2 - y1*x2 + z1*w2 );
        _v(3) = static_cast<Scalar>( w1*w2 - x1*x2 - y1*y2 - z1*z2 );

        return *this;
    }
template<typename Scalar , typename Double >
mytype& cat::Quaternion< Scalar, Double >::operator= ( const mytype u) [inline]

Definition at line 82 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v, and cat::Vector< DIM, Scalar, Double >::copy().

    {
        _v.copy(u._v);

        return *this;
    }
template<typename Scalar , typename Double >
mytype cat::Quaternion< Scalar, Double >::operator~ ( ) const [inline]

Definition at line 128 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v.

    {
        return mytype(-_v(0), -_v(1), -_v(2), _v(3));
    }
template<typename Scalar , typename Double >
mytype& cat::Quaternion< Scalar, Double >::postMultiply ( const mytype u) [inline]

Definition at line 180 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v.

    {
        // Cache each of the elements since each is used 4 times
        Double x2 = _v(0), x1 = u._v(0);
        Double y2 = _v(1), y1 = u._v(1);
        Double z2 = _v(2), z1 = u._v(2);
        Double w2 = _v(3), w1 = u._v(3);

        // Quaternion multiplication formula:
        _v(0) = static_cast<Scalar>( w1*x2 + x1*w2 + y1*z2 - z1*y2 );
        _v(1) = static_cast<Scalar>( w1*y2 - x1*z2 + y1*w2 + z1*x2 );
        _v(2) = static_cast<Scalar>( w1*z2 + x1*y2 - y1*x2 + z1*w2 );
        _v(3) = static_cast<Scalar>( w1*w2 - x1*x2 - y1*y2 - z1*z2 );

        return *this;
    }
template<typename Scalar , typename Double >
vectype cat::Quaternion< Scalar, Double >::Quaternion::getEulerAngles ( ) [inline]

Definition at line 346 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v, CAT_HALF_PI_64, and cat::Quaternion< Scalar, Double >::Quaternion::getEulerAngles().

Referenced by cat::Quaternion< Scalar, Double >::Quaternion::getEulerAngles().

    {
        Double dx = _v(0);
        Double dy = _v(1);
        Double dz = _v(2);
        Double dw = _v(3);

        Double x2 = dx * dx;
        Double y2 = dy * dy;
        Double z2 = dz * dz;
        Double w2 = dw * dw;
        Double xy = dx * dy;
        Double yz = dy * dz;
        Double xw = dx * dw;
        Double yw = dy * dw;
        Double zw = dz * dw;

        const Double TWO = static_cast<Double>( 2 );

        Double r11 = w2 + x2 - y2 - z2;
        Double r21 = TWO * (xy + zw);
        Double r31 = TWO * (xy - yw);
        Double r32 = TWO * (yz + xw);
        Double r33 = w2 - x2 - y2 + z2;

        Double tmp = fabs(r31);
        const Double LIMIT = static_cast<Double>( 0.999999 );

        if (tmp > LIMIT)
        {
            Double xz = dx * dz;

            Double r12 = TWO * (yz - zw);
            Double r13 = TWO * (xz + yw);

            return vectype(static_cast<Scalar>( 0 ),
                           static_cast<Scalar>( -CAT_HALF_PI_64 * r31 / tmp ),
                           static_cast<Scalar>( atan2(-r12, -r31 * r13) ));
        }

        return vectype(static_cast<Scalar>( atan2(r32, r33) ),
                       static_cast<Scalar>( asin(-r31) ),
                       static_cast<Scalar>( atan2(r21, r11) ));
    }
template<typename Scalar , typename Double >
void cat::Quaternion< Scalar, Double >::rotate ( vectype u) [inline]

Definition at line 198 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v.

    {
        // Implements the simple formula: (q1 * u2 * ~q1).getVector()

        // Cache each of the elements since each is used 4 times
        Double x1 = _v(0), x2 = u(0);
        Double y1 = _v(1), y2 = u(1);
        Double z1 = _v(2), z2 = u(2);
        Double w1 = _v(3);

        // Quaternion-vector multiplication formula (q3 = q1 * u2):
        Double x3 = w1*x2 + y1*z2 - z1*y2;
        Double y3 = w1*y2 - x1*z2 + z1*x2;
        Double z3 = w1*z2 + x1*y2 - y1*x2;
        Double w3 = -(x1*x2 + y1*y2 + z1*z2);

        // Quaternion multiplication formula (q2' = q3 * ~q1):
        u(0) = static_cast<Scalar>( w1*x3 - x1*w3 + y1*z3 - z1*y3 );
        u(1) = static_cast<Scalar>( w1*y3 - x1*z3 - y1*w3 + z1*x3 );
        u(2) = static_cast<Scalar>( w1*z3 + x1*y3 - y1*x3 - z1*w3 );
    }
template<typename Scalar , typename Double >
void cat::Quaternion< Scalar, Double >::setFromAxisAngle ( const vectype axis,
f32  angle 
) [inline]

Definition at line 115 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v.

    {
        angle *= 0.5f;

        Scalar theta = static_cast<Scalar>( sin(angle) );

        _v(0) = theta * axis(0);
        _v(1) = theta * axis(1);
        _v(2) = theta * axis(2);
        _v(3) = static_cast<Scalar>( cos(angle) );
    }
template<typename Scalar , typename Double >
void cat::Quaternion< Scalar, Double >::setFromEulerAngles ( f32  xroll,
f32  ypitch,
f32  zyaw 
) [inline]

Definition at line 91 of file Quaternion.hpp.

References cat::Quaternion< Scalar, Double >::_v, and cat::Vector< DIM, Scalar, Double >::normalize().

    {
        f64 croll = cos(0.5f * xroll);
        f64 cpitch = cos(0.5f * ypitch);
        f64 cyaw = cos(0.5f * zyaw);
        f64 sroll = sin(0.5f * xroll);
        f64 spitch = sin(0.5f * ypitch);
        f64 syaw = sin(0.5f * zyaw);

        f64 cyawcpitch = cyaw * cpitch;
        f64 syawspitch = syaw * spitch;
        f64 cyawspitch = cyaw * spitch;
        f64 syawcpitch = syaw * cpitch;

        _v(0) = static_cast<Scalar>( cyawcpitch * sroll - syawspitch * croll );
        _v(1) = static_cast<Scalar>( cyawspitch * croll + syawcpitch * sroll );
        _v(2) = static_cast<Scalar>( syawcpitch * croll - cyawspitch * sroll );
        _v(3) = static_cast<Scalar>( cyawcpitch * croll + syawspitch * sroll );

        _v.normalize();
    }

Friends And Related Function Documentation

template<typename Scalar , typename Double >
void nlerp ( const mytype q1,
const mytype q2,
Scalar  t,
mytype result 
) [friend]

Definition at line 222 of file Quaternion.hpp.

    {
        // Linearly interpolate and normalize result
        // This formula is a little more work than "q1 + (q2 - q1) * t"
        // but less likely to lose precision when it matters

        // Cosine of phi, the angle between the two vectors
        Double cos_phi = q1._v.dotProduct(q2._v);

        // I have read this may try to rotate around the "long way" sometimes and to
        // fix that we check if cos(phi) is negative and invert one of the inputs.
        if (cos_phi < 0.0)
        {
            result._v = -q1._v;
        }
        else
        {
            result._v = q1._v;
        }

        // Simple linear interpolation
        Scalar scale0 = static_cast<Scalar>(1) - t;
        Scalar scale1 = t;

        result._v *= scale0;
        result._v += q2._v * scale1;
        result._v.normalize();
    }
template<typename Scalar , typename Double >
void slerp ( const mytype q1,
const mytype q2,
Scalar  t,
mytype result 
) [friend]

Definition at line 253 of file Quaternion.hpp.

    {
        // Cosine of phi, the angle between the two vectors
        Double cos_phi = q1._v.dotProduct(q2._v);

        // I have read this may try to rotate around the "long way" sometimes and to
        // fix that we check if cos(phi) is negative and invert one of the inputs.
        if (cos_phi < 0.0)
        {
            cos_phi = -cos_phi;
            result._v = -q1._v;
        }
        else
        {
            result._v = q1._v;
        }

        // Default to simple linear interpolation
        Scalar scale0 = static_cast<Scalar>(1) - t;
        Scalar scale1 = t;

        // If the distance is not small we need to do full slerp:
        if (cos_phi < 0.9995)
        {
            // cos_phi is guaranteed to be within the domain of acos(), 0..1
            Double phi = static_cast<Double>( acos(cos_phi) );
            Double inv_sin_phi = static_cast<Double>(1) / sin(phi);

            scale0 = static_cast<Scalar>( sin(scale0 * phi) * inv_sin_phi );
            scale1 = static_cast<Scalar>( sin(scale1 * phi) * inv_sin_phi );
        }

        result._v *= scale0;
        result._v += q2._v * scale1;
        result._v.normalize();
    }

Member Data Documentation

template<typename Scalar , typename Double >
Vector<4, Scalar, Double> cat::Quaternion< Scalar, Double >::_v [protected]

The documentation for this class was generated from the following file:

Copyright © 2007-2010 by The Shadowrun: Awakened Team. This work is licensed under the GNU Lesser General Public License 3.

GNU Lesser General Public License 3 Sourceforge.net