//----------------------------------------------------------------------------- // // $Logfile:: /Code/DLLs/game/vector.h $ // $Revision:: 24 $ // $Author:: Steven $ // $Date:: 10/13/03 8:54a $ // // Copyright (C) 1997 by Ritual Entertainment, Inc. // All rights reserved. // // This source is may not be distributed and/or modified without // expressly written permission by Ritual Entertainment, Inc. // // // DESCRIPTION: // C++ implemention of a Vector object. Handles standard vector operations // such as addition, subtraction, normalization, scaling, dot product, // cross product, length, and decomposition into Euler angles. // // WARNING: This file is shared between game, cgame and possibly the user interface. // It is instanced in each one of these directories because of the way that SourceSafe works. // #ifndef __VECTOR_H__ #define __VECTOR_H__ #ifdef GAME_DLL #include "g_local.h" #endif #include #include #ifdef __Q_FABS__ #define VECTOR_FABS Q_fabs #else #define VECTOR_FABS fabs #endif class Vector { public: float x; float y; float z; Vector(); Vector( const vec3_t src ); Vector( const float x, const float y, const float z ); explicit Vector( const char *text ); operator float * (); operator float const * () const; float pitch( void ) const; float yaw( void ) const; float roll( void ) const; float operator[]( const int index ) const; float & operator[]( const int index ); void copyTo( vec3_t vec ) const; void setPitch( const float x ); void setYaw( const float y ); void setRoll( const float z ); void setXYZ( const float x, const float y, const float z ); const Vector & operator=( const Vector &a ); const Vector & operator=( vec3_t a ); friend Vector operator+( const Vector &a, const Vector &b ); friend Vector operator+( vec3_t a, const Vector &b ); friend Vector operator+( const Vector &a, vec3_t b ); const Vector & operator+=( const Vector &a ); const Vector & operator+=( vec3_t a ); friend Vector operator-( const Vector &a, const Vector &b ); friend Vector operator-( vec3_t a, const Vector &b ); friend Vector operator-( const Vector &a, vec3_t b ); const Vector & operator-=( const Vector &a ); const Vector & operator-=( vec3_t a ); friend Vector operator*( const Vector &a, const float b ); friend Vector operator*( const float a, const Vector &b ); friend float operator*( const Vector &a, const Vector &b ); friend float operator*( vec3_t a, const Vector &b ); friend float operator*( const Vector &a, vec3_t b ); const Vector & operator*=( const float a ); friend Vector operator/( const Vector &a, const float b ); const Vector & operator/=( const float a ); friend int operator==( const Vector &a, const Vector &b ); friend int operator==( vec3_t a, const Vector &b ); friend int operator==( const Vector &a, vec3_t b ); friend int operator!=( const Vector &a, const Vector &b ); friend int operator!=( vec3_t a, const Vector &b ); friend int operator!=( const Vector &a, vec3_t b ); int FuzzyEqual( const Vector &b, const float epsilon ) const; int FuzzyEqual( vec3_t b, const float epsilon ) const; const Vector & CrossProduct( const Vector &a, const Vector &b ); const Vector & CrossProduct( vec3_t a, const Vector &b ); const Vector & CrossProduct( const Vector &a, vec3_t b ); float length( void ) const; float lengthSquared( void ) const; float lengthXY( void ) const; float normalize( void ); void EulerNormalize( void ); void EulerNormalize360( void ); static Vector Clamp( Vector &value, const Vector &min, const Vector &max ); static Vector Cross( const Vector &vector1, const Vector &vector2 ); static float Dot( const Vector &vector1, const Vector &vector2 ); static float Dot( vec3_t a, const Vector &b ); static float Dot( const Vector &a, vec3_t b ); static float Distance( const Vector &vector1, const Vector &vector2 ); static float DistanceSquared( const Vector &vector1, const Vector &vector2 ); static float DistanceXY( const Vector &vector1, const Vector &vector2 ); static Vector AnglesBetween( const Vector &vector1, const Vector &vector2 ); static float AngleBetween( const Vector &vector1, const Vector &vector2 ); static bool CloseEnough( const Vector &vector1, const Vector &vector2, const float epsilon = Vector::Epsilon()) ; static bool SmallEnough( const Vector &vector, const float epsilon = Vector::Epsilon() ); static float Epsilon( void ); static Vector & Identity( void ); Vector operator-( void ) const; friend Vector fabs( const Vector &a ); float toYaw( void ) const; float toPitch( void ) const; Vector toAngles( void ) const; void AngleVectors( Vector *forward, Vector *left = NULL, Vector *up = NULL ) const; friend Vector LerpVector( const Vector &w1, const Vector &w2, const float t ); friend float MaxValue( const Vector &a ); }; extern Vector vec_zero; inline float Vector::pitch( void ) const { return x; } inline float Vector::yaw( void ) const { return y; } inline float Vector::roll( void ) const { return z; } inline void Vector::setPitch( float pitch ) { x = pitch; } inline void Vector::setYaw( float yaw ) { y = yaw; } inline void Vector::setRoll( float roll ) { z = roll; } inline void Vector::copyTo( vec3_t vec ) const { vec[ 0 ] = x; vec[ 1 ] = y; vec[ 2 ] = z; } inline float Vector::operator[]( const int index ) const { assert( ( index >= 0 ) && ( index < 3 ) ); return ( &x )[ index ]; } inline float& Vector::operator[]( const int index ) { assert( ( index >= 0 ) && ( index < 3 ) ); return ( &x )[ index ]; } inline void Vector::setXYZ( const float new_x, const float new_y,const float new_z ) { x = new_x; y = new_y; z = new_z; } inline Vector::Vector(): x( 0 ), y( 0 ), z( 0 ) { } inline Vector::Vector( const vec3_t src ): x( src[0] ), y( src[1] ), z( src[2] ) { } inline Vector::Vector( const float init_x, const float init_y, const float init_z ): x( init_x ), y( init_y ), z( init_z ) { } inline Vector::Vector( const char *text ): x( 0 ), y( 0 ), z( 0 ) { if ( text ) { if ( text[0] == '"' ) sscanf( text, "\"%f %f %f\"", &x, &y, &z ); else sscanf( text, "%f %f %f", &x, &y, &z ); } } inline Vector::operator float * ( void ) { return &x; } inline Vector::operator float const * ( void ) const { return &x; } inline const Vector & Vector::operator=( const Vector &a ) { x = a.x; y = a.y; z = a.z; return *this; } inline const Vector & Vector::operator=( vec3_t a ) { x = a[ 0 ]; y = a[ 1 ]; z = a[ 2 ]; return *this; } inline Vector operator+( const Vector &a, const Vector &b ) { return Vector( a.x + b.x, a.y + b.y, a.z + b.z ); } inline Vector operator+( vec3_t a, const Vector &b ) { return Vector( a[ 0 ] + b.x, a[ 1 ] + b.y, a[ 2 ] + b.z ); } inline Vector operator+( const Vector &a, vec3_t b ) { return Vector( a.x + b[ 0 ], a.y + b[ 1 ], a.z + b[ 2 ] ); } inline const Vector & Vector::operator+=( const Vector &a ) { x += a.x; y += a.y; z += a.z; return *this; } inline const Vector & Vector::operator+=( vec3_t a ) { x += a[ 0 ]; y += a[ 1 ]; z += a[ 2 ]; return *this; } inline Vector operator-( const Vector &a, const Vector &b ) { return Vector( a.x - b.x, a.y - b.y, a.z - b.z ); } inline Vector operator-( vec3_t a, const Vector &b ) { return Vector( a[ 0 ] - b.x, a[ 1 ] - b.y, a[ 2 ] - b.z ); } inline Vector operator-( const Vector &a, vec3_t b ) { return Vector( a.x - b[ 0 ], a.y - b[ 1 ], a.z - b[ 2 ] ); } inline const Vector & Vector::operator-=( const Vector &a ) { x -= a.x; y -= a.y; z -= a.z; return *this; } inline const Vector & Vector::operator-=( vec3_t a ) { x -= a[ 0 ]; y -= a[ 1 ]; z -= a[ 2 ]; return *this; } inline Vector operator*( const Vector &a, const float b ) { return Vector( a.x * b, a.y * b, a.z * b ); } inline Vector operator*( const float a, const Vector &b ) { return b * a; } inline float operator*( const Vector &a, const Vector &b ) { return ( a.x * b.x ) + ( a.y * b.y ) + ( a.z * b.z ); } inline float operator*( vec3_t a, const Vector &b ) { return ( a[ 0 ] * b.x ) + ( a[ 1 ] * b.y ) + ( a[ 2 ] * b.z ); } inline float operator*( const Vector &a, vec3_t b ) { return ( a.x * b[ 0 ] ) + ( a.y * b[ 1 ] ) + ( a.z * b[ 2 ] ); } inline const Vector& Vector::operator*=( const float a ) { x *= a; y *= a; z *= a; return *this; } inline Vector operator/( const Vector &a, const float b ) { return Vector (a.x/b, a.y/b, a.z/b); } inline const Vector & Vector::operator/=( const float a ) { *this=*this/a; return *this; } inline int Vector::FuzzyEqual( const Vector &b, const float epsilon ) const { return ( ( VECTOR_FABS( x - b.x ) < epsilon ) && ( VECTOR_FABS( y - b.y ) < epsilon ) && ( VECTOR_FABS( z - b.z ) < epsilon ) ); } inline int Vector::FuzzyEqual( vec3_t b, const float epsilon ) const { return ( ( VECTOR_FABS( x - b[ 0 ] ) < epsilon ) && ( VECTOR_FABS( y - b[ 1 ] ) < epsilon ) && ( VECTOR_FABS( z - b[ 2 ] ) < epsilon ) ); } inline int operator==( const Vector &a, const Vector &b ) { return ( ( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ) ); } inline int operator==( vec3_t a, const Vector &b ) { return ( ( a[ 0 ] == b.x ) && ( a[ 1 ] == b.y ) && ( a[ 2 ] == b.z ) ); } inline int operator==( const Vector &a, vec3_t b ) { return ( ( a.x == b[ 0 ] ) && ( a.y == b[ 1 ] ) && ( a.z == b[ 2 ] ) ); } inline int operator!=( const Vector &a, const Vector &b ) { return ( ( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ) ); } inline int operator!=( vec3_t a, const Vector &b ) { return ( ( a[ 0 ] != b.x ) || ( a[ 1 ] != b.y ) || ( a[ 2 ] != b.z ) ); } inline int operator!=( const Vector &a, vec3_t b ) { return ( ( a.x != b[ 0 ] ) || ( a.y != b[ 1 ] ) || ( a.z != b[ 2 ] ) ); } inline const Vector & Vector::CrossProduct( const Vector &a, const Vector &b ) { x = ( a.y * b.z ) - ( a.z * b.y ); y = ( a.z * b.x ) - ( a.x * b.z ); z = ( a.x * b.y ) - ( a.y * b.x ); return *this; } inline const Vector & Vector::CrossProduct( vec3_t a, const Vector &b ) { x = ( a[ 1 ] * b.z ) - ( a[ 2 ] * b.y ); y = ( a[ 2 ] * b.x ) - ( a[ 0 ] * b.z ); z = ( a[ 0 ] * b.y ) - ( a[ 1 ] * b.x ); return *this; } inline const Vector & Vector::CrossProduct( const Vector &a, vec3_t b ) { x = ( a.y * b[ 2 ] ) - ( a.z * b[ 1 ] ); y = ( a.z * b[ 0 ] ) - ( a.x * b[ 2 ] ); z = ( a.x * b[ 1 ] ) - ( a.y * b[ 0 ] ); return *this; } inline Vector Vector::Clamp( Vector &value, const Vector &minimum, const Vector &maximum ) { Vector clamped(value); for (int i=0; i<3; i++) { const float min = minimum[i]; const float max = maximum[i]; assert( min <= max ); if (clamped[i] < min) { clamped[i] = min; } else if (clamped[i] > max) { clamped[i] = max; } } return clamped; } inline Vector Vector::Cross( const Vector &vector1, const Vector &vector2 ) { const Vector result ( ( vector1.y * vector2.z ) - ( vector1.z * vector2.y ), ( vector1.z * vector2.x ) - ( vector1.x * vector2.z ), ( vector1.x * vector2.y ) - ( vector1.y * vector2.x ) ); return result; } inline float Vector::Dot( const Vector &vector1, const Vector &vector2 ) { return vector1 * vector2; } inline float Vector::Dot( vec3_t vector1, const Vector &vector2 ) { return vector1 * vector2; } inline float Vector::Dot( const Vector &vector1, vec3_t vector2 ) { return vector1 * vector2; } //---------------------------------------------------------------- // Name: lengthSquared // Class: Vector // // Description: Returns squared length of the vector // // Parameters: None // // Returns: float - squared length //---------------------------------------------------------------- inline float Vector::lengthSquared( void ) const { return ( x * x ) + ( y * y ) + ( z * z ); } inline float Vector::length( void ) const { return sqrt( lengthSquared() ); } //---------------------------------------------------------------- // Name: lengthXY // Class: Vector // // Description: Returns length of the vector (using only the x // and y components // // Parameters: None // // Returns: float - length of the vector in the xy plane //---------------------------------------------------------------- inline float Vector::lengthXY( void ) const { return sqrt(( x * x ) + ( y * y )); } //---------------------------------------------------------------- // Name: normalize // Class: Vector // // Description: unitizes the vector // // Parameters: None // // Returns: float - length of the vector before the function //---------------------------------------------------------------- inline float Vector::normalize( void ) { float length, ilength; length = this->length(); if ( length ) { ilength = 1.0f / length; x *= ilength; y *= ilength; z *= ilength; } return length; } //---------------------------------------------------------------- // Name: EulerNormalize // Class: Vector // // Description: forces each component of the vector into the // range (-180, +180) by adding or subtracting 360 // This is useful when the Vector is being used as // EulerAngles to represent a rotational offset // // Parameters: None // // Returns: None //---------------------------------------------------------------- inline void Vector::EulerNormalize( void ) { x = AngleNormalize180( x ); y = AngleNormalize180( y ); z = AngleNormalize180( z ); } //---------------------------------------------------------------- // Name: EulerNormalize360 // Class: Vector // // Description: forces each component of the vector into the // range (0, +360) by adding or subtracting 360 // This is useful when the Vector is being used as // EulerAngles to represent a rotational direction // // Parameters: None // // Returns: None //---------------------------------------------------------------- inline void Vector::EulerNormalize360( void ) { x = AngleNormalize360( x ); y = AngleNormalize360( y ); z = AngleNormalize360( z ); } //---------------------------------------------------------------- // Name: Epsilon // Class: Vector // // Description: returns a standard 'small' value for the class // // Parameters: None // // Returns: float - the epsilon constant for the class //---------------------------------------------------------------- inline float Vector::Epsilon( void ) { return 0.000000001f; } //---------------------------------------------------------------- // Name: Identity // Class: Vector // // Description: returns the additive identity for the class // // Parameters: None // // Returns: Vector - the identity for the class //---------------------------------------------------------------- inline Vector & Vector::Identity(void) { return vec_zero; } //---------------------------------------------------------------- // Name: Distance // Class: Vector // // Description: returns the distance between two vectors // // Parameters: // Vector - first vector // Vector - second vector // // Returns: float - distance between the two vectors //---------------------------------------------------------------- inline float Vector::Distance(const Vector &vector1, const Vector &vector2) { return (vector1 - vector2).length(); } //---------------------------------------------------------------- // Name: DistanceSquared // Class: Vector // // Description: returns the squared distance between two vectors // // Parameters: // Vector - first vector // Vector - second vector // // Returns: float - distance between the two vectors squared //---------------------------------------------------------------- inline float Vector::DistanceSquared(const Vector &vector1, const Vector &vector2) { return (vector1 - vector2).lengthSquared(); } //---------------------------------------------------------------- // Name: DistanceXY // Class: Vector // // Description: returns the distance between two vectors in the // xy plane // // Parameters: // Vector - first vector // Vector - second vector // // Returns: float - distance between the two vectors in the // xy plane //---------------------------------------------------------------- inline float Vector::DistanceXY(const Vector &vector1, const Vector &vector2) { return (vector1 - vector2).lengthXY(); } inline Vector Vector::toAngles( void ) const { float forward; float yaw, pitch; if ( ( x == 0.0f ) && ( y == 0.0f ) ) { yaw = 0.0f; if ( z > 0.0f ) { pitch = 90.0f; } else { pitch = 270.0f; } } else { yaw = atan2( y, x ) * 180.0f / M_PI; if ( yaw < 0.0f ) { yaw += 360.0f; } forward = ( float )sqrt( x * x + y * y ); pitch = atan2( z, forward ) * 180.0f / M_PI; if ( pitch < 0.0f ) { pitch += 360.0f; } } return Vector( -pitch, yaw, 0.0f ); } //---------------------------------------------------------------- // Name: AnglesBetween // Class: Vector // // Description: returns the smaller of the angles formed by the // two vectors // // Parameters: // Vector - first vector // Vector - second vector // // Returns: Vector - angles between the vectors //---------------------------------------------------------------- inline Vector Vector::AnglesBetween(const Vector &vector1, const Vector &vector2) { Vector unitVector1(vector1); unitVector1.normalize(); Vector unitVector2(vector2); unitVector2.normalize(); Vector angles(unitVector1.toAngles() - unitVector2.toAngles()); angles.EulerNormalize(); return angles; } //---------------------------------------------------------------- // Name: AngleBetween // Class: Vector // // Description: returns the smaller of the angles formed by the // two vectors // // Parameters: // Vector - first vector // Vector - second vector // // Returns: float - angle between the vectors //---------------------------------------------------------------- inline float Vector::AngleBetween(const Vector &vector1, const Vector &vector2) { Vector unitVector1(vector1); unitVector1.normalize(); Vector unitVector2(vector2); unitVector2.normalize(); return acos( Vector::Dot( unitVector1, unitVector2 ) ); } //---------------------------------------------------------------- // Name: CloseEnough // Class: Vector // // Description: tests to see if the two vectors are within // 'epsilon' of each other // // Parameters: // Vector - first vector // Vector - second vector // float - amount that each component of the // vectors can be apart // // Returns: bool - the result of the test for closeness //---------------------------------------------------------------- inline bool Vector::CloseEnough(const Vector &vector1, const Vector &vector2, const float epsilon) { return Distance(vector1, vector2) < epsilon; } //---------------------------------------------------------------- // Name: SmallEnough // Class: Vector // // Description: tests to see if the vectors are within // 'epsilon' of the origin // // Parameters: // Vector - vector // float - amount that each component of the // vectors can be from the origin // // Returns: bool - the result of the test for smallness //---------------------------------------------------------------- inline bool Vector::SmallEnough(const Vector &vector, const float epsilon) { return CloseEnough(vector, Vector::Identity(), epsilon); } inline Vector Vector::operator-() const { return Vector( -x, -y, -z ); } inline Vector fabs( const Vector &a ) { return Vector( VECTOR_FABS( a.x ), VECTOR_FABS( a.y ), VECTOR_FABS( a.z ) ); } inline float MaxValue( const Vector &a ) { float maxy; float maxz; float max; max = VECTOR_FABS( a.x ); maxy = VECTOR_FABS( a.y ); maxz = VECTOR_FABS( a.z ); if ( maxy > max ) { max = maxy; } if ( maxz > max ) { max = maxz; } return max; } inline float Vector::toYaw( void ) const { float yaw; if ( ( y == 0.0f ) && ( x == 0.0f ) ) { yaw = 0.0f; } else { yaw = ( float )( ( int )( atan2( y, x ) * 180.0f / M_PI ) ); if ( yaw < 0.0f ) { yaw += 360.0f; } } return yaw; } inline float Vector::toPitch( void ) const { float forward; float pitch; if ( ( x == 0.0f ) && ( y == 0.0f ) ) { if ( z > 0.0f ) { pitch = 90.0f; } else { pitch = 270.0f; } } else { forward = ( float )sqrt( ( x * x ) + ( y * y ) ); pitch = ( float )( ( int )( atan2( z, forward ) * 180.0f / M_PI ) ); if ( pitch < 0.0f ) { pitch += 360.0f; } } return pitch; } inline void Vector::AngleVectors( Vector *forward, Vector *left, Vector *up ) const { float angle; static float sr, sp, sy, cr, cp, cy; // static to help MS compiler fp bugs angle = yaw() * ( M_PI * 2.0f / 360.0f ); sy = sin( angle ); cy = cos( angle ); angle = pitch() * ( M_PI * 2.0f / 360.0f ); sp = sin( angle ); cp = cos( angle ); angle = roll() * ( M_PI * 2.0f / 360.0f ); sr = sin( angle ); cr = cos( angle ); if ( forward ) { forward->setXYZ( cp * cy, cp * sy, -sp ); } if ( left ) { left->setXYZ( ( sr * sp * cy ) + ( cr * -sy ), (sr * sp * sy ) + ( cr * cy ), sr * cp ); } if ( up ) { up->setXYZ( ( cr * sp * cy ) + ( -sr * -sy ), ( cr * sp * sy ) + ( -sr * cy ), cr * cp ); } } #define LERP_DELTA 1e-6 inline Vector LerpVector( const Vector &vector1, const Vector &vector2, const float t ) { float omega, cosom, sinom, scale0, scale1; Vector w1( vector1 ); Vector w2( vector2 ); w1.normalize(); w2.normalize(); cosom = w1 * w2; if ( ( 1.0f - cosom ) > LERP_DELTA ) { omega = acos( cosom ); sinom = sin( omega ); scale0 = sin( ( 1.0f - t ) * omega ) / sinom; scale1 = sin( t * omega ) / sinom; } else { scale0 = 1.0f - t; scale1 = t; } return ( ( w1 * scale0 ) + ( w2 * scale1 ) ); } class Quat { public: float x; float y; float z; float w; Quat(); Quat( Vector angles ); Quat( float scrMatrix[ 3 ][ 3 ] ); Quat( const float x, const float y, const float z, const float w ); float * vec4( void ); float operator[]( const int index ) const; float & operator[]( const int index ); void set( const float x, const float y, const float z, const float w ); const Quat & operator=( const Quat &a ); friend Quat operator+( const Quat &a, const Quat &b ); const Quat & operator+=( const Quat &a ); friend Quat operator-( const Quat &a, const Quat &b ); const Quat & operator-=( const Quat &a ); friend Quat operator*( const Quat &a, const float b ); friend Quat operator*( const float a, const Quat &b ); const Quat & operator*=( const float a ); friend int operator==( const Quat &a, const Quat &b ); friend int operator!=( const Quat &a, const Quat &b ); float length( void ) const; float lengthSquared( void ) const; const Quat & normalize( void ); Quat operator-() const; Vector toAngles( void ); }; inline Quat::Quat(): x( 0 ), y( 0 ), z( 0 ), w( 0 ) { } inline Quat::Quat( Vector Angles ) { EulerToQuat( Angles, this->vec4() ); } inline Quat::Quat( float srcMatrix[ 3 ][ 3 ] ) { MatToQuat( srcMatrix, this->vec4() ); } inline Quat::Quat( const float init_x, const float init_y, const float init_z, const float init_w ): x( init_x ), y( init_y ), z( init_z ), w( init_w ) { } inline float Quat::operator[]( const int index ) const { assert( ( index >= 0 ) && ( index < 4 ) ); return ( &x )[ index ]; } inline float & Quat::operator[]( const int index) { assert( ( index >= 0 ) && ( index < 4 ) ); return ( &x )[ index ]; } inline float *Quat::vec4( void ) { return &x; } inline void Quat::set( const float new_x, const float new_y, const float new_z, const float new_w ) { x = new_x; y = new_y; z = new_z; w = new_w; } inline const Quat & Quat::operator=( const Quat &a ) { x = a.x; y = a.y; z = a.z; w = a.w; return *this; } inline Quat operator+( const Quat &a, const Quat &b ) { return Quat( a.x + b.x, a.y + b.y , a.z + b.z, a.w + b.w ); } inline const Quat & Quat::operator+=( const Quat &a ) { *this = *this + a; return *this; } inline Quat operator-( const Quat &a, const Quat &b ) { return Quat( a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w ); } inline const Quat & Quat::operator-=( const Quat &a ) { *this = *this - a; return *this; } inline Quat operator*( const Quat &a, const float b ) { return Quat( a.x * b, a.y * b, a.z * b, a.w * b ); } inline Quat operator*( const float a, const Quat &b ) { return b * a; } inline const Quat & Quat::operator*=( const float a ) { *this = *this * a; return *this; } inline int operator==( const Quat &a, const Quat &b ) { return ( ( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ) && ( a.w == b.w ) ); } inline int operator!=( const Quat &a, const Quat &b ) { return ( ( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ) && ( a.w != b.w ) ); } inline float Quat::length( void ) const { float length; length = ( x * x ) + ( y * y ) + ( z * z ) + ( w * w ); return sqrt( length ); } inline const Quat & Quat::normalize( void ) { float length, ilength; length = this->length(); if ( length ) { ilength = 1.0f / length; *this *= ilength; } return *this; } inline Quat Quat::operator-() const { return Quat( -x, -y, -z, -w ); } inline Vector Quat::toAngles( void ) { float m[ 3 ][ 3 ]; vec3_t angles; QuatToMat( this->vec4(), m ); MatrixToEulerAngles( m, angles ); return Vector( angles ); } #undef VECTOR_FABS #endif /* Vector.h */