This repository has been archived on 2024-06-13. You can view files and clone it, but cannot push or open issues or pull requests.
2020-08-04 13:13:01 -04:00

1329 lines
36 KiB
C++

#pragma GCC diagnostic ignored "-Wunused-value"
#pragma GCC diagnostic ignored "-Wreturn-type"
#include <math.h>
#include <stdlib.h>
#pragma once
#define CHECK_VALID(_v) 0
#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 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 {
CHECK_VALID(*this);
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();
float 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;
CHECK_VALID(*this);
}
//===============================================
inline Vector::Vector(float X, float Y, float Z) {
x = X;
y = Y;
z = Z;
CHECK_VALID(*this);
}
//===============================================
inline Vector::Vector(void) {}
//===============================================
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) {
CHECK_VALID(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 {
CHECK_VALID(src);
CHECK_VALID(*this);
return (src.x == x) && (src.y == y) && (src.z == z);
}
//===============================================
inline bool Vector::operator!=(const Vector& src) const {
CHECK_VALID(src);
CHECK_VALID(*this);
return (src.x != x) || (src.y != y) || (src.z != z);
}
//===============================================
inline void VectorCopy(const Vector& src, Vector& dst) {
CHECK_VALID(src);
dst.x = src.x;
dst.y = src.y;
dst.z = src.z;
}
//===============================================
inline Vector& Vector::operator+=(const Vector& v) {
CHECK_VALID(*this);
CHECK_VALID(v);
x += v.x;
y += v.y;
z += v.z;
return *this;
}
//===============================================
inline Vector& Vector::operator-=(const Vector& v) {
CHECK_VALID(*this);
CHECK_VALID(v);
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
//===============================================
inline Vector& Vector::operator*=(float fl) {
x *= fl;
y *= fl;
z *= fl;
CHECK_VALID(*this);
return *this;
}
//===============================================
inline Vector& Vector::operator*=(const Vector& v) {
CHECK_VALID(v);
x *= v.x;
y *= v.y;
z *= v.z;
CHECK_VALID(*this);
return *this;
}
//===============================================
inline Vector& Vector::operator+=(float fl) {
x += fl;
y += fl;
z += fl;
CHECK_VALID(*this);
return *this;
}
//===============================================
inline Vector& Vector::operator-=(float fl) {
x -= fl;
y -= fl;
z -= fl;
CHECK_VALID(*this);
return *this;
}
//===============================================
inline Vector& Vector::operator/=(float fl) {
Assert(fl != 0.0f);
float oofl = 1.0f / fl;
x *= oofl;
y *= oofl;
z *= oofl;
CHECK_VALID(*this);
return *this;
}
//===============================================
inline Vector& Vector::operator/=(const Vector& v) {
CHECK_VALID(v);
Assert(v.x != 0.0f && v.y != 0.0f && v.z != 0.0f);
x /= v.x;
y /= v.y;
z /= v.z;
CHECK_VALID(*this);
return *this;
}
//===============================================
inline float Vector::Length(void) const {
CHECK_VALID(*this);
float root = 0.0f;
float sqsr = x * x + y * y + z * z;
root = sqrt(sqsr);
return root;
}
//===============================================
inline float Vector::Length2D(void) const {
CHECK_VALID(*this);
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 float 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) {
CHECK_VALID(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) {
CHECK_VALID(a);
CHECK_VALID(b);
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) {
CHECK_VALID(a);
CHECK_VALID(b);
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);
}
class ALIGN16 VectorAligned : public Vector {
public:
inline VectorAligned(void){};
inline VectorAligned(float X, float Y, float Z) { Init(X, Y, Z); }
#ifdef VECTOR_NO_SLOW_OPERATIONS
private:
// No copy constructors allowed if we're in optimal mode
VectorAligned(const VectorAligned& vOther);
VectorAligned(const Vector& vOther);
#else
public:
explicit VectorAligned(const Vector& vOther) {
Init(vOther.x, vOther.y, vOther.z);
}
VectorAligned& operator=(const Vector& vOther) {
Init(vOther.x, vOther.y, vOther.z);
return *this;
}
#endif
float w; // this space is used anyway
};
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;
// 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;
CHECK_VALID(*this);
}
//-----------------------------------------------------------------------------
// initialization
//-----------------------------------------------------------------------------
inline void QAngle::Init(float ix, float iy, float iz) {
x = ix;
y = iy;
z = iz;
CHECK_VALID(*this);
}
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);
CHECK_VALID(*this);
}
//-----------------------------------------------------------------------------
// assignment
//-----------------------------------------------------------------------------
inline QAngle& QAngle::operator=(const QAngle& vOther) {
CHECK_VALID(vOther);
x = vOther.x;
y = vOther.y;
z = vOther.z;
return *this;
}
//-----------------------------------------------------------------------------
// comparison
//-----------------------------------------------------------------------------
inline bool QAngle::operator==(const QAngle& src) const {
CHECK_VALID(src);
CHECK_VALID(*this);
return (src.x == x) && (src.y == y) && (src.z == z);
}
inline bool QAngle::operator!=(const QAngle& src) const {
CHECK_VALID(src);
CHECK_VALID(*this);
return (src.x != x) || (src.y != y) || (src.z != z);
}
//-----------------------------------------------------------------------------
// standard math operations
//-----------------------------------------------------------------------------
inline QAngle& QAngle::operator+=(const QAngle& v) {
CHECK_VALID(*this);
CHECK_VALID(v);
x += v.x;
y += v.y;
z += v.z;
return *this;
}
inline QAngle& QAngle::operator-=(const QAngle& v) {
CHECK_VALID(*this);
CHECK_VALID(v);
x -= v.x;
y -= v.y;
z -= v.z;
return *this;
}
inline QAngle& QAngle::operator*=(float fl) {
x *= fl;
y *= fl;
z *= fl;
CHECK_VALID(*this);
return *this;
}
inline QAngle& QAngle::operator/=(float fl) {
Assert(fl != 0.0f);
float oofl = 1.0f / fl;
x *= oofl;
y *= oofl;
z *= oofl;
CHECK_VALID(*this);
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 {
CHECK_VALID(*this);
return (float)FastSqrt(LengthSqr());
}
inline float QAngle::LengthSqr() const {
CHECK_VALID(*this);
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) {
CHECK_VALID(a);
CHECK_VALID(b);
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) {
CHECK_VALID(a);
CHECK_VALID(b);
c.x = a.x + b.x;
c.y = a.y + b.y;
c.z = a.z + b.z;
}