Vector.inl
Go to the documentation of this file.00001 /**<!--------------------------------------------------------------------> 00002 @file Vector.inl 00003 @author Travis Fischer (fisch0920@gmail.com) 00004 @date Fall 2008 00005 00006 @brief 00007 Provides basic functionality for a constant-sized Vector 00008 <!-------------------------------------------------------------------->**/ 00009 00010 #ifndef VECTOR_INL_ 00011 #define VECTOR_INL_ 00012 00013 00014 // Constructors 00015 // ------------ 00016 00017 // Expects N arguments of type T 00018 // (srcData is a pointer to an N-length array of type T) 00019 template <unsigned N, typename T> 00020 inline Vector<N, T>::Vector(const T *srcData) { 00021 memcpy(data, srcData, VECTOR_SIZE); 00022 } 00023 00024 // Constructs an zero Vector 00025 template <unsigned N, typename T> 00026 inline Vector<N, T>::Vector() { 00027 bzero(data, VECTOR_SIZE); 00028 } 00029 00030 // Copy Constructor; copies the underlying data from v to this vector 00031 template <unsigned N, typename T> 00032 inline Vector<N, T>::Vector(const Vector<N, T> &v) { 00033 memcpy(data, v.data, VECTOR_SIZE); 00034 } 00035 00036 00037 // Accessor Operators 00038 // ------------------ 00039 00040 // @returns a const reference to the element at the given index 00041 template <unsigned N, typename T> 00042 inline const T &Vector<N, T>::operator[](const unsigned index) const { 00043 ASSERT(index < N); 00044 00045 return data[index]; 00046 } 00047 00048 // @returns a reference to the element at the given index 00049 // @note changes to the returned element will affect this vector 00050 template <unsigned N, typename T> 00051 inline T &Vector<N, T>::operator[](const unsigned index) { 00052 ASSERT(index < N); 00053 00054 return data[index]; 00055 } 00056 00057 // @returns a pointer to the underlying data (N-length array of type T) 00058 template <unsigned N, typename T> 00059 inline const T *Vector<N, T>::operator* () const { 00060 return (T*)this; 00061 } 00062 00063 // @returns a pointer to the underlying data (N-length array of type T) 00064 template <unsigned N, typename T> 00065 inline T *Vector<N, T>::operator* () { 00066 return (T*)this; 00067 } 00068 00069 00070 // Equality Operators 00071 // ------------------ 00072 template <unsigned N, typename T> 00073 inline bool Vector<N, T>::operator==(const Vector<N, T> &v) const 00074 { 00075 for(unsigned i = N; i--;) 00076 if (NEQ(data[i], v.data[i])) 00077 return false; 00078 00079 return true; 00080 } 00081 00082 template <unsigned N, typename T> 00083 inline bool Vector<N, T>::operator!=(const Vector<N, T> &v) const 00084 { 00085 return !((*this) == v); 00086 } 00087 00088 // Mutator Operators 00089 // ----------------- 00090 00091 template <unsigned N, typename T> 00092 inline Vector<N, T> &Vector<N, T>::operator =(const Vector<N, T> &v) 00093 { 00094 memcpy(data, v.data, VECTOR_SIZE); 00095 00096 return *this; 00097 } 00098 00099 template <unsigned N, typename T> 00100 inline Vector<N, T> &Vector<N, T>::operator+=(const Vector<N, T> &rhs) 00101 { 00102 for(unsigned i = N; i--;) 00103 data[i] += rhs.data[i]; 00104 00105 return *this; 00106 } 00107 00108 template <unsigned N, typename T> 00109 inline Vector<N, T> &Vector<N, T>::operator-=(const Vector<N, T> &rhs) 00110 { 00111 return (*this += -rhs); 00112 } 00113 00114 00115 // Scalar Mutator Operators 00116 // ------------------------ 00117 template <unsigned N, typename T> 00118 inline Vector<N, T> &Vector<N, T>::operator*=(const T &scale) { 00119 for(unsigned i = N; i--;) 00120 data[i] *= scale; 00121 00122 return *this; 00123 } 00124 00125 template <unsigned N, typename T> 00126 inline Vector<N, T> &Vector<N, T>::operator/=(const T &scale) { 00127 if (scale != 0) { 00128 for(unsigned i = N; i--;) 00129 data[i] /= scale; 00130 } else { 00131 std::cerr << "Error: Attempting to divide Vector by zero" << std::endl << std::endl; 00132 ASSERT(0); 00133 } 00134 00135 return *this; 00136 } 00137 00138 00139 // Arithmetic Operators 00140 // -------------------- 00141 00142 template <unsigned N, typename T> 00143 inline Vector<N, T> Vector<N, T>::operator+ (const Vector<N, T> &rhs) const 00144 { 00145 T d[VECTOR_NO_ELEMENTS]; 00146 00147 for(unsigned i = N; i--;) 00148 d[i] = data[i] + rhs.data[i]; 00149 00150 return Vector<N, T>(d); 00151 } 00152 00153 template <unsigned N, typename T> 00154 inline Vector<N, T> Vector<N, T>::operator- (const Vector<N, T> &rhs) const 00155 { 00156 T d[VECTOR_NO_ELEMENTS]; 00157 00158 for(unsigned i = N; i--;) 00159 d[i] = data[i] - rhs.data[i]; 00160 00161 return Vector<N, T>(d); 00162 } 00163 00164 template <unsigned N, typename T> 00165 inline Vector<N, T> Vector<N, T>::operator* (const Vector<N, T> &rhs) const 00166 { 00167 T d[VECTOR_NO_ELEMENTS]; 00168 00169 for(unsigned i = N; i--;) 00170 d[i] = data[i] * rhs.data[i]; 00171 00172 return Vector<N, T>(d); 00173 } 00174 00175 // Scalar Arithmetic Operators 00176 template <unsigned N, typename T> 00177 inline Vector<N, T> Vector<N, T>::operator* (const T &scale) const { 00178 T d[VECTOR_NO_ELEMENTS]; 00179 00180 for(unsigned i = N; i--;) 00181 d[i] = data[i] * scale; 00182 00183 return Vector<N, T>(d); 00184 } 00185 00186 template <unsigned N, typename T> 00187 inline Vector<N, T> Vector<N, T>::operator/ (const T &scale) const { 00188 if (scale != 0) { 00189 return (*this * (create_real(1.0) / scale)); 00190 } else { 00191 std::cerr << "Error: Attempting to divide Vector by zero" << std::endl << std::endl; 00192 ASSERT(0); 00193 00194 return Vector<N, T>(); 00195 } 00196 } 00197 00198 00199 // More Complex Functionality 00200 // -------------------------- 00201 00202 // @returns whether or not this Vector is unitized 00203 template <unsigned N, typename T> 00204 inline bool Vector<N, T>::isUnit() const { 00205 return (EQ(getMagnitude2(), 1)); 00206 } 00207 00208 // @returns whether or not this Vector is the zero vector 00209 template <unsigned N, typename T> 00210 inline bool Vector<N, T>::isZero() const { 00211 for(unsigned i = N; i--;) { 00212 if (data[i] != 0) 00213 return false; 00214 } 00215 00216 return true; 00217 } 00218 00219 // @returns a normalized version of this vector 00220 template <unsigned N, typename T> 00221 inline Vector<N, T> Vector<N, T>::getNormalized() const { 00222 const T &magnitude = getMagnitude(); 00223 00224 if (magnitude == 0) { 00225 //std::cerr << "Error: Attempting to normalize vector with magnitude zero" << std::endl << std::endl; 00226 //ASSERT(0); 00227 00228 // TODO: how to handle this; apparently lots of meshes contain zero-ish data 00229 // which gets truncated to zero and we get here.. 00230 00231 return Vector<N, T>(); 00232 } else { 00233 const real_t &inv = create_real(1.0) / magnitude; 00234 T d[VECTOR_NO_ELEMENTS]; 00235 00236 for(unsigned i = N; i--;) 00237 d[i] = data[i] * inv; 00238 00239 return Vector<N, T>(d); 00240 } 00241 } 00242 00243 // @returns the reciprocal version of this vector (1.0 / this) 00244 template <unsigned N, typename T> 00245 inline Vector<N, T> Vector<N, T>::getReciprocal() const { 00246 T d[VECTOR_NO_ELEMENTS]; 00247 00248 for(unsigned i = N; i--;) 00249 d[i] = create_real(1.0) / data[i]; 00250 00251 return Vector<N, T>(d); 00252 } 00253 00254 // Normalizes this Vector and returns the old magnitude 00255 template <unsigned N, typename T> 00256 inline T Vector<N, T>::normalize() { 00257 const T &magnitude = getMagnitude(); 00258 00259 if (magnitude != 0) { 00260 const real_t &inv = 1.0 / magnitude; 00261 00262 for(unsigned i = N; i--;) 00263 data[i] *= inv; 00264 } else { 00265 //std::cerr << "Error: Attempting to normalize vector with magnitude zero" << std::endl << std::endl; 00266 //ASSERT(0); 00267 // TODO: how to handle this; apparently lots of meshes contain zero-ish data 00268 // which gets truncated to zero and we get here.. 00269 } 00270 00271 return magnitude; 00272 } 00273 00274 // @returns the magnitude of this vector 00275 template <unsigned N, typename T> 00276 inline T Vector<N, T>::getMagnitude() const { 00277 return sqrt(getMagnitude2()); 00278 } 00279 00280 // @returns the squared magnitude of this vector 00281 template <unsigned N, typename T> 00282 inline T Vector<N, T>::getMagnitude2() const { 00283 T magnitude2 = 0; 00284 00285 for(unsigned i = N; i--;) 00286 magnitude2 += data[i] * data[i]; 00287 00288 return magnitude2; 00289 } 00290 00291 // @returns the magnitude of the vector connecting this vector to the one 00292 // passed in 00293 template <unsigned N, typename T> 00294 inline T Vector<N, T>::getDistance(const Vector<N, T> &v) const { 00295 return sqrt(getDistance2(v)); 00296 } 00297 00298 // @returns the squared magnitude of the vector connecting this vector to 00299 // the one passed in 00300 template <unsigned N, typename T> 00301 inline T Vector<N, T>::getDistance2(const Vector<N, T> &v) const { 00302 return (v - *this).getMagnitude2(); 00303 } 00304 00305 // @returns the sum of the components in this Vector 00306 template <unsigned N, typename T> 00307 inline T Vector<N, T>::getSum() const { 00308 T sum = 0; 00309 00310 for(unsigned i = N; i--;) 00311 sum += data[i]; 00312 00313 return sum; 00314 } 00315 00316 // @returns the average of the components in this Vector 00317 template <unsigned N, typename T> 00318 inline T Vector<N, T>::getAverage() const { 00319 return (getSum() / N); 00320 } 00321 00322 // @returns the dot (inner) product of two vectors 00323 template <unsigned N, typename T> 00324 inline T Vector<N, T>::dot(const Vector<N, T> &rhs) const { 00325 T result = 0; 00326 00327 for(unsigned i = N; i--;) 00328 result += data[i] * rhs[i]; 00329 00330 return result; 00331 } 00332 00333 00334 // Specialized Vector Functionality 00335 // -------------------------------- 00336 00337 // Convenience Constructor 00338 template <unsigned N, typename T> 00339 inline Vector<N, T>::Vector(const T &v0, const T &v1, const T &v2) { 00340 if (N > 0) 00341 data[0] = v0; 00342 if (N > 1) 00343 data[1] = v1; 00344 if (N > 2) 00345 data[2] = v2; 00346 } 00347 00348 // @returns the cross product of two vectors 00349 // @note only have to implement for 3 or 4 dimensions 00350 // (in either case, just use hardcoded cross product for 3 dimensions and 00351 // if N is 4, set 'w' to 0) 00352 template <unsigned N, typename T> 00353 inline Vector<N, T> Vector<N, T>::cross(const Vector<N, T> &v) const 00354 { 00355 const Vector<N, T> &u = *this; 00356 00357 if (N == 3 || N == 4) { 00358 return Vector<N, T>(u[1] * v[2] - u[2] * v[1], 00359 u[2] * v[0] - u[0] * v[2], 00360 u[0] * v[1] - u[1] * v[0]); 00361 } 00362 00363 ASSERT(0 && "cross products are only implemented for N=3 and N=4\n"); 00364 return Vector<N, T>(); 00365 } 00366 00367 00368 // Extra operators where Vector is on right-hand side 00369 // -------------------------------------------------- 00370 00371 // @returns the N-length vector resulting from multiplying a scalar by an 00372 // N-length vector 00373 template <unsigned N, typename T> 00374 inline Vector<N, T> operator* (const real_t &scale, 00375 const Vector<N, T> &rhs) 00376 { 00377 return rhs * scale; 00378 } 00379 00380 // @returns (-1) * rhs, which is a negated version of the original right 00381 // hand side vector 00382 template <unsigned N, typename T> 00383 inline Vector<N, T> operator- (const Vector<N, T> &rhs) { 00384 return rhs * (-1); 00385 } 00386 00387 // Prints a Vector to an output stream 00388 template <unsigned N, typename T> 00389 inline std::ostream &operator<<(std::ostream &os, 00390 const Vector<N, T> &v) 00391 { 00392 os << "[ "; 00393 00394 for(unsigned i = 0; i < N; ++i) 00395 os << v.data[i] << (i < N - 1 ? ", " : ""); 00396 00397 os << " ]"; 00398 return os; 00399 } 00400 00401 // @returns dimension (0,1,...,N) of maximum length 00402 template <unsigned N, typename T> 00403 inline unsigned Vector<N, T>::getMaxDimension() const { 00404 unsigned max = 0; 00405 T maxVal = 0; 00406 00407 for(unsigned i = N; i--;) { 00408 const T &val = ABS(data[i]); 00409 00410 if (val > maxVal) { 00411 max = i; 00412 maxVal = val; 00413 } 00414 } 00415 00416 return max; 00417 } 00418 00419 // @returns dimension (0,1,...,N) of minimum length 00420 template <unsigned N, typename T> 00421 inline unsigned Vector<N, T>::getMinDimension() const { 00422 unsigned min = N - 1; 00423 00424 for(unsigned i = N - 1; i--;) 00425 if (data[i] < data[min]) 00426 min = i; 00427 00428 return min; 00429 } 00430 00431 00432 // Cleans up vector (0's out entries that are less than epsilon) 00433 template <unsigned N, typename T> 00434 void Vector<N, T>::cleanup() { 00435 for(unsigned i = N; i--;) { 00436 if (EQ(data[i], 0)) { 00437 data[i] = 0; 00438 } 00439 } 00440 } 00441 00442 /* Assume normal is normalized, incident vector is incoming and 00443 * resultant vector is exiting */ 00444 template <unsigned N, typename T> 00445 Vector<N, T> Vector<N, T>::reflectVector(const Vector<N, T> &normal) const { 00446 return -2 * normal * dot(normal) + *this; 00447 //const Vector<N, T> &n = (dot(normal) < 0 ? normal : -normal); 00448 00449 //return -2 * n * dot(n) + *this; 00450 } 00451 00452 template <unsigned N, typename T> 00453 Vector<N, T> Vector<N, T>::refractVector(const Vector<N, T> &normal, 00454 real_t in, real_t out) const 00455 { 00456 const Vector3 &w = -*this; 00457 Vector3 norm; 00458 real_t n; 00459 00460 if (dot(normal) < 0) { // wi incident on front-side of surface 00461 ASSERT(out != 0); 00462 norm = normal; 00463 n = in / out; 00464 } else { // wi incident on back-side of surface 00465 ASSERT(in != 0); 00466 norm = -normal; 00467 n = out / in; 00468 } 00469 00470 const real_t d = w.dot(norm); 00471 const real_t det = 1 - n * n * (1 - d * d); 00472 00473 if (det < 0) 00474 return Vector3::zero(); 00475 00476 const Vector3 &wo = -n * w + norm * (n * d - sqrt(det)); 00477 ASSERT(wo.isUnit()); 00478 00479 return wo; 00480 } 00481 00482 #if 0 00483 template <unsigned N, typename T> 00484 Vector<N, T> Vector<N, T>::refractVector(const Vector<N, T> &normal, 00485 real_t in, real_t out) const 00486 { 00487 const Vector3 &dir = -*this; 00488 Vector3 norm; 00489 real_t n; 00490 00491 if (dot(normal) < 0) { // wi incident on front-side of surface 00492 ASSERT(in != 0); 00493 norm = normal; 00494 n = out / in; 00495 } else { // wi incident on back-side of surface 00496 ASSERT(out != 0); 00497 norm = -normal; 00498 n = in / out; 00499 } 00500 00501 const real_t d = dir.dot(norm); 00502 const real_t det = 1 - n * n * (1 - d * d); 00503 00504 if (det < 0) 00505 return Vector<3, T>::zero(); 00506 00507 return -n * (dir - d * norm) - norm * sqrt(det); 00508 } 00509 #endif 00510 00511 template <unsigned N, typename T> 00512 void Vector<N, T>::getOrthonormalBasis(Vector<N, T> &U, Vector<N, T> &V) 00513 { 00514 normalize(); 00515 const Vector3 &normal = *this; 00516 Vector3 up = Vector3(0, 1, 0); 00517 00518 if (ABS(up.dot(normal)) > create_real(0.8)) 00519 up = Vector3(1, 0, 0); 00520 00521 U = up.cross(normal).getNormalized(); 00522 V = normal.cross(U).getNormalized(); 00523 } 00524 00525 inline Vector3 convertHemisphere(const real_t theta, const real_t phi, 00526 const Vector3 &N) 00527 { 00528 ASSERT(theta >= -EPSILON && theta <= M_PI / 2 + EPSILON); 00529 ASSERT(phi >= -EPSILON && phi <= M_PI * 2 + EPSILON); 00530 00531 const Vector3 &w = Vector3::fromSpherical(theta, phi); 00532 00533 return convertHemisphere(w, N); 00534 } 00535 00536 #endif // VECTOR_INL_ 00537
Generated on 28 Feb 2009 for Milton by
1.5.6