/* =========================================================================== Copyright (C) 2000 - 2013, Raven Software, Inc. Copyright (C) 2001 - 2013, Activision, Inc. Copyright (C) 2013 - 2015, OpenJK contributors This file is part of the OpenJK source code. OpenJK is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see . =========================================================================== */ //////////////////////////////////////////////////////////////////////////////////////// // RAVEN STANDARD TEMPLATE LIBRARY // (c) 2002 Activision // // // Vector Library // -------------- // The base implimention of the Raven Vector object attempts to solve a number of // high level problems as efficiently as possible. Where ever feasible, functions have // been included in the .h file so the compiler can inline them. // // The vectors define the following operations: // - Construction // - Initialization // - Member Access // - Equality / Inequality Operators // - Arithimitic Operators // - Length & Distance // - Normalization (Standard, Safe, Angular) // - Dot & Cross Product // - Perpendicular Vector // - Truncation // - Min & Max Element Analisis // - Interpolation // - Angle / Vector Conversion // - Translation & Rotation // - Point and Line Intersection Tests // - Left / Right Line Test // - String Operations // - Debug Routines // - "Standard" Vectors As Static Memebers // // As necessary, some projects may #define special faster versions of these routines to // make better use of native hardware / software implimentations. // // // // // NOTES: // 05/29/02 - CREATED // 05/30/02 - RotatePoint() is currently unimplimented. Waiting for Matrix Library // // //////////////////////////////////////////////////////////////////////////////////////// #if !defined(RAVL_VEC_INC) #define RAVL_VEC_INC //namespace ravl //{ template T Min(const T& a, const T& b) {return (a T Max(const T& a, const T& b) {return (b Radians #define RAVL_VEC_RADTODEG( a ) ( (a) * RAVL_VEC_RADTODEGCONST ) // Quick Macro For Radians -> Degrees //////////////////////////////////////////////////////////////////////////////////////// // Enums And Typedefs //////////////////////////////////////////////////////////////////////////////////////// enum ESide { Side_None = 0, Side_Left = 1, Side_Right = 2, Side_In = 3, Side_Out = 4, Side_AllIn = 5 }; //////////////////////////////////////////////////////////////////////////////////////// // The 4 Dimensional Vector //////////////////////////////////////////////////////////////////////////////////////// class CVec4 { public: //////////////////////////////////////////////////////////////////////////////////// // Constructors //////////////////////////////////////////////////////////////////////////////////// #ifndef _DEBUG CVec4() {} #else CVec4() {v[0]=v[1]=v[2]=v[3]=RAVL_VEC_UDF;} // DEBUG INITIALIZATION #endif CVec4(const float val) {v[0]=val; v[1]=val; v[2]=val; v[3]=val;} CVec4(const float x,const float y,const float z, const float r) {v[0]=x; v[1]=y; v[2]=z; v[3]=r;} CVec4(const CVec4& t) {v[0]=t.v[0]; v[1]=t.v[1]; v[2]=t.v[2]; v[3]=t.v[3];} CVec4(const float *t) {v[0]=t[0]; v[1]=t[1]; v[2]=t[2]; v[3]=t[3];} //////////////////////////////////////////////////////////////////////////////////// // Initializers //////////////////////////////////////////////////////////////////////////////////// void Set(const float t) {v[0]=t; v[1]=t; v[2]=t; v[3]=t;} void Set(const float *t) {v[0]=t[0]; v[1]=t[1]; v[2]=t[2]; v[3]=t[3];} void Set(const float x,const float y,const float z, const float r) {v[0]=x; v[1]=y; v[2]=z; v[3]=r;} void Clear() {v[0]=0; v[1]=0; v[2]=0; v[3]=0;} //////////////////////////////////////////////////////////////////////////////////// // Member Accessors //////////////////////////////////////////////////////////////////////////////////// const float& operator[](int i) const {return v[i];} float& operator[](int i) {return v[i];} float& pitch() {return v[0];} float& yaw() {return v[1];} float& roll() {return v[2];} float& radius() {return v[3];} //////////////////////////////////////////////////////////////////////////////////// // Equality / Inequality Operators //////////////////////////////////////////////////////////////////////////////////// bool operator! () const {return !(v[0] && v[1] && v[2] && v[3] );} bool operator== (const CVec4& t) const {return (v[0]==t.v[0] && v[1]==t.v[1] && v[2]==t.v[2] && v[3]==t.v[3]);} bool operator!= (const CVec4& t) const {return !(v[0]==t.v[0] && v[1]==t.v[1] && v[2]==t.v[2] && v[3]==t.v[3]);} bool operator< (const CVec4& t) const {return (v[0]< t.v[0] && v[1]< t.v[1] && v[2]< t.v[2] && v[3]< t.v[3]);} bool operator> (const CVec4& t) const {return (v[0]> t.v[0] && v[1]> t.v[1] && v[2]> t.v[2] && v[3]> t.v[3]);} bool operator<= (const CVec4& t) const {return (v[0]<=t.v[0] && v[1]<=t.v[1] && v[2]<=t.v[2] && v[3]<=t.v[3]);} bool operator>= (const CVec4& t) const {return (v[0]>=t.v[0] && v[1]>=t.v[1] && v[2]>=t.v[2] && v[3]>=t.v[3]);} //////////////////////////////////////////////////////////////////////////////////// // Basic Arithimitic Operators //////////////////////////////////////////////////////////////////////////////////// const CVec4 &operator= (const float d) {v[0]=d; v[1]=d; v[2]=d; v[3]=d; return *this;} const CVec4 &operator= (const CVec4& t) {v[0]=t.v[0]; v[1]=t.v[1]; v[2]=t.v[2]; v[3]=t.v[3]; return *this;} const CVec4 &operator+= (const float d) {v[0]+=d; v[1]+=d; v[2]+=d; v[3]+=d; return *this;} const CVec4 &operator+= (const CVec4& t) {v[0]+=t.v[0]; v[1]+=t.v[1]; v[2]+=t.v[2]; v[3]+=t.v[3];return *this;} const CVec4 &operator-= (const float d) {v[0]-=d; v[1]-=d; v[2]-=d; v[3]-=d; return *this;} const CVec4 &operator-= (const CVec4& t) {v[0]-=t.v[0]; v[1]-=t.v[1]; v[2]-=t.v[2]; v[3]-=t.v[3];return *this;} const CVec4 &operator*= (const float d) {v[0]*=d; v[1]*=d; v[2]*=d; v[3]*=d; return *this;} const CVec4 &operator*= (const CVec4& t) {v[0]*=t.v[0]; v[1]*=t.v[1]; v[2]*=t.v[2]; v[3]*=t.v[3];return *this;} const CVec4 &operator/= (const float d) {v[0]/=d; v[1]/=d; v[2]/=d; v[3]/=d; return *this;} const CVec4 &operator/= (const CVec4& t) {v[0]/=t.v[0]; v[1]/=t.v[1]; v[2]/=t.v[2]; v[3]/=t.v[3];return *this;} inline CVec4 operator+ (const CVec4 &t) const {return CVec4(v[0]+t.v[0], v[1]+t.v[1], v[2]+t.v[2], v[3]+t.v[3]);} inline CVec4 operator- (const CVec4 &t) const {return CVec4(v[0]-t.v[0], v[1]-t.v[1], v[2]-t.v[2], v[3]-t.v[3]);} inline CVec4 operator* (const CVec4 &t) const {return CVec4(v[0]*t.v[0], v[1]*t.v[1], v[2]*t.v[2], v[3]*t.v[3]);} inline CVec4 operator/ (const CVec4 &t) const {return CVec4(v[0]/t.v[0], v[1]/t.v[1], v[2]/t.v[2], v[3]/t.v[3]);} //////////////////////////////////////////////////////////////////////////////////// // Length And Distance Calculations //////////////////////////////////////////////////////////////////////////////////// float Len() const; float Len2() const {return (v[0]*v[0]+v[1]*v[1]+v[2]*v[2]+v[3]*v[3]);} float Dist(const CVec4& t) const; float Dist2(const CVec4& t) const {return ((t.v[0]-v[0])*(t.v[0]-v[0]) + (t.v[1]-v[1])*(t.v[1]-v[1]) + (t.v[2]-v[2])*(t.v[2]-v[2]) + (t.v[3]-v[3])*(t.v[3]-v[3]) );} //////////////////////////////////////////////////////////////////////////////////// // Normalization //////////////////////////////////////////////////////////////////////////////////// float Norm(); float SafeNorm(); void AngleNorm(); //////////////////////////////////////////////////////////////////////////////////// // Dot, Cross & Perpendicular Vector //////////////////////////////////////////////////////////////////////////////////// float Dot(const CVec4& t) const {return (v[0]*t.v[0] + v[1]*t.v[1] + v[2]*t.v[2] + v[3]*t.v[3]);} void Cross(const CVec4& t) { CVec4 temp(*this); v[0] = (temp.v[1]*t.v[2]) - (temp.v[2]*t.v[1]); v[1] = (temp.v[2]*t.v[0]) - (temp.v[0]*t.v[2]); v[2] = (temp.v[0]*t.v[1]) - (temp.v[1]*t.v[0]); v[3] = 0; } void Perp(); //////////////////////////////////////////////////////////////////////////////////// // Truncation & Element Analysis //////////////////////////////////////////////////////////////////////////////////// void Min(const CVec4& t) { if (t.v[0]v[0]) v[0]=t.v[0]; if (t.v[1]>v[1]) v[1]=t.v[1]; if (t.v[2]>v[2]) v[2]=t.v[2]; if (t.v[3]>v[3]) v[3]=t.v[3]; } float MaxElement() const { return v[MaxElementIndex()]; } int MaxElementIndex() const; //////////////////////////////////////////////////////////////////////////////////// // Interpolation //////////////////////////////////////////////////////////////////////////////////// void Interp(const CVec4 &v1, const CVec4 &v2, const float t) { (*this)=v1; (*this)-=v2; (*this)*=t; (*this)+=v2; } void ScaleAdd(const CVec4& t, const float scale) { v[0] += (scale * t.v[0]); v[1] += (scale * t.v[1]); v[2] += (scale * t.v[2]); v[3] += (scale * t.v[3]); } //////////////////////////////////////////////////////////////////////////////////// // Conversion Angle To Vector (Angle In Degrees) //////////////////////////////////////////////////////////////////////////////////// void VecToAng(); void AngToVec(); void AngToVec(CVec4& Right, CVec4& Up); //////////////////////////////////////////////////////////////////////////////////// // Conversion Angle To Vector (Angle In Radians) //////////////////////////////////////////////////////////////////////////////////// void VecToAngRad(); void AngToVecRad(); void AngToVecRad(CVec4& Right, CVec4& Up); //////////////////////////////////////////////////////////////////////////////////// // Conversion Between Radians And Degrees //////////////////////////////////////////////////////////////////////////////////// void ToRadians(); void ToDegrees(); //////////////////////////////////////////////////////////////////////////////////// // Project // // Standard projection function. Take the (this) and project it onto the vector // (U). Imagine drawing a line perpendicular to U from the endpoint of the (this) // Vector. That then becomes the new vector. // // The value returned is the scale of the new vector with respect to the one passed // to the function. If the scale is less than (1.0) then the new vector is shorter // than (U). If the scale is negative, then the vector is going in the opposite // direction of (U). // // _ (U) // /| // / _ (this) // / RESULTS-> /| // / / // / __\ (this) / // /___--- / / // //////////////////////////////////////////////////////////////////////////////////// float Project(const CVec4 &U) { float Scale = (Dot(U) / U.Len2()); // Find the scale of this vector on U (*this)=U; // Copy U onto this vector (*this)*=Scale; // Use the previously calculated scale to get the right length. return Scale; } //////////////////////////////////////////////////////////////////////////////////// // Project To Line // // This function takes two other points in space as the start and end of a line // segment and projects the (this) point onto the line defined by (Start)->(Stop) // // RETURN VALUES: // (-INF, 0.0) : (this) landed on the line before (Start) // (0.0, 1.0) : (this) landed in the line segment between (Start) and (Stop) // (1.0, INF) : (this) landed on the line beyond (End) // // (Stop) // / // / // o _ // / |\ // / (this) // / // (Start) // //////////////////////////////////////////////////////////////////////////////////// float ProjectToLine(const CVec4 &Start, const CVec4 &Stop) { (*this) -= Start; float Scale = Project(Stop - Start); (*this) += Start; return Scale; } //////////////////////////////////////////////////////////////////////////////////// // Project To Line Seg // // Same As Project To Line, Except It Will Clamp To Start And Stop //////////////////////////////////////////////////////////////////////////////////// float ProjectToLineSeg(const CVec4 &Start, const CVec4 &Stop) { float Scale = ProjectToLine(Start, Stop); if (Scale<0.0f) { (*this) = Start; } else if (Scale>1.0f) { (*this) = Stop; } return Scale; } //////////////////////////////////////////////////////////////////////////////////// // Distance To Line // // Uses project to line and than calculates distance to the new point //////////////////////////////////////////////////////////////////////////////////// float DistToLine(const CVec4 &Start, const CVec4 &Stop) const { CVec4 P(*this); P.ProjectToLineSeg(Start, Stop); return Dist(P); } //////////////////////////////////////////////////////////////////////////////////// // Distance To Line // // Uses project to line and than calculates distance to the new point //////////////////////////////////////////////////////////////////////////////////// float DistToLine2(const CVec4 &Start, const CVec4 &Stop) const { CVec4 P(*this); P.ProjectToLineSeg(Start, Stop); return Dist2(P); } //////////////////////////////////////////////////////////////////////////////////// // Translation & Rotation (2D) //////////////////////////////////////////////////////////////////////////////////// void RotatePoint(const CVec4 &Angle, const CVec4 &Origin); void Reposition(const CVec4 &Translation, float RotationDegrees=0.0); //////////////////////////////////////////////////////////////////////////////////// // Area Of The Parallel Pipid (2D) // // Given two more points, this function calculates the area of the parallel pipid // formed. // // Note: This function CAN return a negative "area" if (this) is above or right of // (A) and (B)... We do not take the abs because the sign of the "area" is needed // for the left right test (see below) // // // ___---( ... ) // (A)---/ / // / / // / / // / / // / ___---(B) // (this)---/ // //////////////////////////////////////////////////////////////////////////////////// float AreaParallelPipid(const CVec4 &A, const CVec4 &B) const { return ((A.v[0]*B.v[1] - A.v[1]*B.v[0]) + (B.v[0]* v[1] - v[0]*B.v[1]) + ( v[0]*A.v[1] - A.v[0]* v[1])); } //////////////////////////////////////////////////////////////////////////////////// // Area Of The Triangle (2D) // // Given two more points, this function calculates the area of the triangle formed. // // (A) // / \__ // / \__ // / \_ // / ___---(B) // (this)---/ // //////////////////////////////////////////////////////////////////////////////////// float AreaTriange(const CVec4 &A, const CVec4 &B) const { return (AreaParallelPipid(A, B) * 0.5f); } //////////////////////////////////////////////////////////////////////////////////// // The Left Right Test (2D) // // Given a line segment (Start->End) and a tolerance for *right on*, this function // evaluates which side the point is of the line. (Side_Left in this example) // // // // (this) ___---/(End) // ___---/ // ___---/ // (Start)/ // //////////////////////////////////////////////////////////////////////////////////// ESide LRTest(const CVec4 &Start, const CVec4 &End, float Tolerance=0.0) const { float Area = AreaParallelPipid(Start, End); if (Area>Tolerance) { return Side_Left; } if (Area<(Tolerance*-1)) { return Side_Right; } return Side_None; } //////////////////////////////////////////////////////////////////////////////////// // Point In Circumscribed Circle (True/False) // // Returns true if the given point is within the circumscribed // circle of the given ABC Triangle: // _____ // / B \ // / / \ \ // | / \ | // |A---------C| // \ Pt / // \_______/ // //////////////////////////////////////////////////////////////////////////////////// bool PtInCircle(const CVec4 &A, const CVec4 &B, const CVec4 &C) const; //////////////////////////////////////////////////////////////////////////////////// // Point In Standard Circle (True/False) // // Returns true if the given point is within the Circle // _____ // / \ // / \ // | Circle | // | | // \ Pt / // \_______/ // //////////////////////////////////////////////////////////////////////////////////// bool PtInCircle(const CVec4 &Circle, float Radius) const; //////////////////////////////////////////////////////////////////////////////////// // Line Intersects Circle (True/False) // // r - Radius Of The Circle // A - Start Of Line Segment // B - End Of Line Segment // // P - Projected Position Of Origin Onto Line AB // // // (Stop) // / // / // (P) // / \ \ // / (this)-r->| // / / // (Start) // //////////////////////////////////////////////////////////////////////////////////// bool LineInCircle(const CVec4 &Start, const CVec4 &Stop, float Radius); bool LineInCircle(const CVec4 &Start, const CVec4 &Stop, float Radius, CVec4 &PointOnLine); //////////////////////////////////////////////////////////////////////////////////// // String Operations //////////////////////////////////////////////////////////////////////////////////// void FromStr(const char *s); void ToStr(char* s) const; //////////////////////////////////////////////////////////////////////////////////// // Debug Routines //////////////////////////////////////////////////////////////////////////////////// #ifdef _DEBUG bool IsFinite(); bool IsInitialized(); #endif //////////////////////////////////////////////////////////////////////////////////// // Data //////////////////////////////////////////////////////////////////////////////////// private: float v[4]; public: static const CVec4 mX; static const CVec4 mY; static const CVec4 mZ; static const CVec4 mW; static const CVec4 mZero; }; //////////////////////////////////////////////////////////////////////////////////////// // The 3 Dimensional Vector //////////////////////////////////////////////////////////////////////////////////////// class CVec3 { public: //////////////////////////////////////////////////////////////////////////////////// // Constructors //////////////////////////////////////////////////////////////////////////////////// #ifndef _DEBUG CVec3() {} #else CVec3() {v[0]=v[1]=v[2]=RAVL_VEC_UDF;} // DEBUG INITIALIZATION #endif CVec3(const float val) {v[0]=val; v[1]=val; v[2]=val; } CVec3(const float x,const float y,const float z) {v[0]=x; v[1]=y; v[2]=z; } CVec3(const CVec3& t) {v[0]=t.v[0]; v[1]=t.v[1]; v[2]=t.v[2];} CVec3(const float *t) {v[0]=t[0]; v[1]=t[1]; v[2]=t[2]; } float x() const {return v[0];} float y() const {return v[1];} float z() const {return v[2];} //////////////////////////////////////////////////////////////////////////////////// // Initializers //////////////////////////////////////////////////////////////////////////////////// void Set(const float t) {v[0]=t; v[1]=t; v[2]=t; } void Set(const float *t) {v[0]=t[0]; v[1]=t[1]; v[2]=t[2]; } void Set(const float x,const float y,const float z) {v[0]=x; v[1]=y; v[2]=z; } void Clear() {v[0]=0; v[1]=0; v[2]=0; } //////////////////////////////////////////////////////////////////////////////////// // Member Accessors //////////////////////////////////////////////////////////////////////////////////// const float& operator[](int i) const {return v[i];} float& operator[](int i) {return v[i];} float& pitch() {return v[0];} float& yaw() {return v[1];} float& roll() {return v[2];} //////////////////////////////////////////////////////////////////////////////////// // Equality / Inequality Operators //////////////////////////////////////////////////////////////////////////////////// bool operator! () const {return !(v[0] && v[1] && v[2] );} bool operator== (const CVec3& t) const {return (v[0]==t.v[0] && v[1]==t.v[1] && v[2]==t.v[2]);} bool operator!= (const CVec3& t) const {return !(v[0]==t.v[0] && v[1]==t.v[1] && v[2]==t.v[2]);} bool operator< (const CVec3& t) const {return (v[0]< t.v[0] && v[1]< t.v[1] && v[2]< t.v[2]);} bool operator> (const CVec3& t) const {return (v[0]> t.v[0] && v[1]> t.v[1] && v[2]> t.v[2]);} bool operator<= (const CVec3& t) const {return (v[0]<=t.v[0] && v[1]<=t.v[1] && v[2]<=t.v[2]);} bool operator>= (const CVec3& t) const {return (v[0]>=t.v[0] && v[1]>=t.v[1] && v[2]>=t.v[2]);} //////////////////////////////////////////////////////////////////////////////////// // Basic Arithimitic Operators //////////////////////////////////////////////////////////////////////////////////// const CVec3 &operator= (const float d) {v[0]=d; v[1]=d; v[2]=d; return *this;} const CVec3 &operator= (const CVec3& t) {v[0]=t.v[0]; v[1]=t.v[1]; v[2]=t.v[2]; return *this;} const CVec3 &operator+= (const float d) {v[0]+=d; v[1]+=d; v[2]+=d; return *this;} const CVec3 &operator+= (const CVec3& t) {v[0]+=t.v[0]; v[1]+=t.v[1]; v[2]+=t.v[2];return *this;} const CVec3 &operator-= (const float d) {v[0]-=d; v[1]-=d; v[2]-=d; return *this;} const CVec3 &operator-= (const CVec3& t) {v[0]-=t.v[0]; v[1]-=t.v[1]; v[2]-=t.v[2];return *this;} const CVec3 &operator*= (const float d) {v[0]*=d; v[1]*=d; v[2]*=d; return *this;} const CVec3 &operator*= (const CVec3& t) {v[0]*=t.v[0]; v[1]*=t.v[1]; v[2]*=t.v[2];return *this;} const CVec3 &operator/= (const float d) {v[0]/=d; v[1]/=d; v[2]/=d; return *this;} const CVec3 &operator/= (const CVec3& t) {v[0]/=t.v[0]; v[1]/=t.v[1]; v[2]/=t.v[2];return *this;} inline CVec3 operator+ (const CVec3 &t) const {return CVec3(v[0]+t.v[0], v[1]+t.v[1], v[2]+t.v[2]);} inline CVec3 operator- (const CVec3 &t) const {return CVec3(v[0]-t.v[0], v[1]-t.v[1], v[2]-t.v[2]);} inline CVec3 operator* (const CVec3 &t) const {return CVec3(v[0]*t.v[0], v[1]*t.v[1], v[2]*t.v[2]);} inline CVec3 operator/ (const CVec3 &t) const {return CVec3(v[0]/t.v[0], v[1]/t.v[1], v[2]/t.v[2]);} //////////////////////////////////////////////////////////////////////////////////// // Length And Distance Calculations //////////////////////////////////////////////////////////////////////////////////// float Len() const; float Len2() const {return (v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);} float Dist(const CVec3& t) const; float Dist2(const CVec3& t) const {return ((t.v[0]-v[0])*(t.v[0]-v[0]) + (t.v[1]-v[1])*(t.v[1]-v[1]) + (t.v[2]-v[2])*(t.v[2]-v[2]));} //////////////////////////////////////////////////////////////////////////////////// // Normalization //////////////////////////////////////////////////////////////////////////////////// float Norm(); float SafeNorm(); void AngleNorm(); float Truncate(float maxlen); //////////////////////////////////////////////////////////////////////////////////// // Dot, Cross & Perpendicular Vector //////////////////////////////////////////////////////////////////////////////////// float Dot(const CVec3& t) const {return (v[0]*t.v[0] + v[1]*t.v[1] + v[2]*t.v[2]);} void Cross(const CVec3& t) { CVec3 temp(*this); v[0] = (temp.v[1]*t.v[2]) - (temp.v[2]*t.v[1]); v[1] = (temp.v[2]*t.v[0]) - (temp.v[0]*t.v[2]); v[2] = (temp.v[0]*t.v[1]) - (temp.v[1]*t.v[0]); } void Perp(); //////////////////////////////////////////////////////////////////////////////////// // Truncation & Element Analysis //////////////////////////////////////////////////////////////////////////////////// void Min(const CVec3& t) { if (t.v[0]v[0]) v[0]=t.v[0]; if (t.v[1]>v[1]) v[1]=t.v[1]; if (t.v[2]>v[2]) v[2]=t.v[2]; } float MaxElement() const { return v[MaxElementIndex()]; } int MaxElementIndex() const; //////////////////////////////////////////////////////////////////////////////////// // Interpolation //////////////////////////////////////////////////////////////////////////////////// void Interp(const CVec3 &v1, const CVec3 &v2, const float t) { (*this)=v1; (*this)-=v2; (*this)*=t; (*this)+=v2; } void ScaleAdd(const CVec3& t, const float scale) { v[0] += (scale * t.v[0]); v[1] += (scale * t.v[1]); v[2] += (scale * t.v[2]); } //////////////////////////////////////////////////////////////////////////////////// // Conversion Angle To Vector (Angle In Degrees) //////////////////////////////////////////////////////////////////////////////////// void VecToAng(); void AngToVec(); void AngToVec(CVec3& Right, CVec3& Up); //////////////////////////////////////////////////////////////////////////////////// // Conversion Angle To Vector (Angle In Radians) //////////////////////////////////////////////////////////////////////////////////// void VecToAngRad(); void AngToVecRad(); void AngToVecRad(CVec3& Right, CVec3& Up); //////////////////////////////////////////////////////////////////////////////////// // Conversion Between Radians And Degrees //////////////////////////////////////////////////////////////////////////////////// void ToRadians(); void ToDegrees(); //////////////////////////////////////////////////////////////////////////////////// // Project // // Standard projection function. Take the (this) and project it onto the vector // (U). Imagine drawing a line perpendicular to U from the endpoint of the (this) // Vector. That then becomes the new vector. // // The value returned is the scale of the new vector with respect to the one passed // to the function. If the scale is less than (1.0) then the new vector is shorter // than (U). If the scale is negative, then the vector is going in the opposite // direction of (U). // // _ (U) // /| // / _ (this) // / RESULTS-> /| // / / // / __\ (this) / // /___--- / / // //////////////////////////////////////////////////////////////////////////////////// float Project(const CVec3 &U) { float Scale = (Dot(U) / U.Len2()); // Find the scale of this vector on U (*this)=U; // Copy U onto this vector (*this)*=Scale; // Use the previously calculated scale to get the right length. return Scale; } //////////////////////////////////////////////////////////////////////////////////// // Project To Line // // This function takes two other points in space as the start and end of a line // segment and projects the (this) point onto the line defined by (Start)->(Stop) // // RETURN VALUES: // (-INF, 0.0) : (this) landed on the line before (Start) // (0.0, 1.0) : (this) landed in the line segment between (Start) and (Stop) // (1.0, INF) : (this) landed on the line beyond (End) // // (Stop) // / // / // o _ // / |\ // / (this) // / // (Start) // //////////////////////////////////////////////////////////////////////////////////// float ProjectToLine(const CVec3 &Start, const CVec3 &Stop) { (*this) -= Start; float Scale = Project(Stop - Start); (*this) += Start; return Scale; } //////////////////////////////////////////////////////////////////////////////////// // Project To Line Seg // // Same As Project To Line, Except It Will Clamp To Start And Stop //////////////////////////////////////////////////////////////////////////////////// float ProjectToLineSeg(const CVec3 &Start, const CVec3 &Stop) { float Scale = ProjectToLine(Start, Stop); if (Scale<0.0f) { (*this) = Start; } else if (Scale>1.0f) { (*this) = Stop; } return Scale; } //////////////////////////////////////////////////////////////////////////////////// // Distance To Line // // Uses project to line and than calculates distance to the new point //////////////////////////////////////////////////////////////////////////////////// float DistToLine(const CVec3 &Start, const CVec3 &Stop) const { CVec3 P(*this); P.ProjectToLineSeg(Start, Stop); return Dist(P); } //////////////////////////////////////////////////////////////////////////////////// // Distance To Line // // Uses project to line and than calculates distance to the new point //////////////////////////////////////////////////////////////////////////////////// float DistToLine2(const CVec3 &Start, const CVec3 &Stop) const { CVec3 P(*this); P.ProjectToLineSeg(Start, Stop); return Dist2(P); } //////////////////////////////////////////////////////////////////////////////////// // Translation & Rotation (2D) //////////////////////////////////////////////////////////////////////////////////// void RotatePoint(const CVec3 &Angle, const CVec3 &Origin); void Reposition(const CVec3 &Translation, float RotationDegrees=0.0); //////////////////////////////////////////////////////////////////////////////////// // Area Of The Parallel Pipid (2D) // // Given two more points, this function calculates the area of the parallel pipid // formed. // // Note: This function CAN return a negative "area" if (this) is above or right of // (A) and (B)... We do not take the abs because the sign of the "area" is needed // for the left right test (see below) // // // ___---( ... ) // (A)---/ / // / / // / / // / / // / ___---(B) // (this)---/ // //////////////////////////////////////////////////////////////////////////////////// float AreaParallelPipid(const CVec3 &A, const CVec3 &B) const { return ((A.v[0]*B.v[1] - A.v[1]*B.v[0]) + (B.v[0]* v[1] - v[0]*B.v[1]) + ( v[0]*A.v[1] - A.v[0]* v[1])); } //////////////////////////////////////////////////////////////////////////////////// // Area Of The Triangle (2D) // // Given two more points, this function calculates the area of the triangle formed. // // (A) // / \__ // / \__ // / \_ // / ___---(B) // (this)---/ // //////////////////////////////////////////////////////////////////////////////////// float AreaTriange(const CVec3 &A, const CVec3 &B) const { return (AreaParallelPipid(A, B) * 0.5f); } //////////////////////////////////////////////////////////////////////////////////// // The Left Right Test (2D) // // Given a line segment (Start->End) and a tolerance for *right on*, this function // evaluates which side the point is of the line. (Side_Left in this example) // // // // (this) ___---/(End) // ___---/ // ___---/ // (Start)/ // //////////////////////////////////////////////////////////////////////////////////// ESide LRTest(const CVec3 &Start, const CVec3 &End, float Tolerance=0.0) const { float Area = AreaParallelPipid(Start, End); if (Area>Tolerance) { return Side_Left; } if (Area<(Tolerance*-1)) { return Side_Right; } return Side_None; } //////////////////////////////////////////////////////////////////////////////////// // Point In Circumscribed Circle (True/False) // // Returns true if the given point is within the circumscribed // circle of the given ABC Triangle: // _____ // / B \ // / / \ \ // | / \ | // |A---------C| // \ Pt / // \_______/ // //////////////////////////////////////////////////////////////////////////////////// bool PtInCircle(const CVec3 &A, const CVec3 &B, const CVec3 &C) const; //////////////////////////////////////////////////////////////////////////////////// // Point In Standard Circle (True/False) // // Returns true if the given point is within the Circle // _____ // / \ // / \ // | Circle | // | | // \ Pt / // \_______/ // //////////////////////////////////////////////////////////////////////////////////// bool PtInCircle(const CVec3 &Circle, float Radius) const; //////////////////////////////////////////////////////////////////////////////////// // Line Intersects Circle (True/False) // // r - Radius Of The Circle // A - Start Of Line Segment // B - End Of Line Segment // // P - Projected Position Of Origin Onto Line AB // // // (Stop) // / // / // (P) // / \ \ // / (this)-r->| // / / // (Start) // //////////////////////////////////////////////////////////////////////////////////// bool LineInCircle(const CVec3 &Start, const CVec3 &Stop, float Radius); bool LineInCircle(const CVec3 &Start, const CVec3 &Stop, float Radius, CVec3 &PointOnLine); //////////////////////////////////////////////////////////////////////////////////// // String Operations //////////////////////////////////////////////////////////////////////////////////// void FromStr(const char *s); void ToStr(char* s) const; //////////////////////////////////////////////////////////////////////////////////// // Debug Routines //////////////////////////////////////////////////////////////////////////////////// #ifdef _DEBUG bool IsFinite(); bool IsInitialized(); #endif //////////////////////////////////////////////////////////////////////////////////// // Data //////////////////////////////////////////////////////////////////////////////////// public: float v[3]; static const CVec3 mX; static const CVec3 mY; static const CVec3 mZ; static const CVec3 mZero; }; //}; #endif