Files
Leviathan/Library/External/include/SpeedGrass/LibVector_Source/IdvVector.h
T
2026-06-01 12:46:52 +02:00

1229 lines
49 KiB
C++

// Name: IdvVector.h
//
// *** INTERACTIVE DATA VISUALIZATION (IDV) PROPRIETARY INFORMATION ***
//
// Copyright (c) 2001-2002 IDV, Inc.
// All Rights Reserved.
//
// IDV, Inc.
// 1233 Washington St. Suite 610
// Columbia, SC 29201
// Voice: (803) 799-1699
// Fax: (803) 931-0320
// Web: http://www.idvinc.com
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Interactive Data Visualization and may not
// be copied or disclosed except in accordance with the terms of that
// agreement.
#pragma once
#define BUILD_VECTOR_SET
#include <iostream>
#include "IdvFastMath.h"
#define VectorSinD(x) sinf((x) / 57.29578f)
#define VectorCosD(x) cosf((x) / 57.29578f)
#define VectorSinR(x) sinf(x)
#define VectorCosR(x) cosf(x)
///////////////////////////////////////////////////////////////////////
// Vector constants
//
const float c_fPi = 3.1415926535897932384626433832795f;
const float c_fHalfPi = c_fPi * 0.5f;
const float c_fQuarterPi = c_fPi * 0.25f;
const float c_fTwoPi = 2.0f * c_fPi;
///////////////////////////////////////////////////////////////////////
// Forward references
//
class CTransform;
class CRotTransform;
class CRegion;
class CVec;
///////////////////////////////////////////////////////////////////////
// class CVec3 declaration
//
//
// Description:
//
// Construction:
// -------------
// CVec3( ) Builds a vector equal to (0.0f, 0.0f, 0.0f).
// CVec3(bool bSkipInitialization) Builds a vector within uninitialized member variables
// CVec3(float x, y, z) Builds a vector with values (x, y, z)
// CVec3(float x, y) Builds a vector with values (x, y, 0.0f);
//
// Variables:
// ----------
// m_afData[3] Vector data storage. Public for OpenGL convenience and fast access.
//
// Inspectors:
// -----------
// AbsoluteValue( ) Returns a CVec3 where each m_afData[i] = fabs((*this)[i]).
// AngleBetween(const CVec3& CVec3) Returns the angle (in radians) between *this and CVec3 (assumes normalized vectors)
// Distance(const CVec3& cPoint) Returns the distance between *this and cPoint.
// GetSize( ) Returns the size of the CVec3.
// GetTolerance( ) Returns the current tolerance setting (used in RoughlyEqual( )) for all CVec3s.
// Magnitude( ) Computes the magnitude of the CVec3.
// MaxAxis( ) Returns the largest value in the CVec3.
// Midpoint(const CVec3& cVec) Computes the point half way between cVec and *this.
// MinAxis( ) Returns the smallest value in the CVec3.
// RoughlyEqual(const CVec3& CVec3) Determines if *this CVec3 is equivalent to CVec3 within the specified tolerance.
//
// Mutators:
// ---------
// Set(...) All forms set the specified data points and leave the others unchanged.
// SetTolerance(float fTolerance) Sets the RoughlyEqual tolerance for ALL CVec3s.
// SetSize(int nSize) Sets the size (number of data points considered valid) of *this.
// Normalize( ) Makes the CVec3 a unit vector.
//
// Operators:
// ----------
// operator float*( ) Converts a CVec3 to a float*.
// operator[](int nIndex) Returns a reference to the specified data point (const version allows access for other const member functions).
// operator<(const CVec3 &CVec3) Returns true if the x coord of *this is less than that of CVec3. If they are equal, the test moves to the y coord and then the z.
// operator<=(const CVec3 &CVec3) Returns true if the x coord of *this is less than or equal to that of CVec3.
// operator>(const CVec3 &CVec3) Returns true if the x coord of *this is greater than that of CVec3. If they are equal, the test moves to the y coord and then the z.
// operator>=(const CVec3 &CVec3) Returns true if the x coord of *this is greater than or equal to that of CVec3.
// operator+(const CVec3& CVec3) Returns *this + CVec3.
// operator+=(const CVec3& CVec3) Adds CVec3 to *this.
// operator-(const CVec3& CVec3) Returns *this - CVec3.
// operator-=(const CVec3& CVec3) Subtracts CVec3 from *this.
// operator-( ) Returns -(*this).
// operator^(const CVec3& CVec3) Computes the DOT product of *this and CVec3.
// operator*(const CVec3& CVec3) Computes the CROSS product of *this and CVec3.
// operator*=(const CVec3& CVec3) *this equals the cross product of *this and CVec3.
// operator*(float fValue) Returns a CVec3 equal to *this with each data point multiplied by fValue.
// operator*=(float fValue) Each data point of *this is multiplied by fValue.
// operator/(float fValue) Returns a CVec3 equal to *this with each data point divided by fValue.
// operator/=(float fValue) Each data point of *this is divided by fValue.
// operator==(const CVec3& CVec3) Returns true when *this and CVec3 are identical.
// operator!=(const CVec3& CVec3) Returns true when *this and CVec3 are not identical.
// operator*(const CTransform& CTrans) Returns a CVec3 that is equal to *this * CTransform3 (the vector is on the left).
// operator*(const CRotTransform3& CTrans) Returns a CVec3 that is equal to *this * CTransform3 (the vector is on the left).
// operator<<(ostream& cStream, ...) Outputs *this.
class BUILD_VECTOR_SET CVec3
{
public:
CVec3( );
CVec3(bool bSkipInitialization) { }
CVec3(float fX, float fY, float fZ);
CVec3(float fX, float fY);
// inspectors
CVec3 AbsoluteValue( ) const;
float AngleBetween(const CVec3& cVec) const;
CVec3 Cross(const CVec3& cVec) const;
float Distance(const CVec3& cPoint) const;
float Dot(const CVec3& cVec) const;
float GetTolerance( ) const { return m_fTolerance; }
float Magnitude( ) const;
float MaxAxis( ) const;
CVec3 Midpoint(const CVec3& cVec) const;
float MinAxis( ) const;
bool RoughlyEqual(const CVec3& cVec) const;
CVec ToVec(void) const;
// mutators
void Normalize( );
void Set(float fX, float fY);
void Set(float fX, float fY, float fZ);
void SetTolerance(float fTolerance) { m_fTolerance = fTolerance; }
// operators
operator float*( ) { return &m_afData[0]; }
operator const float*( ) const { return &m_afData[0]; }
float& operator[](int nIndex) { return m_afData[nIndex]; }
// float& operator[](int nIndex) { return m_afData[nIndex]; }
//const float& operator[](int nIndex) const { return m_afData[nIndex]; }
bool operator<(const CVec3& cVec) const;
bool operator<=(const CVec3& cVec) const;
bool operator>(const CVec3& cVec) const;
bool operator>=(const CVec3& cVec) const;
CVec3 operator+(const CVec3& cVec) const;
CVec3& operator+=(const CVec3& cVec);
CVec3 operator-(const CVec3& cVec) const;
CVec3& operator-=(const CVec3& cVec);
CVec3 operator-( ) const;
float operator^(const CVec3& cVec) const;
CVec3 operator*(const CVec3& cVec) const;
CVec3& operator*=(const CVec3& cVec);
CVec3 operator*(float fValue) const;
CVec3& operator*=(float fValue);
CVec3 operator/(float fValue) const;
CVec3& operator/=(float fValue);
bool operator==(const CVec3& cVec) const;
bool operator!=(const CVec3& cVec) const;
CVec3 operator*(const CTransform& cTransform) const;
CVec3 operator*(const CRotTransform& cTransform) const;
bool operator<=(const CRegion& cRegion) const;
bool operator<(const CRegion& cRegion) const;
friend BUILD_VECTOR_SET std::ostream& operator<<(std::ostream& cStream, const CVec3& cVec);
float m_afData[3]; // store the x, y, & z components of the CVec3
private:
static float m_fTolerance;
};
///////////////////////////////////////////////////////////////////////
// class CVec declaration
//
// Description: Summary of public interface
//
//
// Construction:
// -------------
// CVec( ) Builds a vector equal to (0.0f, 0.0f, 0.0f).
// CVec(int nSize) Builds a vector of size nSize with each member set to zero.
// CVec(float fX, ...) All forms build a vector whose size is equal to the number of arguments. The values are set to the corresponding parameters.
//
// Variables:
// ----------
// m_afData Vector data storage. Public for OpenGL convenience and fast access.
//
// Inspectors:
// -----------
// GetTolerance( ) Returns the current tolerance setting (used in RoughlyEqual( )) for all CVecs.
// GetSize( ) Returns the size of the CVec.
// Magnitude( ) Computes the magnitude of the CVec.
// MaxAxis( ) Returns the largest value in the CVec.
// MinAxis( ) Returns the smallest value in the CVec.
// AbsoluteValue( ) Returns a CVec where each m_afData[i] = fabs((*this)[i]).
// RoughlyEqual(const CVec& cVec) Determines if *this CVec is equivalent to cVec within the specified tolerance.
// Distance(const CVec& cPoint) Returns the distance between *this and cPoint.
// AngleBetween(const CVec& cVec) Returns the angle (in radians) between *this and cVec.
//
// Mutators:
// ---------
// Set(...) All forms set the specified data points and leave the others unchanged.
// SetTolerance(float fTolerance) Sets the RoughlyEqual tolerance for ALL CVecs.
// SetSize(int nSize) Sets the size (number of data points considered valid) of *this.
// Normalize( ) Makes the CVec a unit vector.
//
// Operators:
// ----------
// operator float*( ) Converts a CVec to a float*.
// operator[](int nIndex) Returns a reference to the specified data point (const version allows access for other const member functions).
// operator<(const CVec &cVec) Returns true if the x coord of *this is less than that of cVec. If they are equal, the test moves to the y coord and then the z.
// operator<=(const CVec &cVec) Returns true if the x coord of *this is less than or equal to that of cVec.
// operator>(const CVec &cVec) Returns true if the x coord of *this is greater than that of cVec. If they are equal, the test moves to the y coord and then the z.
// operator>=(const CVec &cVec) Returns true if the x coord of *this is greater than or equal to that of cVec.
// operator+(const CVec& cVec) Returns *this + cVec.
// operator+=(const CVec& cVec) Adds cVec to *this.
// operator-(const CVec& cVec) Returns *this - cVec.
// operator-=(const CVec& cVec) Subtracts cVec from *this.
// operator-( ) Returns -(*this).
// operator^(const CVec& cVec) Computes the DOT product of *this and cVec.
// operator*(const CVec& cVec) Computes the CROSS product of *this and cVec.
// operator*=(const CVec& cVec) *this equals the cross product of *this and cVec.
// operator*(float fValue) Returns a CVec equal to *this with each data point multiplied by fValue.
// operator*=(float fValue) Each data point of *this is multiplied by fValue.
// operator/(float fValue) Returns a CVec equal to *this with each data point divided by fValue.
// operator/=(float fValue) Each data point of *this is divided by fValue.
// operator==(const CVec& cVec) Returns true when *this and cVec are identical.
// operator!=(const CVec& cVec) Returns true when *this and cVec are not identical.
// operator*(const CTransform& cTransform) Returns a CVec that is equal to *this * cTransform (the vector is on the left).
// operator<<(ostream& cStream, ...) Outputs *this.
class BUILD_VECTOR_SET CVec
{
public:
CVec( );
CVec(int nSize);
CVec(float fX, float fY);
CVec(float fX, float fY, float fZ);
CVec(float fX, float fY, float fZ, float fW);
CVec(float fX, float fY, float fZ, float fW, float fV);
~CVec( );
// inspectors
float GetTolerance( ) const { return m_fTolerance; }
int GetSize( ) const { return m_nSize; }
CVec Midpoint(const CVec& cVec) const { return (*this + cVec) * 0.5f; }
void SetTolerance(float fTolerance) { m_fTolerance = fTolerance; }
void SetSize(int nSize) { m_nSize = nSize; }
float Magnitude( ) const;
float MaxAxis( ) const;
float MinAxis( ) const;
bool RoughlyEqual(const CVec& cVec) const;
CVec AbsoluteValue( ) const;
float Distance(const CVec& cPoint) const;
float AngleBetween(const CVec& cVec) const;
// mutators
void Normalize( );
void Set(float fX, float fY) { m_afData[0] = fX; m_afData[1] = fY; }
void Set(float fX, float fY, float fZ) { m_afData[0] = fX; m_afData[1] = fY; m_afData[2] = fZ; }
void Set(float fX, float fY, float fZ, float fW) { m_afData[0] = fX; m_afData[1] = fY; m_afData[2] = fZ; m_afData[3] = fW; }
void Set(float fX, float fY, float fZ, float fW, float fV) { m_afData[0] = fX; m_afData[1] = fY; m_afData[2] = fZ; m_afData[3] = fW; m_afData[4] = fV; }
// operators
operator float*( ) { return &m_afData[0]; }
operator const float*( ) const { return &m_afData[0]; }
float& operator[](int nIndex) { return m_afData[nIndex]; }
// float& operator[](int nIndex) { return m_afData[nIndex]; }
// float& operator[](const int& nIndex) const { return m_afData[nIndex]; }
bool operator<(const CVec& cVec) const;
bool operator<=(const CVec& cVec) const;
bool operator>(const CVec& cVec) const;
bool operator>=(const CVec& cVec) const;
CVec operator+(const CVec& cVec) const;
CVec& operator+=(const CVec& cVec);
CVec operator-(const CVec& cVec) const;
CVec& operator-=(const CVec& cVec);
CVec operator-( ) const;
float operator^(const CVec& cVec) const;
CVec operator*(const CVec& cVec) const;
CVec& operator*=(const CVec& cVec);
CVec operator*(float fValue) const;
CVec& operator*=(float fValue);
CVec operator/(float fValue) const;
CVec& operator/=(float fValue);
bool operator==(const CVec& cVec) const;
bool operator!=(const CVec& cVec) const;
CVec operator*(const CTransform& cTrans) const;
bool operator<=(const CRegion& cRegion) const;
bool operator<(const CRegion& cRegion) const;
friend BUILD_VECTOR_SET std::ostream& operator<<(std::ostream& cStream, const CVec& cVec);
float m_afData[5]; // store each component of the vector
private:
int m_nSize;
static float m_fTolerance;
};
///////////////////////////////////////////////////////////////////////
// class CRotTransform declaration
//
//
// Description: Optimized class used for matrix rotations & scales only (3 x 3 instead of 4 x 4)
//
// Construction:
// -------------
// CRotTransform( ) Builds a transformation matrix. LoadIdentity( ) is called.
// CRotTransform(bool) Builds a matrix without initialization.
//
// Variables:
// ----------
// m_afData[3][3] Matrix data storage. Public for OpenGL convenience and fast access.
//
// Inspectors:
// -----------
// IsIdentity( ) Returns true if *this represents the identity matrix.
//
// Mutators:
// ---------
// Set(int nRow, int nCol, float fValue) Sets the element at [nRow][nCol] to fValue.
// Set(float afData[3][3]) Sets the entire matrix.
// Invert( ) Inverts *this using lu decomposition.
// LoadIdentity( ) Makes *this the identity matrix.
// Scale(float fFactor) Scales *this on the x, y, and z axes by fFactor.
// Scale(float fX, float fY, float fZ) Scales *this.
// RotateX(float fAngle) Rotates *this fAngle degrees around the X axis (faster than general rotate)
// RotateY(float fAngle) Rotates *this fAngle degrees around the Y axis (faster than general rotate)
// RotateZ(float fAngle) Rotates *this fAngle degrees around the Z axis (faster than general rotate)
// RotateYZ(float fAngle) Rotates *this fAngle degrees around the Y then Z axes (faster than separate calls)
// RotateAxis(float fAngle, CVec3 cAxis) Rotates *this fAngle degrees around the axis represented by cAxis. *cAxis is assumed normalized.
// RotateAxis(float fAngle, CVec cAxis) Rotates *this fAngle degrees around the axis represented by cAxis. *cAxis is assumed normalized.
//
// Operators:
// ----------
// operator float*( ) Converts a CTransform3 to a float*.
// operator*(const CRotTransform3& ) Returns a CTransform3 equal to *this * CTransform3.
// operator*(const CVec3& CVec3) Returns a CVec3 equal to *this * CVec3.
// operator*(const CVec& CVec) Returns a CVec equal to *this * CVec.
// operator+(const CRotTransform3& ) Returns a CTransform3 equal to *this + CTransform3.
// operator-(const CRotTransform3& ) Returns a CTransform3 equal to *this - CTransform3.
// operator<<(ostream& cStream, ...) Outputs *this.
class BUILD_VECTOR_SET CRotTransform
{
public:
// constructors
CRotTransform( );
CRotTransform(bool bDontLoadIdentity) { }
// data gathering/setting
void Set(int nRow, int nCol, float fValue) { m_afData[nRow][nCol] = fValue; }
void Set(float afData[3][3]);
bool IsIdentity( ) const;
void LoadIdentity( );
// standard affine transform functions
void Scale(float fFactor);
void Scale(float fX, float fY, float fZ);
void RotateX(float fAngle);
void RotateY(float fAngle);
void RotateZ(float fAngle);
void RotateYZ(float fYangle, float fZangle);
void RotateAxis(float fAngle, CVec3 cAxis);
void RotateAxis(float fAngle, CVec cAxis);
void RotateAxisFromIdentity(float fAngle, CVec3 cAxis);
// C++ operator overloads
operator float*( ) { return &m_afData[0][0]; }
operator const float*( ) const { return &m_afData[0][0]; }
CRotTransform operator*(const CRotTransform& cTrans) const;
CVec3 operator*(const CVec3& cVec) const;
CVec operator*(const CVec& cVec) const;
CRotTransform operator+(const CRotTransform& cTrans) const;
CRotTransform operator-(const CRotTransform& cTrans) const;
friend BUILD_VECTOR_SET std::ostream& operator<<(std::ostream& cStream, const CRotTransform& cTrans);
float m_afData[3][3]; // 3 x 3 rotation matrix
};
///////////////////////////////////////////////////////////////////////
// class CTransform declaration
//
//
// Description: Summary of public interface
//
// Construction:
// -------------
// CTransform( ) Builds a transformation matrix. LoadIdentity( ) is called.
//
// Variables:
// ----------
// m_afData Matrix data storage. Public for OpenGL convenience and fast access.
//
// Inspectors:
// -----------
// IsIdentity( ) Returns true if *this represents the identity matrix.
//
// Mutators:
// ---------
// Set(int nRow, int nCol, float fValue) Sets the element at [nRow][nCol] to fValue.
// Set(float afData[4][4]) Sets the entire matrix.
// Invert( ) Inverts *this using lu decomposition.
// LoadIdentity( ) Makes *this the identity matrix.
// Scale(float fFactor) Scales *this on the x, y, and z axes by fFactor.
// Scale(float fX, float fY, float fZ) Scales *this.
// Translate(float fX, float fY, float fZ) Translates *this.
// Rotate(float fAngle, char chAxis) Rotates *this fAngle degrees around chAxis ('x', 'X', 'y', etc.)
// RotateAxis(float fAngle, CVec cAxis) Rotates *this fAngle degrees around the axis represented by cAxis. cAxis is normalized.
// LookAt(const CVec& cEye, const CVec& ...) Mimics the gluLookAt routine.
//
// Operators:
// ----------
// operator float*( ) Converts a CTransform to a float*.
// operator*(const CTransform& cTransform) Returns a CTransform equal to *this * cTransform.
// operator*(const CVec& cVec) Returns a CVec equal to *this * cVec.
// operator*(const CRegion& cRegion) Returns a CRegion where cRegion.m_cMin/m_cMax are multiplied by *this.
// operator+(const CTransform& cTransform) Returns a CTransform equal to *this + cTransform.
// operator-(const CTransform& cTransform) Returns a CTransform equal to *this - cTransform.
// operator<<(ostream& cStream, ...) Outputs *this.
class BUILD_VECTOR_SET CTransform
{
public:
enum EInversionCodeType
{
OK, SINGULAR
};
CTransform( );
// direct access
void Set(int nRow, int nCol, float fValue) { m_afData[nRow][nCol] = fValue; }
void Set(float afData[4][4]);
// inspectors
bool IsIdentity( ) const;
// mutators
EInversionCodeType Invert( );
void LoadIdentity( );
void Scale(float fFactor);
void Scale(float fX, float fY, float fZ);
void Translate(float fX, float fY, float fZ);
void Rotate(float fAngle, char chAxis);
void RotateAxis(float fAngle, CVec cAxis);
void LookAt(const CVec& cEye, const CVec& cCenter, const CVec& cUp);
// operators
operator float*( ) { return &m_afData[0][0]; }
operator const float*( ) const { return &m_afData[0][0]; }
CTransform operator*(const CTransform& cTransform) const;
CVec operator*(const CVec& cVec) const;
CVec3 operator*(const CVec3& cVec3) const;
CRegion operator*(const CRegion& cRegion) const;
CTransform operator+(const CTransform& cTransform) const;
CTransform operator-(const CTransform& cTransform) const;
friend BUILD_VECTOR_SET std::ostream& operator<<(std::ostream& cStream, const CTransform& cTransform);
float m_afData[4][4]; // standard 4 x 4 transform matrix
private:
EInversionCodeType ludcmp(float a[5][5], int n, int *indx, float *d); // taken from numerical recipes
void lubksb(float a[5][5], int n, int *indx, float b[ ]); // taken from numerical recipes
};
///////////////////////////////////////////////////////////////////////
// class CRegion declaration
//
//
// Description: Summary of public interface
//
//
// Construction:
// -------------
// CRegion( ) Builds a CBox and calls Initialize( ).
//
// Variables:
// ----------
// m_cMin Minimum extents vector. Public for OpenGL convenience and fast access.
// m_cMax Maximum extents vector. Public for OpenGL convenience and fast access.
//
// Inspectors:
// -----------
// Dimension(int nAxis) Returns the length of the specified axis (0 = x, 1 = y, 2 = z).
// MidValue(int nAxis) Returns the middle of the specified axis.
// Midpoint( ) Returns the midpoint of the extents.
// LongestExtent( ) Returns the length of the longest axis.
// ShortestExtent( ) Returns the length of the shortest axis.
// AverageExtent( ) Returns the average length of all axes.
// IsSet( ) Returns true when any member of *this does not match the initialized state.
//
//
// Mutators:
// ---------
// Initialize( ) Sets m_cMin to (FLT_MAX, FLT_MAX, FLT_MAX) and m_cMax to -m_cMin. Called automatically by the constructor.
// Scale(float fScale) Scales *this by fScale relative to the origin (NOT the midpoint).
//
// Operators:
// ----------
// operator+(const CRegion& cRegion) Returns a CRegion exactly large enough to include *this and cRegion.
// operator+(const CVec& cVec) Returns a CRegion where cVec is added to m_cMin/m_cMax.
// operator^(const CVec3& cVec) Returns a CRegion where min and max include those of cVec
// operator*(float fScale) Returns a CRegion scaled by fScale relative to the midpoint of *this (NOT the origin).
// operator*(const CTransform& cTransform) Returns a CRegion where m_cMin/m_cMax of *this are multiplied by cTransform.
// operator<(const CRegion& cRegion) Returns true when *this is contained within cRegion (using <= and >=).
// operator<<(ostream& cStream, ...) Outputs *this.
class BUILD_VECTOR_SET CRegion
{
public:
CRegion( );
// inspectors
float Dimension(int nAxis) const { return m_cMax[nAxis] - m_cMin[nAxis]; }
float MidValue(int nAxis) const { return (m_cMax[nAxis] + m_cMin[nAxis]) * 0.5f; }
CVec Midpoint( ) const { return m_cMin.Midpoint(m_cMax); }
float LongestExtent( ) const { return (((m_cMax - m_cMin).AbsoluteValue( )).MaxAxis( )); }
float ShortestExtent( ) const { return (((m_cMax - m_cMin).AbsoluteValue( )).MinAxis( )); }
float AverageExtent( ) const;
bool IsSet( ) const;
bool ContainsPoint2D(const CVec& cVec)
{
return (cVec[0] >= m_cMin[0] &&
cVec[0] <= m_cMax[0] &&
cVec[1] >= m_cMin[1] &&
cVec[1] <= m_cMax[1]);
}
// mutators
void Initialize( );
void Scale(float fScale);
// operators
CRegion operator+(const CRegion& cRegion) const;
CRegion operator+(const CVec& cVec) const;
CRegion operator^(const CVec3& cVec) const;
CRegion operator*(float fScale) const;
CRegion operator*(const CTransform& cTransform) const;
bool operator<(const CRegion& cRegion) const;
friend BUILD_VECTOR_SET std::ostream& operator<<(std::ostream& cStream, const CRegion& cRegion);
CVec m_cMin; // minimum corner of the region (x, y, z)
CVec m_cMax; // maximum corner of the region (x, y, z)
};
///////////////////////////////////////////////////////////////////////
// class CVec3 inlined function definitions
//
// CVec3( )
__forceinline CVec3::CVec3( )
{
m_afData[0] = m_afData[1] = m_afData[2] = 0.0f;
}
// CVec3(float fX, float fY, float fZ)
__forceinline CVec3::CVec3(float fX, float fY, float fZ)
{
m_afData[0] = fX;
m_afData[1] = fY;
m_afData[2] = fZ;
}
// CVec3(float fX, float fY)
__forceinline CVec3::CVec3(float fX, float fY)
{
m_afData[0] = fX;
m_afData[1] = fY;
m_afData[2] = 0.0f;
}
// AbsoluteValue
__forceinline CVec3 CVec3::AbsoluteValue( ) const
{
return CVec3(fabs(m_afData[0]),
fabs(m_afData[1]),
fabs(m_afData[2]));
}
// AngleBetween
__forceinline float CVec3::AngleBetween(const CVec3& cVec) const
{
float fDot = *this ^ cVec;
if (fDot < -1.0f)
fDot = -1.0f;
if (fDot > 1.0f)
fDot = 1.0f;
return acosf(fDot);
}
// Dot
__forceinline float CVec3::Dot(const CVec3& cVec) const
{
return m_afData[0] * cVec.m_afData[0] +
m_afData[1] * cVec.m_afData[1] +
m_afData[2] * cVec.m_afData[2];
}
// Cross
__forceinline CVec3 CVec3::Cross(const CVec3& cVec) const
{
return CVec3(m_afData[1] * cVec.m_afData[2] - m_afData[2] * cVec.m_afData[1],
m_afData[2] * cVec.m_afData[0] - m_afData[0] * cVec.m_afData[2],
m_afData[0] * cVec.m_afData[1] - m_afData[1] * cVec.m_afData[0]);
}
// Distance
__forceinline float CVec3::Distance(const CVec3& cVec) const
{
return _idv_sqrt1(
((cVec.m_afData[0] - m_afData[0]) * (cVec.m_afData[0] - m_afData[0])) +
((cVec.m_afData[1] - m_afData[1]) * (cVec.m_afData[1] - m_afData[1])) +
((cVec.m_afData[2] - m_afData[2]) * (cVec.m_afData[2] - m_afData[2]))
);
}
// Magnitude
__forceinline float CVec3::Magnitude( ) const
{
return _idv_sqrt1(m_afData[0] * m_afData[0] +
m_afData[1] * m_afData[1] +
m_afData[2] * m_afData[2]);
}
// MaxAxis
__forceinline float CVec3::MaxAxis( ) const
{
float fMax(m_afData[0]);
if (m_afData[1] > fMax)
fMax = m_afData[1];
if (m_afData[2] > fMax)
fMax = m_afData[2];
return fMax;
}
// Midpoint
__forceinline CVec3 CVec3::Midpoint(const CVec3& cVec) const
{
return CVec3(0.5f * (cVec.m_afData[0] + m_afData[0]),
0.5f * (cVec.m_afData[1] + m_afData[1]),
0.5f * (cVec.m_afData[2] + m_afData[2]));
}
// MinAxis
__forceinline float CVec3::MinAxis( ) const
{
float fMin(m_afData[0]);
if (m_afData[1] < fMin)
fMin = m_afData[1];
if (m_afData[2] < fMin)
fMin = m_afData[2];
return fMin;
}
// RoughlyEqual
__forceinline bool CVec3::RoughlyEqual(const CVec3& cVec) const
{
return ((fabs(m_afData[0] - cVec.m_afData[0]) > m_fTolerance) &&
(fabs(m_afData[1] - cVec.m_afData[1]) > m_fTolerance) &&
(fabs(m_afData[2] - cVec.m_afData[2]) > m_fTolerance));
}
// ToVec
__forceinline CVec CVec3::ToVec(void) const
{
return CVec(m_afData[0], m_afData[1], m_afData[2]);
}
// Normalize
__forceinline void CVec3::Normalize( )
{
float fSumOfSquares = (m_afData[0] * m_afData[0]) +
(m_afData[1] * m_afData[1]) +
(m_afData[2] * m_afData[2]);
float fInvSquareRoot = 1.0f / sqrtf(fSumOfSquares);
m_afData[0] *= fInvSquareRoot;
m_afData[1] *= fInvSquareRoot;
m_afData[2] *= fInvSquareRoot;
}
// Set(float fX, float fY)
__forceinline void CVec3::Set(float fX, float fY)
{
m_afData[0] = fX;
m_afData[1] = fY;
}
// Set(float fX, float fY. float fZ)
__forceinline void CVec3::Set(float fX, float fY, float fZ)
{
m_afData[0] = fX;
m_afData[1] = fY;
m_afData[2] = fZ;
}
// operator <
__forceinline bool CVec3::operator<(const CVec3& cVec) const
{
if (m_afData[0] < cVec.m_afData[0])
{
return true;
}
else if (m_afData[0] > cVec.m_afData[0])
{
return false;
}
else
{
if (m_afData[1] < cVec.m_afData[1])
return true;
else if (m_afData[1] > cVec.m_afData[1])
return false;
else
return m_afData[2] < cVec.m_afData[2];
}
}
// operator <=
__forceinline bool CVec3::operator<=(const CVec3& cVec) const
{
return (m_afData[0] <= cVec.m_afData[0]);
}
// operator >
__forceinline bool CVec3::operator>(const CVec3& cVec) const
{
if (m_afData[0] > cVec.m_afData[0])
{
return true;
}
else if (m_afData[0] < cVec.m_afData[0])
{
return false;
}
else
{
if (m_afData[1] > cVec.m_afData[1])
return true;
else if (m_afData[1] < cVec.m_afData[1])
return false;
else
return m_afData[2] > cVec.m_afData[2];
}
}
// operator >=
__forceinline bool CVec3::operator>=(const CVec3& cVec) const
{
return (m_afData[0] >= cVec.m_afData[0]);
}
// operator +
__forceinline CVec3 CVec3::operator+(const CVec3& cVec) const
{
return CVec3(m_afData[0] + cVec.m_afData[0],
m_afData[1] + cVec.m_afData[1],
m_afData[2] + cVec.m_afData[2]);
}
// operator +=
__forceinline CVec3& CVec3::operator+=(const CVec3& cVec)
{
m_afData[0] += cVec.m_afData[0];
m_afData[1] += cVec.m_afData[1];
m_afData[2] += cVec.m_afData[2];
return *this;
}
// operator -
__forceinline CVec3 CVec3::operator-(const CVec3& cVec) const
{
return CVec3(m_afData[0] - cVec.m_afData[0],
m_afData[1] - cVec.m_afData[1],
m_afData[2] - cVec.m_afData[2]);
}
// operator +=
__forceinline CVec3& CVec3::operator-=(const CVec3& cVec)
{
m_afData[0] -= cVec.m_afData[0];
m_afData[1] -= cVec.m_afData[1];
m_afData[2] -= cVec.m_afData[2];
return *this;
}
// operator-
__forceinline CVec3 CVec3::operator-( ) const
{
return CVec3(-m_afData[0],
-m_afData[1],
-m_afData[2]);
}
// operator^
__forceinline float CVec3::operator^(const CVec3& cVec) const
{
return m_afData[0] * cVec.m_afData[0] +
m_afData[1] * cVec.m_afData[1] +
m_afData[2] * cVec.m_afData[2];
}
// operator*
__forceinline CVec3 CVec3::operator*(const CVec3& cVec) const
{
return CVec3(m_afData[1] * cVec.m_afData[2] - m_afData[2] * cVec.m_afData[1],
m_afData[2] * cVec.m_afData[0] - m_afData[0] * cVec.m_afData[2],
m_afData[0] * cVec.m_afData[1] - m_afData[1] * cVec.m_afData[0]);
}
// operator*=
__forceinline CVec3& CVec3::operator*=(const CVec3& cVec)
{
float x(m_afData[0]), y(m_afData[1]), z(m_afData[2]);
m_afData[0] = y * cVec.m_afData[2] - z * cVec.m_afData[1];
m_afData[1] = z * cVec.m_afData[0] - x * cVec.m_afData[2];
m_afData[2] = x * cVec.m_afData[1] - y * cVec.m_afData[0];
return *this;
}
// operator*
__forceinline CVec3 CVec3::operator*(float fScale) const
{
return CVec3(m_afData[0] * fScale,
m_afData[1] * fScale,
m_afData[2] * fScale);
}
// operator*=
__forceinline CVec3& CVec3::operator*=(float fScale)
{
m_afData[0] *= fScale;
m_afData[1] *= fScale;
m_afData[2] *= fScale;
return *this;
}
// operator/
__forceinline CVec3 CVec3::operator/(float fScale) const
{
return CVec3(m_afData[0] / fScale,
m_afData[1] / fScale,
m_afData[2] / fScale);
}
// operator/=
__forceinline CVec3& CVec3::operator/=(float fScale)
{
m_afData[0] /= fScale;
m_afData[1] /= fScale;
m_afData[2] /= fScale;
return *this;
}
// operator==
__forceinline bool CVec3::operator==(const CVec3& cVec) const
{
return m_afData[0] == cVec.m_afData[0] &&
m_afData[1] == cVec.m_afData[1] &&
m_afData[2] == cVec.m_afData[2];
}
// operator!=
__forceinline bool CVec3::operator!=(const CVec3& cVec) const
{
return m_afData[0] != cVec.m_afData[0] ||
m_afData[1] != cVec.m_afData[1] ||
m_afData[2] != cVec.m_afData[2];
}
// operator*
__forceinline CVec3 CVec3::operator*(const CTransform& cTransform) const
{
return CVec3(m_afData[0] * cTransform.m_afData[0][0] +
m_afData[1] * cTransform.m_afData[1][0] +
m_afData[2] * cTransform.m_afData[2][0] +
cTransform.m_afData[3][0],
m_afData[0] * cTransform.m_afData[0][1] +
m_afData[1] * cTransform.m_afData[1][1] +
m_afData[2] * cTransform.m_afData[2][1] +
cTransform.m_afData[3][1],
m_afData[0] * cTransform.m_afData[0][2] +
m_afData[1] * cTransform.m_afData[1][2] +
m_afData[2] * cTransform.m_afData[2][2] +
cTransform.m_afData[3][2]);
}
// operator*
__forceinline CVec3 CVec3::operator*(const CRotTransform& cTransform) const
{
return CVec3(m_afData[0] * cTransform.m_afData[0][0] +
m_afData[1] * cTransform.m_afData[1][0] +
m_afData[2] * cTransform.m_afData[2][0],
m_afData[0] * cTransform.m_afData[0][1] +
m_afData[1] * cTransform.m_afData[1][1] +
m_afData[2] * cTransform.m_afData[2][1],
m_afData[0] * cTransform.m_afData[0][2] +
m_afData[1] * cTransform.m_afData[1][2] +
m_afData[2] * cTransform.m_afData[2][2]);
}
// operator<<
__forceinline std::ostream& operator<<(std::ostream& cStream, const CVec3& cVec)
{
cStream << "(" << cVec[0] << " " << cVec[1] << " " << cVec[2] << ")\n";
return cStream;
}
///////////////////////////////////////////////////////////////////////
// class CRotTransform inlined function definitions
//
// CRotTransform
__forceinline CRotTransform::CRotTransform( )
{
m_afData[0][0] = 1.0f;
m_afData[0][1] = 0.0f;
m_afData[0][2] = 0.0f;
m_afData[1][0] = 0.0f;
m_afData[1][1] = 1.0f;
m_afData[1][2] = 0.0f;
m_afData[2][0] = 0.0f;
m_afData[2][1] = 0.0f;
m_afData[2][2] = 1.0f;
}
// Set
__forceinline void CRotTransform::Set(float afData[3][3])
{
m_afData[0][0] = afData[0][0];
m_afData[0][1] = afData[0][1];
m_afData[0][2] = afData[0][2];
m_afData[1][0] = afData[1][0];
m_afData[1][1] = afData[1][1];
m_afData[1][2] = afData[1][2];
m_afData[2][0] = afData[2][0];
m_afData[2][1] = afData[2][1];
m_afData[2][2] = afData[2][2];
}
// LoadIdentity
__forceinline void CRotTransform::LoadIdentity( )
{
m_afData[0][0] = 1.0f;
m_afData[0][1] = 0.0f;
m_afData[0][2] = 0.0f;
m_afData[1][0] = 0.0f;
m_afData[1][1] = 1.0f;
m_afData[1][2] = 0.0f;
m_afData[2][0] = 0.0f;
m_afData[2][1] = 0.0f;
m_afData[2][2] = 1.0f;
}
// operator*
__forceinline CRotTransform CRotTransform::operator*(const CRotTransform& cTrans) const
{
CRotTransform cTemp(true); // don't load identity
cTemp.m_afData[0][0] = m_afData[0][0] * cTrans.m_afData[0][0] +
m_afData[0][1] * cTrans.m_afData[1][0] +
m_afData[0][2] * cTrans.m_afData[2][0];
cTemp.m_afData[0][1] = m_afData[0][0] * cTrans.m_afData[0][1] +
m_afData[0][1] * cTrans.m_afData[1][1] +
m_afData[0][2] * cTrans.m_afData[2][1];
cTemp.m_afData[0][2] = m_afData[0][0] * cTrans.m_afData[0][2] +
m_afData[0][1] * cTrans.m_afData[1][2] +
m_afData[0][2] * cTrans.m_afData[2][2];
cTemp.m_afData[1][0] = m_afData[1][0] * cTrans.m_afData[0][0] +
m_afData[1][1] * cTrans.m_afData[1][0] +
m_afData[1][2] * cTrans.m_afData[2][0];
cTemp.m_afData[1][1] = m_afData[1][0] * cTrans.m_afData[0][1] +
m_afData[1][1] * cTrans.m_afData[1][1] +
m_afData[1][2] * cTrans.m_afData[2][1];
cTemp.m_afData[1][2] = m_afData[1][0] * cTrans.m_afData[0][2] +
m_afData[1][1] * cTrans.m_afData[1][2] +
m_afData[1][2] * cTrans.m_afData[2][2];
cTemp.m_afData[2][0] = m_afData[2][0] * cTrans.m_afData[0][0] +
m_afData[2][1] * cTrans.m_afData[1][0] +
m_afData[2][2] * cTrans.m_afData[2][0];
cTemp.m_afData[2][1] = m_afData[2][0] * cTrans.m_afData[0][1] +
m_afData[2][1] * cTrans.m_afData[1][1] +
m_afData[2][2] * cTrans.m_afData[2][1];
cTemp.m_afData[2][2] = m_afData[2][0] * cTrans.m_afData[0][2] +
m_afData[2][1] * cTrans.m_afData[1][2] +
m_afData[2][2] * cTrans.m_afData[2][2];
return cTemp;
}
// operator*
__forceinline CVec3 CRotTransform::operator*(const CVec3& cVec3) const
{
return CVec3(m_afData[0][0] * cVec3.m_afData[0] +
m_afData[0][1] * cVec3.m_afData[1] +
m_afData[0][2] * cVec3.m_afData[2],
m_afData[1][0] * cVec3.m_afData[0] +
m_afData[1][1] * cVec3.m_afData[1] +
m_afData[1][2] * cVec3.m_afData[2],
m_afData[2][0] * cVec3.m_afData[0] +
m_afData[2][1] * cVec3.m_afData[1] +
m_afData[2][2] * cVec3.m_afData[2]);
}
// RotateX
__forceinline void CRotTransform::RotateX(float fAngle)
{
CRotTransform cRotMatrix(true); // don't load identity
float fCosine = VectorCosD(fAngle);
float fSine = VectorSinD(fAngle);
cRotMatrix.m_afData[0][0] = 1.0f;
cRotMatrix.m_afData[0][1] = 0.0f;
cRotMatrix.m_afData[0][2] = 0.0f;
cRotMatrix.m_afData[1][0] = 0.0f;
cRotMatrix.m_afData[1][1] = fCosine;
cRotMatrix.m_afData[1][2] = fSine;
cRotMatrix.m_afData[2][0] = 0.0f;
cRotMatrix.m_afData[2][1] = -fSine;
cRotMatrix.m_afData[2][2] = fCosine;
// this function can be further optimized by hardcoding
// the multiplication here and removing terms with 0.0 multipliers.
*this = cRotMatrix * *this;
}
// RotateY
__forceinline void CRotTransform::RotateY(float fAngle)
{
CRotTransform cRotMatrix(true); // don't load identity
float fCosine = VectorCosD(fAngle);
float fSine = VectorSinD(fAngle);
cRotMatrix.m_afData[0][0] = fCosine;
cRotMatrix.m_afData[0][1] = 0.0f;
cRotMatrix.m_afData[0][2] = -fSine;
cRotMatrix.m_afData[1][0] = 0.0f;
cRotMatrix.m_afData[1][1] = 1.0f;
cRotMatrix.m_afData[1][2] = 0.0f;
cRotMatrix.m_afData[2][0] = fSine;
cRotMatrix.m_afData[2][1] = 0.0f;
cRotMatrix.m_afData[2][2] = fCosine;
// this function can be further optimized by hardcoding
// the multiplication here and removing terms with 0.0 multipliers.
*this = cRotMatrix * *this;
}
// RotateZ
__forceinline void CRotTransform::RotateZ(float fAngle)
{
CRotTransform cRotMatrix(true); // don't load identity
float fCosine = VectorCosD(fAngle);
float fSine = VectorSinD(fAngle);
cRotMatrix.m_afData[0][0] = fCosine;
cRotMatrix.m_afData[0][1] = fSine;
cRotMatrix.m_afData[0][2] = 0.0f;
cRotMatrix.m_afData[1][0] = -fSine;
cRotMatrix.m_afData[1][1] = fCosine;
cRotMatrix.m_afData[1][2] = 0.0f;
cRotMatrix.m_afData[2][0] = 0.0f;
cRotMatrix.m_afData[2][1] = 0.0f;
cRotMatrix.m_afData[2][2] = 1.0f;
// this function can be further optimized by hardcoding
// the multiplication here and removing terms with 0.0 multipliers.
*this = cRotMatrix * *this;
}
// RotateYZ
__forceinline void CRotTransform::RotateYZ(float fYangle, float fZangle)
{
CRotTransform cRotMatrix(true); // don't load identity
float fCosineY = VectorCosD(fYangle);
float fSineY = VectorSinD(fYangle);
float fCosineZ = VectorCosD(fZangle);
float fSineZ = VectorSinD(fZangle);
cRotMatrix.m_afData[0][0] = fCosineY * fCosineZ;
cRotMatrix.m_afData[0][1] = fCosineY * fSineZ;
cRotMatrix.m_afData[0][2] = -fSineY;
cRotMatrix.m_afData[1][0] = -fSineZ;
cRotMatrix.m_afData[1][1] = fCosineZ;
cRotMatrix.m_afData[1][2] = 0.0f;
cRotMatrix.m_afData[2][0] = fSineY * fCosineZ;
cRotMatrix.m_afData[2][1] = fSineY * fSineZ;
cRotMatrix.m_afData[2][2] = fCosineY;
*this = cRotMatrix * *this;
}
// RotateAxis
__forceinline void CRotTransform::RotateAxis(float fAngle, CVec3 cAxis)
{
CRotTransform cRotMatrix(true); // don't load identity
float s = VectorSinD(fAngle);
float c = VectorCosD(fAngle);
float t = 1.0 - c;
float x = cAxis.m_afData[0];
float y = cAxis.m_afData[1];
float z = cAxis.m_afData[2];
cRotMatrix.m_afData[0][0] = t * x * x + c;
cRotMatrix.m_afData[0][1] = t * x * y + s * z;
cRotMatrix.m_afData[0][2] = t * x * z - s * y;
cRotMatrix.m_afData[1][0] = t * x * y - s * z;
cRotMatrix.m_afData[1][1] = t * y * y + c;
cRotMatrix.m_afData[1][2] = t * y * z + s * x;
cRotMatrix.m_afData[2][0] = t * x * z + s * y;
cRotMatrix.m_afData[2][1] = t * y * z - s * x;
cRotMatrix.m_afData[2][2] = t * z * z + c;
*this = cRotMatrix * *this;
}
// RotateAxisFromIdentity
__forceinline void CRotTransform::RotateAxisFromIdentity(float fAngle, CVec3 cAxis)
{
float s = VectorSinD(fAngle);
float c = VectorCosD(fAngle);
float t = 1.0 - c;
float x = cAxis.m_afData[0];
float y = cAxis.m_afData[1];
float z = cAxis.m_afData[2];
m_afData[0][0] = t * x * x + c;
m_afData[0][1] = t * x * y + s * z;
m_afData[0][2] = t * x * z - s * y;
m_afData[1][0] = t * x * y - s * z;
m_afData[1][1] = t * y * y + c;
m_afData[1][2] = t * y * z + s * x;
m_afData[2][0] = t * x * z + s * y;
m_afData[2][1] = t * y * z - s * x;
m_afData[2][2] = t * z * z + c;
}
///////////////////////////////////////////////////////////////////////
// Global utility function definitions
//
inline float VecRad2Deg(float fRad)
{
return fRad * 57.295779513082320876798154814105f;
}
inline float VecDeg2Rad(float fDeg)
{
return fDeg / 57.295779513082320876798154814105f;
}
inline float VecInterpolate(float fStart, float fEnd, float fPercent)
{
return fStart + (fEnd - fStart) * fPercent;
}
inline CVec VecInterpolate(CVec cStart, CVec cEnd, float fPercent)
{
return cStart + (cEnd - cStart) * fPercent;
}
inline CVec3 VecInterpolate(CVec3 cStart, CVec3 cEnd, float fPercent)
{
return cStart + (cEnd - cStart) * fPercent;
}
inline bool VecRouglyEqual(float fA, float fB, float fTolerance)
{
return fabs(fA - fB) < fTolerance;
}