1229 lines
49 KiB
C++
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;
|
|
}
|
|
|