//------------------------------------------------------------------- // SVector.h - A vector math library. // By: Aaron Hilton (c) 1/21/98 //------------------------------------------------------------------- #ifndef __SVECTOR_H_ #define __SVECTOR_H_ #include //------------------------------------------------------------------- // Pseudo-constantes: #define PI 3.14159265359f #define EPSILON 1e-8 #define ZERO EPSILON #define M_1_MAXINT 4.65661287524579692410E-10 //---> 1/(2^31-1) 1/meu maxint 32bits #define M_1_255 (1.0 / 255.0) #define M_1_65535 (1.0 / 65535.0) #define M_1_65500 (1.0 / 65500.0) // 3DFX Glide requires triangles to snap its coordinates to this precision. #define SNAP_BIAS (float)(1<<19) //------------------------------------------- // Forward declaration. // Actual Vector struct. class SVector3D { public: SVector3D () { }; SVector3D (float tx, float ty, float tz) { x = tx; y = ty; z = tz; w = 1.f; } SVector3D (float tx, float ty, float tz, float tw) { x = tx; y = ty; z = tz; w = tw; } union { float x; // Coorinate float nx; // Normal }; union { float y; float ny; }; union { float z; float nz; }; float w; // This coordinate is only used for the final transformation process. Not used by any of the vector methods. //------------------------------------------- // General utility functions. void Print (char *s = 0); // Prints the vector's coordinates to the "stderr" stream. void Rand (); // Randomly generates a new vector. inline float DotProduct (const SVector3D & other) const; // DotProduct of this vector into the other vector. inline void CrossProduct (const SVector3D & a, const SVector3D & b); // Calculates the cross product of "a" and "b", then storing it in this vector. inline float Length (); // Returns the length of this vector. inline float Length2 (); // Returns the squared length of this vector. //------------------------------------------- // Results of these opperations are contained in "this" vector by default. inline float Normalize (); // Normalizes this vector, and returns the scalar value used to normalize the vector. inline void Zero (); // Reset variables to a normal zero constant. (w = 1.f) inline void Scale (float s); // Scale this vector by "s". inline void Add (const SVector3D & other); // Add the other vector to this vector. inline void Subtract (const SVector3D & other); // Subtract the other vector from this vector. (result is contained in this vector.) inline void Combine (const SVector3D & other, float s = 1.f); // Combine vectors with a scalar quantity. inline void Lerp (const SVector3D & a, const SVector3D & b, float fPercent); // Linear interpolate inline void LerpW (const SVector3D & a, const SVector3D & b, float fPercent); // Linear interpolate with W inline void RotV (const SVector3D & e, const SVector3D & p); // Rotate this vector to the normal of e. inline void GetAngles (float &fPan, float &fPitch); // Retrieve the angles of this vector. // Assignment opperator. const SVector3D & operator= (const SVector3D & point) { x = point.x; y = point.y; z = point.z; w = point.w; return *this; } // Math opperations. // Unary. friend SVector3D operator+ (const SVector3D & ptSrc1, const SVector3D & ptSrc2); friend SVector3D operator- (const SVector3D & ptSrc1, const SVector3D & ptSrc2); // Binary. const SVector3D & operator+= (const SVector3D & ptSrc) { Add (ptSrc); return *this; } const SVector3D & operator-= (const SVector3D & ptSrc) { Subtract (ptSrc); return *this; } //------------------------------------------- // Matrix transformation process. // void Transform( const SVector3D &v, const SMatrix &a ); }; //------------------------------------------------------------------------ // Inline implementation. //------------------------------------------- // General utility functions. // DotProduct of this vector into the other vector. float SVector3D::DotProduct (const SVector3D & other) const { return (x * other.x + y * other.y + z * other.z); } // Calculates the cross product of "a" and "b", then storing it in this vector. void SVector3D::CrossProduct (const SVector3D & a, const SVector3D & b) { x = a.y * b.z - b.y * a.z; y = b.x * a.z - a.x * b.z; z = a.x * b.y - b.x * a.y; } // Returns the length of this vector. float SVector3D::Length () { return (float)sqrt (x * x + y * y + z * z); } // Returns the squared length of this vector. float SVector3D::Length2 () { return (float)(x * x + y * y + z * z); } //------------------------------------------------------------------------ // Results of these opperations are contained in "this" vector by default. //------------------------------------------- // Normalizes this vector, and returns the scalar value used to normalize the vector. float SVector3D::Normalize () { float n, nn; nn = x * x + y * y + z * z; if (nn < ZERO) return 0.0f; nn = (float)sqrt (nn); n = 1.0f / nn; x *= n; y *= n; z *= n; return nn; } void SVector3D::Zero () { x = y = z = 0.f; w = 1.f; } // Scale this vector by "s". void SVector3D::Scale (float s) { x *= s; y *= s; z *= s; } // Add the other vector to this vector. void SVector3D::Add (const SVector3D & other) { x += other.x; y += other.y; z += other.z; } // Subtract the other vector from this vector. void SVector3D::Subtract (const SVector3D & other) { x -= other.x; y -= other.y; z -= other.z; } // Combine vectors with a scalar quantity. void SVector3D::Combine (const SVector3D & other, float s) { x += s * other.x; y += s * other.y; z += s * other.z; } // Linear interpolate void SVector3D::Lerp (const SVector3D & a, const SVector3D & b, float fPercent) { x = a.x * (1.f - fPercent) + b.x * fPercent; y = a.y * (1.f - fPercent) + b.y * fPercent; z = a.z * (1.f - fPercent) + b.z * fPercent; } // Linear interpolate with W void SVector3D::LerpW (const SVector3D & a, const SVector3D & b, float fPercent) { x = a.x * (1.f - fPercent) + b.x * fPercent; y = a.y * (1.f - fPercent) + b.y * fPercent; z = a.z * (1.f - fPercent) + b.z * fPercent; w = a.w * (1.f - fPercent) + b.w * fPercent; } // Rotate a quaternion vector ("p") around a normal ("e"). void SVector3D::RotV (const SVector3D & e, const SVector3D & p) { float m = (float)sqrt (p.y * p.y + p.z * p.z); float im = 1.0f / m; x = m * e.x + p.x * e.z; y = (-p.x * p.y * e.x + p.z * e.y) * im + p.y * e.z; z = (-p.x * p.z * e.x - p.y * e.y) * im + p.z * e.z; } // Retrieve the angles of this vector. void SVector3D::GetAngles (float &fPan, float &fPitch) { // fPan = -(float)atan2( x, z ); // fPitch = 0;//(float)atan2( sin(fPan)*z + cos(fPan)*x, y); double dx, dy, dz; dx = (double)x; dy = (double)y; dz = (double)z; if (dz > 0.0001f) { fPan = (float)-atan (dx / dz); dz /= cos ((double)fPan); fPitch = (float)atan (dy / dz); } else if (dz < -0.0001f) { fPan = (float)(PI - atan (dx / dz)); dz /= cos ((double)fPan - PI); fPitch = (float)-atan (dy / dz); } else { fPan = 0.0; fPitch = (float)-PI / 2.f; } } // Math opperations. inline SVector3D operator+ (const SVector3D & ptSrc1, const SVector3D & ptSrc2) { SVector3D ptTmp (ptSrc1); ptTmp.Add (ptSrc2); return ptTmp; } inline SVector3D operator- (const SVector3D & ptSrc1, const SVector3D & ptSrc2) { SVector3D ptTmp (ptSrc1); ptTmp.Subtract (ptSrc2); return ptTmp; } //------------------------------------------------------------------- // Extra tidbits... //------------------------------------------- // Calculates the equation of "b" to the power of "e". int IPower (int b, int e); inline float operator* (const SVector3D & a, const SVector3D & b) { return a.DotProduct (b); } inline SVector3D operator* (const SVector3D & a, float b) { return SVector3D (a.x * b, a.y * b, a.z * b); } inline SVector3D & operator*= (SVector3D & a, float b) { a.Scale (b); return a; } inline SVector3D operator^ (const SVector3D & a, const SVector3D & b) { SVector3D c; c.CrossProduct (a, b); return c; } class SMatrix3D { public: SVector3D x, y, z; SMatrix3D ():x (1, 0, 0), y (0, 1, 0), z (0, 0, 1) { } void FromAngle (float ax, float ay, float az) { float cx = (float)cos (ax); float sx = (float)sin (ax); float cy = (float)cos (ay); float sy = (float)sin (ay); float cz = (float)cos (az); float sz = (float)sin (az); // Calcul de la matrice de transformation 3D x.x = cy * cz; x.y = cx * sz * cy + sx * sy; x.z = sx * sz * cy - cx * sy; y.x = -sz; y.y = cx * cz; y.z = sx * cz; z.x = cz * sy; z.y = cx * sz * sy - sx * cy; z.z = sx * sz * sy + cx * cy; } void Apply (const SVector3D & v, SVector3D * out) { out->x = v * x; out->y = v * y; out->z = v * z; } void RApply (SVector3D const &v, SVector3D * out) { out->x = v.x * x.x + v.y * y.x + v.z * z.x; out->y = v.x * x.y + v.y * y.y + v.z * z.y; out->z = v.x * x.z + v.y * y.z + v.z * z.z; } void Apply (SVector3D * v) { SVector3D i (*v); Apply (i, v); } void RApply (SVector3D * v) { SVector3D i (*v); RApply (i, v); } }; #endif // __SVECTOR_H_