912 lines
14 KiB
C++
912 lines
14 KiB
C++
//-----------------------------------------------------------------------------
|
|
//
|
|
// $Logfile:: /Quake 2 Engine/Sin/code/game/vector.h $
|
|
// $Revision:: 17 $
|
|
// $Author:: Markd $
|
|
// $Date:: 9/25/98 4:42p $
|
|
//
|
|
// 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.
|
|
//
|
|
// $Log:: /Quake 2 Engine/Sin/code/game/vector.h $
|
|
//
|
|
// 17 9/25/98 4:42p Markd
|
|
// Fixed a local reference return problem in Quat
|
|
//
|
|
// 16 9/05/98 6:57p Markd
|
|
// took out int type casts in toAngles
|
|
//
|
|
// 15 7/21/98 4:15p Jimdose
|
|
// Disabled the - (negate) operator since VC++ generates incorrect code for it
|
|
//
|
|
// 14 7/08/98 12:43p Markd
|
|
// Added quaternion support
|
|
//
|
|
// 13 7/02/98 7:57p Markd
|
|
// Added MaxValue function
|
|
//
|
|
// 12 7/01/98 8:15p Markd
|
|
// Added LerpVector
|
|
//
|
|
// 11 5/24/98 2:46p Markd
|
|
// Made char *'s into const char *'s
|
|
//
|
|
// 10 5/20/98 6:38p Jimdose
|
|
// Added toPitch
|
|
//
|
|
// 9 5/03/98 4:42p Jimdose
|
|
// Simplified class to get rid of bugs when passing into functions
|
|
// Replaced vec and vector with x, y, and z
|
|
// got rid of pointsTo and Init
|
|
// got rid of setX, setY, and setZ. Direct modifaction of x, y, z is permitted
|
|
// got rid of x(), y(), z(). Direct inspection of x,y,z is permitted.
|
|
//
|
|
// 8 2/06/98 5:50p Jimdose
|
|
// Replace getValue and setValue with [] override to allow random access to
|
|
// vector parameters.
|
|
// Fixed the -(negate) operator
|
|
//
|
|
// 7 2/03/98 11:01a Jimdose
|
|
// Added pitch, yaw, roll, value inspection and manipulation.
|
|
// Added Init which essential resets the vector to the startup state, for when
|
|
// the vector isn't initialized or is memset.
|
|
//
|
|
// 5 11/20/97 4:36p Jimdose
|
|
// Made multiply work for double * vector as well as vector * double.
|
|
//
|
|
// 4 10/27/97 4:22p Jimdose
|
|
// Added includes for math.h and stdio.h
|
|
//
|
|
// 3 10/27/97 2:59p Jimdose
|
|
// Removed dependency on quakedef.h
|
|
//
|
|
// 2 9/26/97 6:14p Jimdose
|
|
// Added standard Ritual headers
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
#ifndef __VECTOR_H__
|
|
#define __VECTOR_H__
|
|
|
|
#include "g_local.h"
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
|
|
class EXPORT_FROM_DLL Vector
|
|
{
|
|
public:
|
|
float x;
|
|
float y;
|
|
float z;
|
|
|
|
Vector();
|
|
Vector( vec3_t src );
|
|
Vector( double x, double y, double z );
|
|
Vector( const char *text );
|
|
|
|
float *vec3( void );
|
|
float pitch( void );
|
|
float yaw( void );
|
|
float roll( void );
|
|
float operator[]( int index ) const;
|
|
float& operator[]( int index );
|
|
void copyTo( vec3_t vec );
|
|
void setPitch( double x );
|
|
void setYaw( double y );
|
|
void setRoll( double z );
|
|
void setXYZ( double x, double y, double z );
|
|
void operator=( Vector a );
|
|
void operator=( vec3_t a );
|
|
friend Vector operator+( Vector a, Vector b );
|
|
Vector& operator+=( Vector a );
|
|
friend Vector operator-( Vector a, Vector b );
|
|
Vector& operator-=( Vector a );
|
|
friend Vector operator*( Vector a, double b );
|
|
friend Vector operator*( double a, Vector b );
|
|
friend float operator*( Vector a, Vector b );
|
|
Vector& operator*=( double a );
|
|
friend int operator==( Vector a, Vector b );
|
|
friend int operator!=( Vector a, Vector b );
|
|
Vector& CrossProduct( Vector a, Vector b );
|
|
float length( void );
|
|
Vector& normalize( void );
|
|
#if 0
|
|
//FIXME
|
|
// Some kind of compiler bug in VC++ prevents this from working.
|
|
// Returns result of ( -x, -y, -x ) for some reason
|
|
Vector& operator-();
|
|
#endif
|
|
friend Vector fabs( Vector a );
|
|
float toYaw( void );
|
|
float toPitch( void );
|
|
Vector toAngles( void );
|
|
void AngleVectors( Vector *forward, Vector *right, Vector *up );
|
|
friend Vector LerpVector( Vector w1, Vector w2, float t );
|
|
friend float MaxValue( Vector a );
|
|
};
|
|
|
|
inline float Vector::pitch( void ) { return x; }
|
|
inline float Vector::yaw( void ) { return y; }
|
|
inline float Vector::roll( void ) { return z; }
|
|
inline void Vector::setPitch( double pitch ) { x = ( float )pitch; }
|
|
inline void Vector::setYaw( double yaw ) { y = ( float )yaw; }
|
|
inline void Vector::setRoll( double roll ) { z = ( float )roll; }
|
|
|
|
inline void Vector::copyTo
|
|
(
|
|
vec3_t vec
|
|
)
|
|
|
|
{
|
|
vec[ 0 ] = x;
|
|
vec[ 1 ] = y;
|
|
vec[ 2 ] = z;
|
|
}
|
|
|
|
inline float Vector::operator[]
|
|
(
|
|
int index
|
|
) const
|
|
|
|
{
|
|
assert( ( index >= 0 ) && ( index < 3 ) );
|
|
return ( &x )[ index ];
|
|
}
|
|
|
|
inline float& Vector::operator[]
|
|
(
|
|
int index
|
|
)
|
|
|
|
{
|
|
assert( ( index >= 0 ) && ( index < 3 ) );
|
|
return ( &x )[ index ];
|
|
}
|
|
|
|
inline void Vector::setXYZ
|
|
(
|
|
double x,
|
|
double y,
|
|
double z
|
|
)
|
|
|
|
{
|
|
this->x = x;
|
|
this->y = y;
|
|
this->z = z;
|
|
}
|
|
|
|
inline Vector::Vector()
|
|
{
|
|
x = 0;
|
|
y = 0;
|
|
z = 0;
|
|
}
|
|
|
|
inline Vector::Vector
|
|
(
|
|
vec3_t src
|
|
)
|
|
|
|
{
|
|
x = src[ 0 ];
|
|
y = src[ 1 ];
|
|
z = src[ 2 ];
|
|
}
|
|
|
|
inline Vector::Vector
|
|
(
|
|
double x,
|
|
double y,
|
|
double z
|
|
)
|
|
|
|
{
|
|
this->x = x;
|
|
this->y = y;
|
|
this->z = z;
|
|
}
|
|
|
|
inline Vector::Vector
|
|
(
|
|
const char *text
|
|
)
|
|
|
|
{
|
|
if ( text )
|
|
{
|
|
sscanf( text, "%f %f %f", &x, &y, &z );
|
|
}
|
|
else
|
|
{
|
|
x = 0;
|
|
y = 0;
|
|
z = 0;
|
|
}
|
|
}
|
|
|
|
inline float *Vector::vec3
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
return &x;
|
|
}
|
|
|
|
inline void Vector::operator=
|
|
(
|
|
Vector a
|
|
)
|
|
|
|
{
|
|
x = a.x;
|
|
y = a.y;
|
|
z = a.z;
|
|
}
|
|
|
|
inline void Vector::operator=
|
|
(
|
|
vec3_t a
|
|
)
|
|
|
|
{
|
|
x = a[ 0 ];
|
|
y = a[ 1 ];
|
|
z = a[ 2 ];
|
|
}
|
|
|
|
inline Vector operator+
|
|
(
|
|
Vector a,
|
|
Vector b
|
|
)
|
|
|
|
{
|
|
return Vector( a.x + b.x, a.y + b.y, a.z + b.z );
|
|
}
|
|
|
|
inline Vector& Vector::operator+=
|
|
(
|
|
Vector a
|
|
)
|
|
|
|
{
|
|
x += a.x;
|
|
y += a.y;
|
|
z += a.z;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Vector operator-
|
|
(
|
|
Vector a,
|
|
Vector b
|
|
)
|
|
|
|
{
|
|
return Vector( a.x - b.x, a.y - b.y, a.z - b.z );
|
|
}
|
|
|
|
inline Vector& Vector::operator-=
|
|
(
|
|
Vector a
|
|
)
|
|
|
|
{
|
|
x -= a.x;
|
|
y -= a.y;
|
|
z -= a.z;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Vector operator*
|
|
(
|
|
Vector a,
|
|
double b
|
|
)
|
|
|
|
{
|
|
return Vector( a.x * b, a.y * b, a.z * b );
|
|
}
|
|
|
|
inline Vector operator*
|
|
(
|
|
double a,
|
|
Vector b
|
|
)
|
|
|
|
{
|
|
return b * a;
|
|
}
|
|
|
|
inline float operator*
|
|
(
|
|
Vector a,
|
|
Vector b
|
|
)
|
|
|
|
{
|
|
return a.x * b.x + a.y * b.y + a.z * b.z;
|
|
}
|
|
|
|
inline Vector& Vector::operator*=
|
|
(
|
|
double a
|
|
)
|
|
|
|
{
|
|
x *= a;
|
|
y *= a;
|
|
z *= a;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline int operator==
|
|
(
|
|
Vector a,
|
|
Vector b
|
|
)
|
|
|
|
{
|
|
return ( ( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ) );
|
|
}
|
|
|
|
inline int operator!=
|
|
(
|
|
Vector a,
|
|
Vector b
|
|
)
|
|
|
|
{
|
|
return ( ( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ) );
|
|
}
|
|
|
|
inline Vector& Vector::CrossProduct
|
|
(
|
|
Vector a,
|
|
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 float Vector::length
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
float length;
|
|
|
|
length = x * x + y * y + z * z;
|
|
return ( float )sqrt( length );
|
|
}
|
|
|
|
inline Vector& Vector::normalize
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
float length, ilength;
|
|
|
|
length = this->length();
|
|
if ( length )
|
|
{
|
|
ilength = 1 / length;
|
|
x *= ilength;
|
|
y *= ilength;
|
|
z *= ilength;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
#if 0
|
|
//FIXME
|
|
// Some kind of compiler bug in VC++ prevents this from working.
|
|
// Returns result of ( -x, -y, -x ) for some reason
|
|
inline Vector& Vector::operator-()
|
|
{
|
|
return Vector( -x, -y, -z );
|
|
}
|
|
#endif
|
|
|
|
inline Vector fabs
|
|
(
|
|
Vector a
|
|
)
|
|
|
|
{
|
|
return Vector( fabs( a.x ), fabs( a.y ), fabs( a.z ) );
|
|
}
|
|
|
|
inline float MaxValue
|
|
(
|
|
Vector a
|
|
)
|
|
|
|
{
|
|
float maxy;
|
|
float maxz;
|
|
float max;
|
|
|
|
max = fabs( a.x );
|
|
maxy = fabs( a.y );
|
|
maxz = fabs( a.z );
|
|
if ( maxy > max )
|
|
max = maxy;
|
|
if ( maxz > max )
|
|
max = maxz;
|
|
return max;
|
|
}
|
|
|
|
inline float Vector::toYaw
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
float yaw;
|
|
|
|
if ( ( y == 0 ) && ( x == 0 ) )
|
|
{
|
|
yaw = 0;
|
|
}
|
|
else
|
|
{
|
|
yaw = ( float )( ( int )( atan2( y, x ) * 180 / M_PI ) );
|
|
if ( yaw < 0 )
|
|
{
|
|
yaw += 360;
|
|
}
|
|
}
|
|
|
|
return yaw;
|
|
}
|
|
|
|
inline float Vector::toPitch
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
float forward;
|
|
float pitch;
|
|
|
|
if ( ( x == 0 ) && ( y == 0 ) )
|
|
{
|
|
if ( z > 0 )
|
|
{
|
|
pitch = 90;
|
|
}
|
|
else
|
|
{
|
|
pitch = 270;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
forward = ( float )sqrt( x * x + y * y );
|
|
pitch = ( float )( ( int )( atan2( z, forward ) * 180 / M_PI ) );
|
|
if ( pitch < 0 )
|
|
{
|
|
pitch += 360;
|
|
}
|
|
}
|
|
|
|
return pitch;
|
|
}
|
|
|
|
inline Vector Vector::toAngles
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
float forward;
|
|
float yaw, pitch;
|
|
|
|
if ( ( x == 0 ) && ( y == 0 ) )
|
|
{
|
|
yaw = 0;
|
|
if ( z > 0 )
|
|
{
|
|
pitch = 90;
|
|
}
|
|
else
|
|
{
|
|
pitch = 270;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
yaw = atan2( y, x ) * 180 / M_PI;
|
|
if ( yaw < 0 )
|
|
{
|
|
yaw += 360;
|
|
}
|
|
|
|
forward = ( float )sqrt( x * x + y * y );
|
|
pitch = atan2( z, forward ) * 180 / M_PI;
|
|
if ( pitch < 0 )
|
|
{
|
|
pitch += 360;
|
|
}
|
|
}
|
|
|
|
return Vector( pitch, yaw, 0 );
|
|
}
|
|
|
|
inline void Vector::AngleVectors
|
|
(
|
|
Vector *forward,
|
|
Vector *right,
|
|
Vector *up
|
|
)
|
|
|
|
{
|
|
float angle;
|
|
static float sr, sp, sy, cr, cp, cy; // static to help MS compiler fp bugs
|
|
|
|
angle = yaw() * ( M_PI * 2 / 360 );
|
|
sy = sin( angle );
|
|
cy = cos( angle );
|
|
|
|
angle = pitch() * ( M_PI * 2 / 360 );
|
|
sp = sin( angle );
|
|
cp = cos( angle );
|
|
|
|
angle = roll() * ( M_PI * 2 / 360 );
|
|
sr = sin( angle );
|
|
cr = cos( angle );
|
|
|
|
if ( forward )
|
|
{
|
|
forward->setXYZ( cp * cy, cp * sy, -sp );
|
|
}
|
|
|
|
if ( right )
|
|
{
|
|
right->setXYZ( -1 * sr * sp * cy + -1 * cr * -sy, -1 * sr * sp * sy + -1 * cr * cy, -1 * 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
|
|
(
|
|
Vector w1,
|
|
Vector w2,
|
|
float t
|
|
)
|
|
{
|
|
double omega, cosom, sinom, scale0, scale1;
|
|
|
|
w1.normalize();
|
|
w2.normalize();
|
|
|
|
cosom = w1 * w2;
|
|
if ( ( 1.0 - cosom ) > LERP_DELTA )
|
|
{
|
|
omega = acos( cosom );
|
|
sinom = sin( omega );
|
|
scale0 = sin( ( 1.0 - t ) * omega ) / sinom;
|
|
scale1 = sin( t * omega ) / sinom;
|
|
}
|
|
else
|
|
{
|
|
scale0 = 1.0 - t;
|
|
scale1 = t;
|
|
}
|
|
|
|
return ( w1 * scale0 + w2 * scale1 );
|
|
}
|
|
|
|
class EXPORT_FROM_DLL Quat
|
|
{
|
|
public:
|
|
float x;
|
|
float y;
|
|
float z;
|
|
float w;
|
|
|
|
Quat();
|
|
Quat( Vector angles );
|
|
Quat( float scrMatrix[ 3 ][ 3 ] );
|
|
Quat( double x, double y, double z, double w );
|
|
|
|
float *vec4( void );
|
|
float operator[]( int index ) const;
|
|
float& operator[]( int index );
|
|
void set( double x, double y, double z, double w );
|
|
void operator=( Quat a );
|
|
friend Quat operator+( Quat a, Quat b );
|
|
Quat& operator+=( Quat a );
|
|
friend Quat operator-( Quat a, Quat b );
|
|
Quat& operator-=( Quat a );
|
|
friend Quat operator*( Quat a, double b );
|
|
friend Quat operator*( double a, Quat b );
|
|
Quat& operator*=( double a );
|
|
friend int operator==( Quat a, Quat b );
|
|
friend int operator!=( Quat a, Quat b );
|
|
float length( void );
|
|
Quat& normalize( void );
|
|
Quat operator-();
|
|
Vector toAngles( void );
|
|
};
|
|
|
|
inline float Quat::operator[]
|
|
(
|
|
int index
|
|
) const
|
|
|
|
{
|
|
assert( ( index >= 0 ) && ( index < 4 ) );
|
|
return ( &x )[ index ];
|
|
}
|
|
|
|
inline float& Quat::operator[]
|
|
(
|
|
int index
|
|
)
|
|
|
|
{
|
|
assert( ( index >= 0 ) && ( index < 4 ) );
|
|
return ( &x )[ index ];
|
|
}
|
|
|
|
inline float *Quat::vec4
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
return &x;
|
|
}
|
|
|
|
inline void Quat::set
|
|
(
|
|
double x,
|
|
double y,
|
|
double z,
|
|
double w
|
|
)
|
|
|
|
{
|
|
this->x = x;
|
|
this->y = y;
|
|
this->z = z;
|
|
this->w = w;
|
|
}
|
|
|
|
inline Quat::Quat()
|
|
{
|
|
x = 0;
|
|
y = 0;
|
|
z = 0;
|
|
w = 0;
|
|
}
|
|
|
|
inline Quat::Quat
|
|
(
|
|
Vector Angles
|
|
)
|
|
|
|
{
|
|
EulerToQuat( Angles.vec3(), this->vec4() );
|
|
}
|
|
|
|
inline Quat::Quat
|
|
(
|
|
float srcMatrix[ 3 ][ 3 ]
|
|
)
|
|
|
|
{
|
|
MatToQuat( srcMatrix, this->vec4() );
|
|
}
|
|
|
|
inline Quat::Quat
|
|
(
|
|
double x,
|
|
double y,
|
|
double z,
|
|
double w
|
|
)
|
|
|
|
{
|
|
this->x = x;
|
|
this->y = y;
|
|
this->z = z;
|
|
this->w = w;
|
|
}
|
|
|
|
inline void Quat::operator=
|
|
(
|
|
Quat a
|
|
)
|
|
|
|
{
|
|
x = a.x;
|
|
y = a.y;
|
|
z = a.z;
|
|
w = a.w;
|
|
}
|
|
|
|
inline Quat operator+
|
|
(
|
|
Quat a,
|
|
Quat b
|
|
)
|
|
|
|
{
|
|
return Quat( a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w );
|
|
}
|
|
|
|
inline Quat& Quat::operator+=
|
|
(
|
|
Quat a
|
|
)
|
|
|
|
{
|
|
x += a.x;
|
|
y += a.y;
|
|
z += a.z;
|
|
w += a.w;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Quat operator-
|
|
(
|
|
Quat a,
|
|
Quat b
|
|
)
|
|
|
|
{
|
|
return Quat( a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w );
|
|
}
|
|
|
|
inline Quat& Quat::operator-=
|
|
(
|
|
Quat a
|
|
)
|
|
|
|
{
|
|
x -= a.x;
|
|
y -= a.y;
|
|
z -= a.z;
|
|
w -= a.w;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Quat operator*
|
|
(
|
|
Quat a,
|
|
double b
|
|
)
|
|
|
|
{
|
|
return Quat( a.x * b, a.y * b, a.z * b, a.w * b );
|
|
}
|
|
|
|
inline Quat operator*
|
|
(
|
|
double a,
|
|
Quat b
|
|
)
|
|
|
|
{
|
|
return b * a;
|
|
}
|
|
|
|
inline Quat& Quat::operator*=
|
|
(
|
|
double a
|
|
)
|
|
|
|
{
|
|
x *= a;
|
|
y *= a;
|
|
z *= a;
|
|
w *= a;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline int operator==
|
|
(
|
|
Quat a,
|
|
Quat b
|
|
)
|
|
|
|
{
|
|
return ( ( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ) && ( a.w == b.w ) );
|
|
}
|
|
|
|
inline int operator!=
|
|
(
|
|
Quat a,
|
|
Quat b
|
|
)
|
|
|
|
{
|
|
return ( ( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ) && ( a.w != b.w ) );
|
|
}
|
|
|
|
inline float Quat::length
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
float length;
|
|
|
|
length = x * x + y * y + z * z + w * w;
|
|
return ( float )sqrt( length );
|
|
}
|
|
|
|
inline Quat& Quat::normalize
|
|
(
|
|
void
|
|
)
|
|
|
|
{
|
|
float length, ilength;
|
|
|
|
length = this->length();
|
|
if ( length )
|
|
{
|
|
ilength = 1 / length;
|
|
x *= ilength;
|
|
y *= ilength;
|
|
z *= ilength;
|
|
w *= ilength;
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline Quat Quat::operator-()
|
|
{
|
|
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 );
|
|
}
|
|
|
|
|
|
#endif /* Vector.h */
|