You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1485 lines
33 KiB
C++
1485 lines
33 KiB
C++
#include <stdlib.h>
|
|
|
|
#define Assert( _exp ) ((void)0)
|
|
|
|
#define FastSqrt(x) (sqrt)(x)
|
|
|
|
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
|
|
|
|
#define M_PI_F ((float)(M_PI)) // Shouldn't collide with anything.
|
|
|
|
#define M_PHI 1.61803398874989484820 // golden ratio
|
|
|
|
// NJS: Inlined to prevent floats from being autopromoted to doubles, as with the old system.
|
|
#ifndef RAD2DEG
|
|
#define RAD2DEG( x ) ( (float)(x) * (float)(180.f / M_PI_F) )
|
|
#endif
|
|
|
|
#ifndef DEG2RAD
|
|
#define DEG2RAD( x ) ( (float)(x) * (float)(M_PI_F / 180.f) )
|
|
#endif
|
|
|
|
// MOVEMENT INFO
|
|
enum
|
|
{
|
|
PITCH = 0, // up / down
|
|
YAW, // left / right
|
|
ROLL // fall over
|
|
};
|
|
|
|
// decls for aligning data
|
|
|
|
#define DECL_ALIGN(x) __attribute__((aligned(x)))
|
|
|
|
|
|
#define ALIGN16 DECL_ALIGN(16)
|
|
#define VALVE_RAND_MAX 0x7fff
|
|
#define VectorExpand(v) (v).x, (v).y, (v).z
|
|
|
|
struct matrix3x4_t
|
|
{
|
|
matrix3x4_t() {}
|
|
matrix3x4_t(
|
|
float m00, float m01, float m02, float m03,
|
|
float m10, float m11, float m12, float m13,
|
|
float m20, float m21, float m22, float m23)
|
|
{
|
|
m_flMatVal[0][0] = m00; m_flMatVal[0][1] = m01; m_flMatVal[0][2] = m02; m_flMatVal[0][3] = m03;
|
|
m_flMatVal[1][0] = m10; m_flMatVal[1][1] = m11; m_flMatVal[1][2] = m12; m_flMatVal[1][3] = m13;
|
|
m_flMatVal[2][0] = m20; m_flMatVal[2][1] = m21; m_flMatVal[2][2] = m22; m_flMatVal[2][3] = m23;
|
|
}
|
|
|
|
float* operator[](int i) { Assert((i >= 0) && (i < 3)); return m_flMatVal[i]; }
|
|
const float* operator[](int i) const { Assert((i >= 0) && (i < 3)); return m_flMatVal[i]; }
|
|
float* Base() { return &m_flMatVal[0][0]; }
|
|
const float* Base() const { return &m_flMatVal[0][0]; }
|
|
|
|
float m_flMatVal[3][4];
|
|
};
|
|
|
|
class VMatrix
|
|
{
|
|
public:
|
|
|
|
VMatrix() {}
|
|
VMatrix(
|
|
float m00, float m01, float m02, float m03,
|
|
float m10, float m11, float m12, float m13,
|
|
float m20, float m21, float m22, float m23,
|
|
float m30, float m31, float m32, float m33
|
|
) {
|
|
m[0][0] = m00;
|
|
m[0][1] = m01;
|
|
m[0][2] = m02;
|
|
m[0][3] = m03;
|
|
|
|
m[1][0] = m10;
|
|
m[1][1] = m11;
|
|
m[1][2] = m12;
|
|
m[1][3] = m13;
|
|
|
|
m[2][0] = m20;
|
|
m[2][1] = m21;
|
|
m[2][2] = m22;
|
|
m[2][3] = m23;
|
|
|
|
m[3][0] = m30;
|
|
m[3][1] = m31;
|
|
m[3][2] = m32;
|
|
m[3][3] = m33;
|
|
}
|
|
|
|
|
|
|
|
// array access
|
|
inline float* operator[](int i)
|
|
{
|
|
return m[i];
|
|
}
|
|
|
|
inline const float* operator[](int i) const
|
|
{
|
|
return m[i];
|
|
}
|
|
|
|
// Get a pointer to m[0][0]
|
|
inline float* Base()
|
|
{
|
|
return &m[0][0];
|
|
}
|
|
|
|
inline const float* Base() const
|
|
{
|
|
return &m[0][0];
|
|
}
|
|
|
|
|
|
public:
|
|
// The matrix.
|
|
float m[4][4];
|
|
};
|
|
|
|
class Vector
|
|
{
|
|
public:
|
|
float x, y, z;
|
|
Vector(void);
|
|
Vector(float X, float Y, float Z);
|
|
void Init(float ix = 0.0f, float iy = 0.0f, float iz = 0.0f);
|
|
bool IsValid() const;
|
|
float operator[](int i) const;
|
|
float& operator[](int i);
|
|
inline void Zero();
|
|
bool operator==(const Vector& v) const;
|
|
bool operator!=(const Vector& v) const;
|
|
inline Vector& operator+=(const Vector& v);
|
|
inline Vector& operator-=(const Vector& v);
|
|
inline Vector& operator*=(const Vector& v);
|
|
inline Vector& operator*=(float s);
|
|
inline Vector& operator/=(const Vector& v);
|
|
inline Vector& operator/=(float s);
|
|
inline Vector& operator+=(float fl);
|
|
inline Vector& operator-=(float fl);
|
|
inline float Length() const;
|
|
inline float LengthSqr(void) const
|
|
{
|
|
return (x * x + y * y + z * z);
|
|
}
|
|
bool IsZero(float tolerance = 0.01f) const
|
|
{
|
|
return (x > -tolerance && x < tolerance &&
|
|
y > -tolerance && y < tolerance &&
|
|
z > -tolerance && z < tolerance);
|
|
}
|
|
Vector Normalize();
|
|
void NormalizeInPlace();
|
|
inline float DistTo(const Vector& vOther) const;
|
|
inline float DistToSqr(const Vector& vOther) const;
|
|
float Dot(const Vector& vOther) const;
|
|
float Length2D(void) const;
|
|
float Length2DSqr(void) const;
|
|
Vector& operator=(const Vector& vOther);
|
|
Vector operator-(void) const;
|
|
Vector operator+(const Vector& v) const;
|
|
Vector operator-(const Vector& v) const;
|
|
Vector operator*(const Vector& v) const;
|
|
Vector operator/(const Vector& v) const;
|
|
Vector operator*(float fl) const;
|
|
Vector operator/(float fl) const;
|
|
// Base address...
|
|
float* Base();
|
|
float const* Base() const;
|
|
};
|
|
|
|
//===============================================
|
|
inline void Vector::Init(float ix, float iy, float iz)
|
|
{
|
|
x = ix; y = iy; z = iz;
|
|
}
|
|
//===============================================
|
|
inline Vector::Vector(float X, float Y, float Z)
|
|
{
|
|
x = X; y = Y; z = Z;
|
|
}
|
|
//===============================================
|
|
inline Vector::Vector(void) { Zero(); }
|
|
//===============================================
|
|
inline void Vector::Zero()
|
|
{
|
|
x = y = z = 0.0f;
|
|
}
|
|
//===============================================
|
|
inline void VectorClear(Vector& a)
|
|
{
|
|
a.x = a.y = a.z = 0.0f;
|
|
}
|
|
//===============================================
|
|
inline Vector& Vector::operator=(const Vector& vOther)
|
|
{
|
|
x = vOther.x; y = vOther.y; z = vOther.z;
|
|
return *this;
|
|
}
|
|
//===============================================
|
|
inline float& Vector::operator[](int i)
|
|
{
|
|
Assert((i >= 0) && (i < 3));
|
|
return ((float*)this)[i];
|
|
}
|
|
//===============================================
|
|
inline float Vector::operator[](int i) const
|
|
{
|
|
Assert((i >= 0) && (i < 3));
|
|
return ((float*)this)[i];
|
|
}
|
|
//===============================================
|
|
inline bool Vector::operator==(const Vector& src) const
|
|
{
|
|
return (src.x == x) && (src.y == y) && (src.z == z);
|
|
}
|
|
//===============================================
|
|
inline bool Vector::operator!=(const Vector& src) const
|
|
{
|
|
return (src.x != x) || (src.y != y) || (src.z != z);
|
|
}
|
|
//===============================================
|
|
inline void VectorCopy(const Vector& src, Vector& dst)
|
|
{
|
|
dst.x = src.x;
|
|
dst.y = src.y;
|
|
dst.z = src.z;
|
|
}
|
|
//===============================================
|
|
inline Vector& Vector::operator+=(const Vector& v)
|
|
{
|
|
x += v.x; y += v.y; z += v.z;
|
|
return *this;
|
|
}
|
|
//===============================================
|
|
inline Vector& Vector::operator-=(const Vector& v)
|
|
{
|
|
x -= v.x; y -= v.y; z -= v.z;
|
|
return *this;
|
|
}
|
|
//===============================================
|
|
inline Vector& Vector::operator*=(float fl)
|
|
{
|
|
x *= fl;
|
|
y *= fl;
|
|
z *= fl;
|
|
|
|
return *this;
|
|
}
|
|
//===============================================
|
|
inline Vector& Vector::operator*=(const Vector& v)
|
|
{
|
|
x *= v.x;
|
|
y *= v.y;
|
|
z *= v.z;
|
|
|
|
return *this;
|
|
}
|
|
//===============================================
|
|
inline Vector& Vector::operator+=(float fl)
|
|
{
|
|
x += fl;
|
|
y += fl;
|
|
z += fl;
|
|
|
|
return *this;
|
|
}
|
|
//===============================================
|
|
inline Vector& Vector::operator-=(float fl)
|
|
{
|
|
x -= fl;
|
|
y -= fl;
|
|
z -= fl;
|
|
|
|
return *this;
|
|
}
|
|
//===============================================
|
|
inline Vector& Vector::operator/=(float fl)
|
|
{
|
|
Assert(fl != 0.0f);
|
|
float oofl = 1.0f / fl;
|
|
x *= oofl;
|
|
y *= oofl;
|
|
z *= oofl;
|
|
|
|
return *this;
|
|
}
|
|
//===============================================
|
|
inline Vector& Vector::operator/=(const Vector& v)
|
|
{
|
|
Assert(v.x != 0.0f && v.y != 0.0f && v.z != 0.0f);
|
|
x /= v.x;
|
|
y /= v.y;
|
|
z /= v.z;
|
|
|
|
return *this;
|
|
}
|
|
//===============================================
|
|
inline float Vector::Length(void) const
|
|
{
|
|
|
|
|
|
float root = 0.0f;
|
|
|
|
float sqsr = x * x + y * y + z * z;
|
|
|
|
root = sqrt(sqsr);
|
|
|
|
return root;
|
|
}
|
|
//===============================================
|
|
inline float Vector::Length2D(void) const
|
|
{
|
|
float root = 0.0f;
|
|
|
|
float sqst = x * x + y * y;
|
|
|
|
root = sqrt(sqst);
|
|
|
|
return root;
|
|
}
|
|
//===============================================
|
|
inline float Vector::Length2DSqr(void) const
|
|
{
|
|
return (x * x + y * y);
|
|
}
|
|
//===============================================
|
|
inline Vector CrossProduct(const Vector& a, const Vector& b)
|
|
{
|
|
return Vector(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
|
|
}
|
|
//===============================================
|
|
float Vector::DistTo(const Vector& vOther) const
|
|
{
|
|
Vector delta;
|
|
|
|
delta.x = x - vOther.x;
|
|
delta.y = y - vOther.y;
|
|
delta.z = z - vOther.z;
|
|
|
|
return delta.Length();
|
|
}
|
|
float Vector::DistToSqr(const Vector& vOther) const
|
|
{
|
|
Vector delta;
|
|
|
|
delta.x = x - vOther.x;
|
|
delta.y = y - vOther.y;
|
|
delta.z = z - vOther.z;
|
|
|
|
return delta.LengthSqr();
|
|
}
|
|
//===============================================
|
|
inline Vector Vector::Normalize()
|
|
{
|
|
Vector vector;
|
|
float length = this->Length();
|
|
|
|
if (length != 0)
|
|
{
|
|
vector.x = x / length;
|
|
vector.y = y / length;
|
|
vector.z = z / length;
|
|
}
|
|
else
|
|
{
|
|
vector.x = vector.y = 0.0f; vector.z = 1.0f;
|
|
}
|
|
|
|
return vector;
|
|
}
|
|
//===============================================
|
|
inline void Vector::NormalizeInPlace()
|
|
{
|
|
Vector& v = *this;
|
|
|
|
float iradius = 1.f / (this->Length() + 1.192092896e-07F); //FLT_EPSILON
|
|
|
|
v.x *= iradius;
|
|
v.y *= iradius;
|
|
v.z *= iradius;
|
|
}
|
|
//===============================================
|
|
inline float VectorNormalize(Vector& v)
|
|
{
|
|
Assert(v.IsValid());
|
|
float l = v.Length();
|
|
if (l != 0.0f)
|
|
{
|
|
v /= l;
|
|
}
|
|
else
|
|
{
|
|
// FIXME:
|
|
// Just copying the existing implemenation; shouldn't res.z == 0?
|
|
v.x = v.y = 0.0f; v.z = 1.0f;
|
|
}
|
|
return l;
|
|
}
|
|
//===============================================
|
|
inline float VectorNormalize(float* v)
|
|
{
|
|
return VectorNormalize(*(reinterpret_cast<Vector*>(v)));
|
|
}
|
|
//===============================================
|
|
inline Vector Vector::operator+(const Vector& v) const
|
|
{
|
|
Vector res;
|
|
res.x = x + v.x;
|
|
res.y = y + v.y;
|
|
res.z = z + v.z;
|
|
return res;
|
|
}
|
|
|
|
//===============================================
|
|
inline Vector Vector::operator-(const Vector& v) const
|
|
{
|
|
Vector res;
|
|
res.x = x - v.x;
|
|
res.y = y - v.y;
|
|
res.z = z - v.z;
|
|
return res;
|
|
}
|
|
//===============================================
|
|
inline Vector Vector::operator*(float fl) const
|
|
{
|
|
Vector res;
|
|
res.x = x * fl;
|
|
res.y = y * fl;
|
|
res.z = z * fl;
|
|
return res;
|
|
}
|
|
//===============================================
|
|
inline Vector Vector::operator*(const Vector& v) const
|
|
{
|
|
Vector res;
|
|
res.x = x * v.x;
|
|
res.y = y * v.y;
|
|
res.z = z * v.z;
|
|
return res;
|
|
}
|
|
//===============================================
|
|
inline Vector Vector::operator/(float fl) const
|
|
{
|
|
Vector res;
|
|
res.x = x / fl;
|
|
res.y = y / fl;
|
|
res.z = z / fl;
|
|
return res;
|
|
}
|
|
//===============================================
|
|
inline Vector Vector::operator/(const Vector& v) const
|
|
{
|
|
Vector res;
|
|
res.x = x / v.x;
|
|
res.y = y / v.y;
|
|
res.z = z / v.z;
|
|
return res;
|
|
}
|
|
inline float Vector::Dot(const Vector& vOther) const
|
|
{
|
|
const Vector& a = *this;
|
|
|
|
return(a.x * vOther.x + a.y * vOther.y + a.z * vOther.z);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// length
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline float VectorLength(const Vector& v)
|
|
{
|
|
|
|
return (float)FastSqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
|
}
|
|
|
|
//VECTOR SUBTRAC
|
|
inline void VectorSubtract(const Vector& a, const Vector& b, Vector& c)
|
|
{
|
|
|
|
|
|
c.x = a.x - b.x;
|
|
c.y = a.y - b.y;
|
|
c.z = a.z - b.z;
|
|
}
|
|
|
|
//VECTORADD
|
|
inline void VectorAdd(const Vector& a, const Vector& b, Vector& c)
|
|
{
|
|
|
|
|
|
c.x = a.x + b.x;
|
|
c.y = a.y + b.y;
|
|
c.z = a.z + b.z;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Base address...
|
|
//-----------------------------------------------------------------------------
|
|
inline float* Vector::Base()
|
|
{
|
|
return (float*)this;
|
|
}
|
|
|
|
inline float const* Vector::Base() const
|
|
{
|
|
return (float const*)this;
|
|
}
|
|
|
|
inline void VectorMAInline(const float* start, float scale, const float* direction, float* dest)
|
|
{
|
|
dest[0] = start[0] + direction[0] * scale;
|
|
dest[1] = start[1] + direction[1] * scale;
|
|
dest[2] = start[2] + direction[2] * scale;
|
|
}
|
|
|
|
inline void VectorMAInline(const Vector& start, float scale, const Vector& direction, Vector& dest)
|
|
{
|
|
dest.x = start.x + direction.x * scale;
|
|
dest.y = start.y + direction.y * scale;
|
|
dest.z = start.z + direction.z * scale;
|
|
}
|
|
|
|
inline void VectorMA(const Vector& start, float scale, const Vector& direction, Vector& dest)
|
|
{
|
|
VectorMAInline(start, scale, direction, dest);
|
|
}
|
|
|
|
inline void VectorMA(const float* start, float scale, const float* direction, float* dest)
|
|
{
|
|
VectorMAInline(start, scale, direction, dest);
|
|
}
|
|
|
|
|
|
inline unsigned long& FloatBits(float& f)
|
|
{
|
|
return *reinterpret_cast<unsigned long*>(&f);
|
|
}
|
|
|
|
inline bool IsFinite(float f)
|
|
{
|
|
return ((FloatBits(f) & 0x7F800000) != 0x7F800000);
|
|
}
|
|
|
|
//=========================================================
|
|
// 2D Vector2D
|
|
//=========================================================
|
|
|
|
class Vector2D
|
|
{
|
|
public:
|
|
// Members
|
|
float x, y;
|
|
|
|
// Construction/destruction
|
|
Vector2D(void);
|
|
Vector2D(float X, float Y);
|
|
Vector2D(const float* pFloat);
|
|
|
|
// Initialization
|
|
void Init(float ix = 0.0f, float iy = 0.0f);
|
|
|
|
// Got any nasty NAN's?
|
|
bool IsValid() const;
|
|
|
|
// array access...
|
|
float operator[](int i) const;
|
|
float& operator[](int i);
|
|
|
|
// Base address...
|
|
float* Base();
|
|
float const* Base() const;
|
|
|
|
// Initialization methods
|
|
void Random(float minVal, float maxVal);
|
|
|
|
// equality
|
|
bool operator==(const Vector2D& v) const;
|
|
bool operator!=(const Vector2D& v) const;
|
|
|
|
// arithmetic operations
|
|
Vector2D& operator+=(const Vector2D& v);
|
|
Vector2D& operator-=(const Vector2D& v);
|
|
Vector2D& operator*=(const Vector2D& v);
|
|
Vector2D& operator*=(float s);
|
|
Vector2D& operator/=(const Vector2D& v);
|
|
Vector2D& operator/=(float s);
|
|
|
|
// negate the Vector2D components
|
|
void Negate();
|
|
|
|
// Get the Vector2D's magnitude.
|
|
float Length() const;
|
|
|
|
// Get the Vector2D's magnitude squared.
|
|
float LengthSqr(void) const;
|
|
|
|
// return true if this vector is (0,0) within tolerance
|
|
bool IsZero(float tolerance = 0.01f) const
|
|
{
|
|
return (x > -tolerance && x < tolerance &&
|
|
y > -tolerance && y < tolerance);
|
|
}
|
|
|
|
float Normalize();
|
|
|
|
// Normalize in place and return the old length.
|
|
float NormalizeInPlace();
|
|
|
|
// Compare length.
|
|
bool IsLengthGreaterThan(float val) const;
|
|
bool IsLengthLessThan(float val) const;
|
|
|
|
// Get the distance from this Vector2D to the other one.
|
|
float DistTo(const Vector2D& vOther) const;
|
|
|
|
// Get the distance from this Vector2D to the other one squared.
|
|
float DistToSqr(const Vector2D& vOther) const;
|
|
|
|
// Copy
|
|
void CopyToArray(float* rgfl) const;
|
|
|
|
// Multiply, add, and assign to this (ie: *this = a + b * scalar). This
|
|
// is about 12% faster than the actual Vector2D equation (because it's done per-component
|
|
// rather than per-Vector2D).
|
|
void MulAdd(const Vector2D& a, const Vector2D& b, float scalar);
|
|
|
|
// Dot product.
|
|
float Dot(const Vector2D& vOther) const;
|
|
|
|
// assignment
|
|
Vector2D& operator=(const Vector2D& vOther);
|
|
|
|
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
|
// copy constructors
|
|
Vector2D(const Vector2D& vOther);
|
|
|
|
// arithmetic operations
|
|
Vector2D operator-(void) const;
|
|
|
|
Vector2D operator+(const Vector2D& v) const;
|
|
Vector2D operator-(const Vector2D& v) const;
|
|
Vector2D operator*(const Vector2D& v) const;
|
|
Vector2D operator/(const Vector2D& v) const;
|
|
Vector2D operator*(float fl) const;
|
|
Vector2D operator/(float fl) const;
|
|
|
|
// Cross product between two vectors.
|
|
Vector2D Cross(const Vector2D& vOther) const;
|
|
|
|
// Returns a Vector2D with the min or max in X, Y, and Z.
|
|
Vector2D Min(const Vector2D& vOther) const;
|
|
Vector2D Max(const Vector2D& vOther) const;
|
|
|
|
#else
|
|
|
|
private:
|
|
// No copy constructors allowed if we're in optimal mode
|
|
Vector2D(const Vector2D& vOther);
|
|
#endif
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
const Vector2D vec2_origin(0, 0);
|
|
//const Vector2D vec2_invalid(3.40282347E+38F, 3.40282347E+38F);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Vector2D related operations
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Vector2D clear
|
|
void Vector2DClear(Vector2D& a);
|
|
|
|
// Copy
|
|
void Vector2DCopy(const Vector2D& src, Vector2D& dst);
|
|
|
|
// Vector2D arithmetic
|
|
void Vector2DAdd(const Vector2D& a, const Vector2D& b, Vector2D& result);
|
|
void Vector2DSubtract(const Vector2D& a, const Vector2D& b, Vector2D& result);
|
|
void Vector2DMultiply(const Vector2D& a, float b, Vector2D& result);
|
|
void Vector2DMultiply(const Vector2D& a, const Vector2D& b, Vector2D& result);
|
|
void Vector2DDivide(const Vector2D& a, float b, Vector2D& result);
|
|
void Vector2DDivide(const Vector2D& a, const Vector2D& b, Vector2D& result);
|
|
void Vector2DMA(const Vector2D& start, float s, const Vector2D& dir, Vector2D& result);
|
|
|
|
// Store the min or max of each of x, y, and z into the result.
|
|
void Vector2DMin(const Vector2D& a, const Vector2D& b, Vector2D& result);
|
|
void Vector2DMax(const Vector2D& a, const Vector2D& b, Vector2D& result);
|
|
|
|
#define Vector2DExpand( v ) (v).x, (v).y
|
|
|
|
// Normalization
|
|
float Vector2DNormalize(Vector2D& v);
|
|
|
|
// Length
|
|
float Vector2DLength(const Vector2D& v);
|
|
|
|
// Dot Product
|
|
float DotProduct2D(const Vector2D& a, const Vector2D& b);
|
|
|
|
// Linearly interpolate between two vectors
|
|
void Vector2DLerp(const Vector2D& src1, const Vector2D& src2, float t, Vector2D& dest);
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Inlined Vector2D methods
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// constructors
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline Vector2D::Vector2D(void)
|
|
{
|
|
#ifdef _DEBUG
|
|
// Initialize to NAN to catch errors
|
|
//x = y = float_NAN;
|
|
#endif
|
|
}
|
|
|
|
inline Vector2D::Vector2D(float X, float Y)
|
|
{
|
|
x = X; y = Y;
|
|
Assert(IsValid());
|
|
}
|
|
|
|
inline Vector2D::Vector2D(const float* pFloat)
|
|
{
|
|
Assert(pFloat);
|
|
x = pFloat[0]; y = pFloat[1];
|
|
Assert(IsValid());
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// copy constructor
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline Vector2D::Vector2D(const Vector2D& vOther)
|
|
{
|
|
Assert(vOther.IsValid());
|
|
x = vOther.x; y = vOther.y;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// initialization
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline void Vector2D::Init(float ix, float iy)
|
|
{
|
|
x = ix; y = iy;
|
|
Assert(IsValid());
|
|
}
|
|
|
|
inline void Vector2D::Random(float minVal, float maxVal)
|
|
{
|
|
x = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal);
|
|
y = minVal + ((float)rand() / VALVE_RAND_MAX) * (maxVal - minVal);
|
|
}
|
|
|
|
inline void Vector2DClear(Vector2D& a)
|
|
{
|
|
a.x = a.y = 0.0f;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// assignment
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline Vector2D& Vector2D::operator=(const Vector2D& vOther)
|
|
{
|
|
Assert(vOther.IsValid());
|
|
x = vOther.x; y = vOther.y;
|
|
return *this;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Array access
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline float& Vector2D::operator[](int i)
|
|
{
|
|
Assert((i >= 0) && (i < 2));
|
|
return ((float*)this)[i];
|
|
}
|
|
|
|
inline float Vector2D::operator[](int i) const
|
|
{
|
|
Assert((i >= 0) && (i < 2));
|
|
return ((float*)this)[i];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Base address...
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline float* Vector2D::Base()
|
|
{
|
|
return (float*)this;
|
|
}
|
|
|
|
inline float const* Vector2D::Base() const
|
|
{
|
|
return (float const*)this;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// IsValid?
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline bool Vector2D::IsValid() const
|
|
{
|
|
return IsFinite(x) && IsFinite(y);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// comparison
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline bool Vector2D::operator==(const Vector2D& src) const
|
|
{
|
|
Assert(src.IsValid() && IsValid());
|
|
return (src.x == x) && (src.y == y);
|
|
}
|
|
|
|
inline bool Vector2D::operator!=(const Vector2D& src) const
|
|
{
|
|
Assert(src.IsValid() && IsValid());
|
|
return (src.x != x) || (src.y != y);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Copy
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline void Vector2DCopy(const Vector2D& src, Vector2D& dst)
|
|
{
|
|
Assert(src.IsValid());
|
|
dst.x = src.x;
|
|
dst.y = src.y;
|
|
}
|
|
|
|
inline void Vector2D::CopyToArray(float* rgfl) const
|
|
{
|
|
Assert(IsValid());
|
|
Assert(rgfl);
|
|
rgfl[0] = x; rgfl[1] = y;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// standard math operations
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline void Vector2D::Negate()
|
|
{
|
|
Assert(IsValid());
|
|
x = -x; y = -y;
|
|
}
|
|
|
|
inline Vector2D& Vector2D::operator+=(const Vector2D& v)
|
|
{
|
|
Assert(IsValid() && v.IsValid());
|
|
x += v.x; y += v.y;
|
|
return *this;
|
|
}
|
|
|
|
inline Vector2D& Vector2D::operator-=(const Vector2D& v)
|
|
{
|
|
Assert(IsValid() && v.IsValid());
|
|
x -= v.x; y -= v.y;
|
|
return *this;
|
|
}
|
|
|
|
inline Vector2D& Vector2D::operator*=(float fl)
|
|
{
|
|
x *= fl;
|
|
y *= fl;
|
|
Assert(IsValid());
|
|
return *this;
|
|
}
|
|
|
|
inline Vector2D& Vector2D::operator*=(const Vector2D& v)
|
|
{
|
|
x *= v.x;
|
|
y *= v.y;
|
|
Assert(IsValid());
|
|
return *this;
|
|
}
|
|
|
|
inline Vector2D& Vector2D::operator/=(float fl)
|
|
{
|
|
Assert(fl != 0.0f);
|
|
float oofl = 1.0f / fl;
|
|
x *= oofl;
|
|
y *= oofl;
|
|
Assert(IsValid());
|
|
return *this;
|
|
}
|
|
|
|
inline Vector2D& Vector2D::operator/=(const Vector2D& v)
|
|
{
|
|
Assert(v.x != 0.0f && v.y != 0.0f);
|
|
x /= v.x;
|
|
y /= v.y;
|
|
Assert(IsValid());
|
|
return *this;
|
|
}
|
|
|
|
inline void Vector2DAdd(const Vector2D& a, const Vector2D& b, Vector2D& c)
|
|
{
|
|
Assert(a.IsValid() && b.IsValid());
|
|
c.x = a.x + b.x;
|
|
c.y = a.y + b.y;
|
|
}
|
|
|
|
inline void Vector2DSubtract(const Vector2D& a, const Vector2D& b, Vector2D& c)
|
|
{
|
|
Assert(a.IsValid() && b.IsValid());
|
|
c.x = a.x - b.x;
|
|
c.y = a.y - b.y;
|
|
}
|
|
|
|
inline void Vector2DMultiply(const Vector2D& a, float b, Vector2D& c)
|
|
{
|
|
Assert(a.IsValid() && IsFinite(b));
|
|
c.x = a.x * b;
|
|
c.y = a.y * b;
|
|
}
|
|
|
|
inline void Vector2DMultiply(const Vector2D& a, const Vector2D& b, Vector2D& c)
|
|
{
|
|
Assert(a.IsValid() && b.IsValid());
|
|
c.x = a.x * b.x;
|
|
c.y = a.y * b.y;
|
|
}
|
|
|
|
|
|
inline void Vector2DDivide(const Vector2D& a, float b, Vector2D& c)
|
|
{
|
|
Assert(a.IsValid());
|
|
Assert(b != 0.0f);
|
|
float oob = 1.0f / b;
|
|
c.x = a.x * oob;
|
|
c.y = a.y * oob;
|
|
}
|
|
|
|
inline void Vector2DDivide(const Vector2D& a, const Vector2D& b, Vector2D& c)
|
|
{
|
|
Assert(a.IsValid());
|
|
Assert((b.x != 0.0f) && (b.y != 0.0f));
|
|
c.x = a.x / b.x;
|
|
c.y = a.y / b.y;
|
|
}
|
|
|
|
inline void Vector2DMA(const Vector2D& start, float s, const Vector2D& dir, Vector2D& result)
|
|
{
|
|
Assert(start.IsValid() && IsFinite(s) && dir.IsValid());
|
|
result.x = start.x + s * dir.x;
|
|
result.y = start.y + s * dir.y;
|
|
}
|
|
|
|
// FIXME: Remove
|
|
// For backwards compatability
|
|
inline void Vector2D::MulAdd(const Vector2D& a, const Vector2D& b, float scalar)
|
|
{
|
|
x = a.x + b.x * scalar;
|
|
y = a.y + b.y * scalar;
|
|
}
|
|
|
|
inline void Vector2DLerp(const Vector2D& src1, const Vector2D& src2, float t, Vector2D& dest)
|
|
{
|
|
dest[0] = src1[0] + (src2[0] - src1[0]) * t;
|
|
dest[1] = src1[1] + (src2[1] - src1[1]) * t;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// dot, cross
|
|
//-----------------------------------------------------------------------------
|
|
inline float DotProduct2D(const Vector2D& a, const Vector2D& b)
|
|
{
|
|
Assert(a.IsValid() && b.IsValid());
|
|
return(a.x * b.x + a.y * b.y);
|
|
}
|
|
|
|
// for backwards compatability
|
|
inline float Vector2D::Dot(const Vector2D& vOther) const
|
|
{
|
|
return DotProduct2D(*this, vOther);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// length
|
|
//-----------------------------------------------------------------------------
|
|
inline float Vector2DLength(const Vector2D& v)
|
|
{
|
|
Assert(v.IsValid());
|
|
return (float)FastSqrt(v.x * v.x + v.y * v.y);
|
|
}
|
|
|
|
inline float Vector2D::LengthSqr(void) const
|
|
{
|
|
Assert(IsValid());
|
|
return (x * x + y * y);
|
|
}
|
|
|
|
inline float Vector2D::NormalizeInPlace()
|
|
{
|
|
return Vector2DNormalize(*this);
|
|
}
|
|
|
|
inline bool Vector2D::IsLengthGreaterThan(float val) const
|
|
{
|
|
return LengthSqr() > val* val;
|
|
}
|
|
|
|
inline bool Vector2D::IsLengthLessThan(float val) const
|
|
{
|
|
return LengthSqr() < val * val;
|
|
}
|
|
|
|
inline float Vector2D::Length(void) const
|
|
{
|
|
return Vector2DLength(*this);
|
|
}
|
|
|
|
|
|
inline void Vector2DMin(const Vector2D& a, const Vector2D& b, Vector2D& result)
|
|
{
|
|
result.x = (a.x < b.x) ? a.x : b.x;
|
|
result.y = (a.y < b.y) ? a.y : b.y;
|
|
}
|
|
|
|
|
|
inline void Vector2DMax(const Vector2D& a, const Vector2D& b, Vector2D& result)
|
|
{
|
|
result.x = (a.x > b.x) ? a.x : b.x;
|
|
result.y = (a.y > b.y) ? a.y : b.y;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Normalization
|
|
//-----------------------------------------------------------------------------
|
|
inline float Vector2DNormalize(Vector2D& v)
|
|
{
|
|
Assert(v.IsValid());
|
|
float l = v.Length();
|
|
if (l != 0.0f)
|
|
{
|
|
v /= l;
|
|
}
|
|
else
|
|
{
|
|
v.x = v.y = 0.0f;
|
|
}
|
|
return l;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Get the distance from this Vector2D to the other one
|
|
//-----------------------------------------------------------------------------
|
|
inline float Vector2D::DistTo(const Vector2D& vOther) const
|
|
{
|
|
Vector2D delta;
|
|
Vector2DSubtract(*this, vOther, delta);
|
|
return delta.Length();
|
|
}
|
|
|
|
inline float Vector2D::DistToSqr(const Vector2D& vOther) const
|
|
{
|
|
Vector2D delta;
|
|
Vector2DSubtract(*this, vOther, delta);
|
|
return delta.LengthSqr();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Computes the closest point to vecTarget no farther than flMaxDist from vecStart
|
|
//-----------------------------------------------------------------------------
|
|
inline void ComputeClosestPoint2D(const Vector2D& vecStart, float flMaxDist, const Vector2D& vecTarget, Vector2D* pResult)
|
|
{
|
|
Vector2D vecDelta;
|
|
Vector2DSubtract(vecTarget, vecStart, vecDelta);
|
|
float flDistSqr = vecDelta.LengthSqr();
|
|
if (flDistSqr <= flMaxDist * flMaxDist)
|
|
{
|
|
*pResult = vecTarget;
|
|
}
|
|
else
|
|
{
|
|
vecDelta /= FastSqrt(flDistSqr);
|
|
Vector2DMA(vecStart, flMaxDist, vecDelta, *pResult);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Slow methods
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
|
#endif
|
|
//-----------------------------------------------------------------------------
|
|
// Returns a Vector2D with the min or max in X, Y, and Z.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline Vector2D Vector2D::Min(const Vector2D& vOther) const
|
|
{
|
|
return Vector2D(x < vOther.x ? x : vOther.x,
|
|
y < vOther.y ? y : vOther.y);
|
|
}
|
|
|
|
inline Vector2D Vector2D::Max(const Vector2D& vOther) const
|
|
{
|
|
return Vector2D(x > vOther.x ? x : vOther.x,
|
|
y > vOther.y ? y : vOther.y);
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// arithmetic operations
|
|
//-----------------------------------------------------------------------------
|
|
|
|
inline Vector2D Vector2D::operator-(void) const
|
|
{
|
|
return Vector2D(-x, -y);
|
|
}
|
|
|
|
inline Vector2D Vector2D::operator+(const Vector2D& v) const
|
|
{
|
|
Vector2D res;
|
|
Vector2DAdd(*this, v, res);
|
|
return res;
|
|
}
|
|
|
|
inline Vector2D Vector2D::operator-(const Vector2D& v) const
|
|
{
|
|
Vector2D res;
|
|
Vector2DSubtract(*this, v, res);
|
|
return res;
|
|
}
|
|
|
|
inline Vector2D Vector2D::operator*(float fl) const
|
|
{
|
|
Vector2D res;
|
|
Vector2DMultiply(*this, fl, res);
|
|
return res;
|
|
}
|
|
|
|
inline Vector2D Vector2D::operator*(const Vector2D& v) const
|
|
{
|
|
Vector2D res;
|
|
Vector2DMultiply(*this, v, res);
|
|
return res;
|
|
}
|
|
|
|
inline Vector2D Vector2D::operator/(float fl) const
|
|
{
|
|
Vector2D res;
|
|
Vector2DDivide(*this, fl, res);
|
|
return res;
|
|
}
|
|
|
|
inline Vector2D Vector2D::operator/(const Vector2D& v) const
|
|
{
|
|
Vector2D res;
|
|
Vector2DDivide(*this, v, res);
|
|
return res;
|
|
}
|
|
|
|
inline Vector2D operator*(float fl, const Vector2D& v)
|
|
{
|
|
return v * fl;
|
|
}
|
|
|
|
class QAngleByValue;
|
|
class QAngle
|
|
{
|
|
public:
|
|
// Members
|
|
float x, y, z;
|
|
|
|
// Construction/destruction
|
|
QAngle(void);
|
|
QAngle(float X, float Y, float Z);
|
|
// QAngle(RadianEuler const &angles); // evil auto type promotion!!!
|
|
|
|
// Allow pass-by-value
|
|
operator QAngleByValue& () { return *((QAngleByValue*)(this)); }
|
|
operator const QAngleByValue& () const { return *((const QAngleByValue*)(this)); }
|
|
|
|
// Initialization
|
|
void Init(float ix = 0.0f, float iy = 0.0f, float iz = 0.0f);
|
|
void Random(float minVal, float maxVal);
|
|
|
|
// Got any nasty NAN's?
|
|
bool IsValid() const;
|
|
void Invalidate();
|
|
|
|
// array access...
|
|
float operator[](int i) const;
|
|
float& operator[](int i);
|
|
|
|
// Base address...
|
|
float* Base();
|
|
float const* Base() const;
|
|
|
|
// equality
|
|
bool operator==(const QAngle& v) const;
|
|
bool operator!=(const QAngle& v) const;
|
|
|
|
bool IsZero(float tolerance = 0.01f) const
|
|
{
|
|
return (x > -tolerance && x < tolerance &&
|
|
y > -tolerance && y < tolerance &&
|
|
z > -tolerance && z < tolerance);
|
|
}
|
|
|
|
// arithmetic operations
|
|
QAngle& operator+=(const QAngle& v);
|
|
QAngle& operator-=(const QAngle& v);
|
|
QAngle& operator*=(float s);
|
|
QAngle& operator/=(float s);
|
|
|
|
// Get the vector's magnitude.
|
|
float Length() const;
|
|
float LengthSqr() const;
|
|
|
|
// negate the QAngle components
|
|
//void Negate();
|
|
|
|
// No assignment operators either...
|
|
QAngle& operator=(const QAngle& src);
|
|
|
|
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
|
// copy constructors
|
|
|
|
// arithmetic operations
|
|
QAngle operator-(void) const;
|
|
|
|
QAngle operator+(const QAngle& v) const;
|
|
QAngle operator-(const QAngle& v) const;
|
|
QAngle operator*(float fl) const;
|
|
QAngle operator/(float fl) const;
|
|
#else
|
|
|
|
private:
|
|
// No copy constructors allowed if we're in optimal mode
|
|
QAngle(const QAngle& vOther);
|
|
|
|
#endif
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// constructors
|
|
//-----------------------------------------------------------------------------
|
|
inline QAngle::QAngle(void)
|
|
{
|
|
#ifdef _DEBUG
|
|
#ifdef VECTOR_PARANOIA
|
|
// Initialize to NAN to catch errors
|
|
x = y = z = VEC_T_NAN;
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
inline QAngle::QAngle(float X, float Y, float Z)
|
|
{
|
|
x = X; y = Y; z = Z;
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// initialization
|
|
//-----------------------------------------------------------------------------
|
|
inline void QAngle::Init(float ix, float iy, float iz)
|
|
{
|
|
x = ix; y = iy; z = iz;
|
|
|
|
}
|
|
|
|
inline void QAngle::Random(float minVal, float maxVal)
|
|
{
|
|
x = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal);
|
|
y = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal);
|
|
z = minVal + ((float)rand() / RAND_MAX) * (maxVal - minVal);
|
|
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// assignment
|
|
//-----------------------------------------------------------------------------
|
|
inline QAngle& QAngle::operator=(const QAngle& vOther)
|
|
{
|
|
|
|
x = vOther.x; y = vOther.y; z = vOther.z;
|
|
return *this;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// comparison
|
|
//-----------------------------------------------------------------------------
|
|
inline bool QAngle::operator==(const QAngle& src) const
|
|
{
|
|
|
|
|
|
return (src.x == x) && (src.y == y) && (src.z == z);
|
|
}
|
|
|
|
inline bool QAngle::operator!=(const QAngle& src) const
|
|
{
|
|
|
|
|
|
return (src.x != x) || (src.y != y) || (src.z != z);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// standard math operations
|
|
//-----------------------------------------------------------------------------
|
|
inline QAngle& QAngle::operator+=(const QAngle& v)
|
|
{
|
|
|
|
|
|
x += v.x; y += v.y; z += v.z;
|
|
return *this;
|
|
}
|
|
|
|
inline QAngle& QAngle::operator-=(const QAngle& v)
|
|
{
|
|
|
|
|
|
x -= v.x; y -= v.y; z -= v.z;
|
|
return *this;
|
|
}
|
|
|
|
inline QAngle& QAngle::operator*=(float fl)
|
|
{
|
|
x *= fl;
|
|
y *= fl;
|
|
z *= fl;
|
|
|
|
return *this;
|
|
}
|
|
|
|
inline QAngle& QAngle::operator/=(float fl)
|
|
{
|
|
Assert(fl != 0.0f);
|
|
float oofl = 1.0f / fl;
|
|
x *= oofl;
|
|
y *= oofl;
|
|
z *= oofl;
|
|
|
|
return *this;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Base address...
|
|
//-----------------------------------------------------------------------------
|
|
inline float* QAngle::Base()
|
|
{
|
|
return (float*)this;
|
|
}
|
|
|
|
inline float const* QAngle::Base() const
|
|
{
|
|
return (float const*)this;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Array access
|
|
//-----------------------------------------------------------------------------
|
|
inline float& QAngle::operator[](int i)
|
|
{
|
|
Assert((i >= 0) && (i < 3));
|
|
return ((float*)this)[i];
|
|
}
|
|
|
|
inline float QAngle::operator[](int i) const
|
|
{
|
|
Assert((i >= 0) && (i < 3));
|
|
return ((float*)this)[i];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// length
|
|
//-----------------------------------------------------------------------------
|
|
inline float QAngle::Length() const
|
|
{
|
|
|
|
return (float)FastSqrt(LengthSqr());
|
|
}
|
|
|
|
|
|
inline float QAngle::LengthSqr() const
|
|
{
|
|
|
|
return x * x + y * y + z * z;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// arithmetic operations (SLOW!!)
|
|
//-----------------------------------------------------------------------------
|
|
#ifndef VECTOR_NO_SLOW_OPERATIONS
|
|
|
|
inline QAngle QAngle::operator-(void) const
|
|
{
|
|
return QAngle(-x, -y, -z);
|
|
}
|
|
|
|
inline QAngle QAngle::operator+(const QAngle& v) const
|
|
{
|
|
QAngle res;
|
|
res.x = x + v.x;
|
|
res.y = y + v.y;
|
|
res.z = z + v.z;
|
|
return res;
|
|
}
|
|
|
|
inline QAngle QAngle::operator-(const QAngle& v) const
|
|
{
|
|
QAngle res;
|
|
res.x = x - v.x;
|
|
res.y = y - v.y;
|
|
res.z = z - v.z;
|
|
return res;
|
|
}
|
|
|
|
inline QAngle QAngle::operator*(float fl) const
|
|
{
|
|
QAngle res;
|
|
res.x = x * fl;
|
|
res.y = y * fl;
|
|
res.z = z * fl;
|
|
return res;
|
|
}
|
|
|
|
inline QAngle QAngle::operator/(float fl) const
|
|
{
|
|
QAngle res;
|
|
res.x = x / fl;
|
|
res.y = y / fl;
|
|
res.z = z / fl;
|
|
return res;
|
|
}
|
|
|
|
inline QAngle operator*(float fl, const QAngle& v)
|
|
{
|
|
return v * fl;
|
|
}
|
|
|
|
#endif // VECTOR_NO_SLOW_OPERATIONS
|
|
|
|
|
|
//QANGLE SUBTRAC
|
|
inline void QAngleSubtract(const QAngle& a, const QAngle& b, QAngle& c)
|
|
{
|
|
|
|
|
|
c.x = a.x - b.x;
|
|
c.y = a.y - b.y;
|
|
c.z = a.z - b.z;
|
|
}
|
|
|
|
//QANGLEADD
|
|
inline void QAngleAdd(const QAngle& a, const QAngle& b, QAngle& c)
|
|
{
|
|
|
|
|
|
c.x = a.x + b.x;
|
|
c.y = a.y + b.y;
|
|
c.z = a.z + b.z;
|
|
} |