/* ======================================================================= cs171CommonVec.H: common vector-oriented stuff for CS 171A Based on the code written at Cornell University by Jim Arvo and adapted for the PCGV framework at Cornell University by James Durkin, Gordon Kindlmann and Philip Hubbard. ======================================================================= */ #ifndef cs171CommonVecHasBeenIncluded #define cs171CommonVecHasBeenIncluded #include #include /* #include "cs171CommonGen.h" The SGIs need a special include to get isnand(). Note that the SGIs must use isnand() instead of isnan(), because the only way to get isnan() is to define _XOPEN_SOURCE, but defining this symbol explicitly hides drand48(). Sigh. #ifdef sgi #include #define isnan isnand #endif */ /* Classes =============================================================== */ /* Forward references. */ class cs171Vec3; /* A class for a 3-element vector. Note that this vector has no explicit homogoneous coordinate, W. */ class cs171Vec3 { protected: double e[3]; public: /* Constructors. */ cs171Vec3(double c = 0.0) { e[0] = c; e[1] = c; e[2] = c;} cs171Vec3(double x, double y, double z) { e[0] = x; e[1] = y; e[2] = z;} cs171Vec3(double* arr) { e[0] = arr[0]; e[1] = arr[1]; e[2] = arr[2];} // make vector of array cs171Vec3(const cs171Vec3 &A) { e[0] = A[0]; e[1] = A[1]; e[2] = A[2];} ~cs171Vec3() { } /* Access the elements of the vector. */ double x() const { return e[0]; } double y() const { return e[1]; } double z() const { return e[2]; } double & x() { return e[0]; } double & y() { return e[1]; } double & z() { return e[2]; } double operator[](int i) const { return e[i]; } double & operator[](int i) { return e[i]; } double * array() { return &e[0]; } // represent vector as array /* Assignment. */ void operator=(double c) { e[0] = c; e[1] = c; e[2] = c;} void operator=(const cs171Vec3 &A) { e[0] = A[0]; e[1] = A[1]; e[2] = A[2];} /* Return length-related quantities. */ double len_sqr() const { return e[0]*e[0] + e[1]*e[1] + e[2]*e[2];} double len() const { return sqrt(e[0]*e[0] + e[1]*e[1] + e[2]*e[2]);} /* Calling v.normalize() modifies v so it has unit length, and returns the old length of v. */ double normalize(); }; /* Inlined functions ===================================================== */ /* cs171Vec3 operators --------------------------------------------------- */ /* Return TRUE if the vector, A, has the scalar, x, in all its elements. */ inline int operator==(const cs171Vec3 &A, double x) { return (A[0] == x) && (A[1] == x) && (A[2] == x); } /* Return TRUE if the vectors, A and B, are exactly equal. Note that this routine does not use cs171EpsEq() to handle imprecise floating-point arithmetic. */ inline int operator==(const cs171Vec3 &A, const cs171Vec3 &B) { return (A[0] == B[0]) && (A[1] == B[1]) && (A[2] == B[2]); } /* Return a new vector that is the sum of the vectors, A and B. */ inline cs171Vec3 operator+(const cs171Vec3 &A, const cs171Vec3 &B) { return cs171Vec3(A.x() + B.x(), A.y() + B.y(), A.z() + B.z()); } /* Add the vector, B, onto the vector, A. */ inline cs171Vec3& operator+=(cs171Vec3 &A, const cs171Vec3 &B) { A.x() += B.x(); A.y() += B.y(); A.z() += B.z(); return A; } /* Return the negation of the vector, A. */ inline cs171Vec3 operator-(const cs171Vec3 &A) { return cs171Vec3(-A.x(), -A.y(), -A.z()); } /* Return a new vector that is the difference of the vectors, A - B. */ inline cs171Vec3 operator-(const cs171Vec3 &A, const cs171Vec3 &B) { return cs171Vec3(A.x() - B.x(), A.y() - B.y(), A.z() - B.z()); } /* Subtract the vector, B, out of the vector, A. */ inline cs171Vec3 & operator-=(cs171Vec3 &A, const cs171Vec3 &B) { A.x() -= B.x(); A.y() -= B.y(); A.z() -= B.z(); return A; } /* Return a new vector that is the scalar multiple of the vector, x. */ inline cs171Vec3 operator*(double a, const cs171Vec3 &x) { return cs171Vec3(a * x.x(), a * x.y(), a * x.z()); } /* Return a new vector that is the scalar multiple of the vector, x. */ inline cs171Vec3 operator*(const cs171Vec3 &x, double a) { return cs171Vec3(a * x.x(), a * x.y(), a * x.z()); } /* Returns the inner (dot) product of the two vectors, A and B. */ inline double operator*(const cs171Vec3 &A, const cs171Vec3 &B) { return A.x() * B.x() + A.y() * B.y() + A.z() * B.z(); } /* Set the vector, A, to be the scalar multiple of itself. */ inline cs171Vec3 & operator*=(cs171Vec3 &A, double a) { A.x() *= a; A.y() *= a; A.z() *= a; return A; } /* Return the equivalent of the scalar division of the vector, A. */ inline cs171Vec3 operator/(const cs171Vec3 &A, double c) { double t = 1.0 / c; return cs171Vec3(A.x() * t, A.y() * t, A.z() * t); } /* Return the equivalent of the scalar division of the vector, A. */ inline cs171Vec3& operator/=(cs171Vec3 &A, double a) { A.x() /= a; A.y() /= a; A.z() /= a; return A; } /* Returns the vector (cross) product, A cross B. */ inline cs171Vec3 operator^(const cs171Vec3 &A, const cs171Vec3 &B) { return cs171Vec3(A.y() * B.z() - A.z() * B.y(), A.z() * B.x() - A.x() * B.z(), A.x() * B.y() - A.y() * B.x()); } /* Output the vector. */ inline ostream & operator<<(ostream &os, const cs171Vec3 &v) { os << "[" << v.x() << ", " << v.y() << ", " << v.z() << "]"; return os; } /* Stand-alone (non-class) functions ------------------------------------- */ /* Return the vector whose elements are the absolute values of the elements of the vector, V. */ inline cs171Vec3 cs171Abs(const cs171Vec3 &V) { return cs171Vec3(fabs(V[0]), fabs(V[1]), fabs(V[2])); } /* Returns the distance between A and B (treated as points). */ inline double cs171Dist(const cs171Vec3 &A, const cs171Vec3 &B) { return (A - B).len(); } /* Returns a unit vector pointing in the same direction as the vector, A. */ inline cs171Vec3 cs171Vec3Unit(const cs171Vec3 &A) { double d = A.len_sqr(); if (d > 0.0) d = 1.0 / sqrt(d); else return A * 0; /* HEY!! Error message. */ return A * d; } /* Create a new unit vector pointing in the direction (x, y, z). */ inline cs171Vec3 cs171Vec3Unit(double x, double y, double z) { return cs171Vec3Unit(cs171Vec3(x, y, z)); } /* Returns TRUE if all 3 coordinats of A are NaN ("not a number" in IEEE floating-point format). inline int Nan(const cs171Vec3 &A) { return isnan(A[0]) || isnan(A[1]) || isnan(A[2]); } */ #endif /* cs171CommonVecHasBeenIncluded */