Blender V2.61 - r43446

VEC3.h

Go to the documentation of this file.
00001 
00004 /******************************************************************************
00005  * Copyright 2007 Nils Thuerey
00006  * Basic vector class 
00007  *****************************************************************************/
00008 #ifndef BASICVECTOR_H
00009 #define BASICVECTOR_H
00010 
00011 #include <math.h>
00012 #include <stdlib.h>
00013 #include <stdio.h>
00014 #include <iostream>
00015 #include <sstream>
00016 
00017 // use which fp-precision? 1=float, 2=double
00018 #ifndef FLOATINGPOINT_PRECISION
00019 #if DDF_DEBUG==1
00020 #define FLOATINGPOINT_PRECISION 2
00021 #else // DDF_DEBUG==1
00022 #define FLOATINGPOINT_PRECISION 1
00023 #endif // DDF_DEBUG==1
00024 #endif
00025 
00026 // VECTOR_EPSILON is the minimal vector length
00027 // In order to be able to discriminate floating point values near zero, and
00028 // to be sure not to fail a comparison because of roundoff errors, use this
00029 // value as a threshold.  
00030 
00031 #if FLOATINGPOINT_PRECISION==1
00032 typedef float Real;
00033 #define FP_REAL_MAX __FLT_MAX__
00034 #define VECTOR_EPSILON (1e-5f)
00035 #else
00036 typedef double Real;
00037 #define FP_REAL_MAX __DBL_MAX__
00038 #define VECTOR_EPSILON (1e-10)
00039 #endif
00040 
00041 
00042 // hardcoded limits for now...
00043 // for e.g. MSVC compiler...
00044 // some of these defines can be needed
00045 // for linux systems as well (e.g. FLT_MAX)
00046 #ifndef __FLT_MAX__
00047 #   ifdef FLT_MAX  // try to use it instead
00048 #       define __FLT_MAX__ FLT_MAX
00049 #   else // FLT_MAX
00050 #       define __FLT_MAX__ 3.402823466e+38f
00051 #   endif // FLT_MAX
00052 #endif // __FLT_MAX__
00053 #ifndef __DBL_MAX__
00054 #   ifdef DBL_MAX // try to use it instead
00055 #       define __DBL_MAX__ DBL_MAX
00056 #   else // DBL_MAX
00057 #       define __DBL_MAX__ 1.7976931348623158e+308
00058 #   endif // DBL_MAX
00059 #endif // __DBL_MAX__
00060 
00061 #ifndef FLT_MAX
00062 #define FLT_MAX __FLT_MAX__
00063 #endif
00064 
00065 #ifndef DBL_MAX
00066 #define DBL_MAX __DBL_MAX__
00067 #endif
00068 
00069 #ifndef M_PI
00070 #   define M_PI 3.1415926536
00071 #   define M_E  2.7182818284
00072 #endif
00073 
00074 
00075 
00076 namespace BasicVector {
00077 
00078 
00079 // basic inlined vector class
00080 template<class Scalar>
00081 class Vector3Dim
00082 {
00083 public:
00084   // Constructor
00085   inline Vector3Dim();
00086   // Copy-Constructor
00087   inline Vector3Dim(const Vector3Dim<Scalar> &v );
00088   inline Vector3Dim(const float *);
00089   inline Vector3Dim(const double *);
00090   // construct a vector from one Scalar
00091   inline Vector3Dim(Scalar);
00092   // construct a vector from three Scalars
00093   inline Vector3Dim(Scalar, Scalar, Scalar);
00094 
00095     // get address of array for OpenGL
00096     Scalar *getAddress() { return value; }
00097 
00098   // Assignment operator
00099   inline const Vector3Dim<Scalar>& operator=  (const Vector3Dim<Scalar>& v);
00100   // Assignment operator
00101   inline const Vector3Dim<Scalar>& operator=  (Scalar s);
00102   // Assign and add operator
00103   inline const Vector3Dim<Scalar>& operator+= (const Vector3Dim<Scalar>& v);
00104   // Assign and add operator
00105   inline const Vector3Dim<Scalar>& operator+= (Scalar s);
00106   // Assign and sub operator
00107   inline const Vector3Dim<Scalar>& operator-= (const Vector3Dim<Scalar>& v);
00108   // Assign and sub operator
00109   inline const Vector3Dim<Scalar>& operator-= (Scalar s);
00110   // Assign and mult operator
00111   inline const Vector3Dim<Scalar>& operator*= (const Vector3Dim<Scalar>& v);
00112   // Assign and mult operator
00113   inline const Vector3Dim<Scalar>& operator*= (Scalar s);
00114   // Assign and div operator
00115   inline const Vector3Dim<Scalar>& operator/= (const Vector3Dim<Scalar>& v);
00116   // Assign and div operator
00117   inline const Vector3Dim<Scalar>& operator/= (Scalar s);
00118 
00119 
00120   // unary operator
00121   inline Vector3Dim<Scalar> operator- () const;
00122 
00123   // binary operator add
00124   inline Vector3Dim<Scalar> operator+ (const Vector3Dim<Scalar>&) const;
00125   // binary operator add
00126   inline Vector3Dim<Scalar> operator+ (Scalar) const;
00127   // binary operator sub
00128   inline Vector3Dim<Scalar> operator- (const Vector3Dim<Scalar>&) const;
00129   // binary operator sub
00130   inline Vector3Dim<Scalar> operator- (Scalar) const;
00131   // binary operator mult
00132   inline Vector3Dim<Scalar> operator* (const Vector3Dim<Scalar>&) const;
00133   // binary operator mult
00134   inline Vector3Dim<Scalar> operator* (Scalar) const;
00135   // binary operator div
00136   inline Vector3Dim<Scalar> operator/ (const Vector3Dim<Scalar>&) const;
00137   // binary operator div
00138   inline Vector3Dim<Scalar> operator/ (Scalar) const;
00139 
00140   // Projection normal to a vector
00141   inline Vector3Dim<Scalar>   getOrthogonalntlVector3Dim() const;
00142   // Project into a plane
00143   inline const Vector3Dim<Scalar>& projectNormalTo(const Vector3Dim<Scalar> &v);
00144   
00145   // minimize
00146   inline const Vector3Dim<Scalar> &minimize(const Vector3Dim<Scalar> &);
00147   // maximize
00148   inline const Vector3Dim<Scalar> &maximize(const Vector3Dim<Scalar> &);
00149   
00150   // access operator
00151   inline Scalar& operator[](unsigned int i);
00152   // access operator
00153   inline const Scalar& operator[](unsigned int i) const;
00154 
00156     union {
00157         struct {
00158         Scalar value[3];  
00159         };
00160         struct {
00161         Scalar x;
00162         Scalar y;
00163         Scalar z;
00164         };
00165         struct {
00166         Scalar X;
00167         Scalar Y;
00168         Scalar Z;
00169         };
00170     };
00171 protected:
00172   
00173 };
00174 
00175 
00176 
00177 
00178 
00179 //------------------------------------------------------------------------------
00180 // VECTOR inline FUNCTIONS
00181 //------------------------------------------------------------------------------
00182 
00183 
00184 
00185 /*************************************************************************
00186   Constructor.
00187   */
00188 template<class Scalar>
00189 inline Vector3Dim<Scalar>::Vector3Dim( void )
00190 {
00191   value[0] = value[1] = value[2] = 0;
00192 }
00193 
00194 
00195 
00196 /*************************************************************************
00197   Copy-Constructor.
00198   */
00199 template<class Scalar>
00200 inline Vector3Dim<Scalar>::Vector3Dim( const Vector3Dim<Scalar> &v )
00201 {
00202   value[0] = v.value[0];
00203   value[1] = v.value[1];
00204   value[2] = v.value[2];
00205 }
00206 template<class Scalar>
00207 inline Vector3Dim<Scalar>::Vector3Dim( const float *fvalue)
00208 {
00209   value[0] = (Scalar)fvalue[0];
00210   value[1] = (Scalar)fvalue[1];
00211   value[2] = (Scalar)fvalue[2];
00212 }
00213 template<class Scalar>
00214 inline Vector3Dim<Scalar>::Vector3Dim( const double *fvalue)
00215 {
00216   value[0] = (Scalar)fvalue[0];
00217   value[1] = (Scalar)fvalue[1];
00218   value[2] = (Scalar)fvalue[2];
00219 }
00220 
00221 
00222 
00223 /*************************************************************************
00224   Constructor for a vector from a single Scalar. All components of
00225   the vector get the same value.
00226   \param s The value to set
00227   \return The new vector
00228   */
00229 template<class Scalar>
00230 inline Vector3Dim<Scalar>::Vector3Dim(Scalar s )
00231 {
00232   value[0]= s;
00233   value[1]= s;
00234   value[2]= s;
00235 }
00236 
00237 
00238 /*************************************************************************
00239   Constructor for a vector from three Scalars.
00240   \param s1 The value for the first vector component
00241   \param s2 The value for the second vector component
00242   \param s3 The value for the third vector component
00243   \return The new vector
00244   */
00245 template<class Scalar>
00246 inline Vector3Dim<Scalar>::Vector3Dim(Scalar s1, Scalar s2, Scalar s3)
00247 {
00248   value[0]= s1;
00249   value[1]= s2;
00250   value[2]= s3;
00251 }
00252 
00253 
00254 
00255 /*************************************************************************
00256   Copy a Vector3Dim componentwise.
00257   \param v vector with values to be copied
00258   \return Reference to self
00259   */
00260 template<class Scalar>
00261 inline const Vector3Dim<Scalar>&
00262 Vector3Dim<Scalar>::operator=( const Vector3Dim<Scalar> &v )
00263 {
00264   value[0] = v.value[0];
00265   value[1] = v.value[1];
00266   value[2] = v.value[2];  
00267   return *this;
00268 }
00269 
00270 
00271 /*************************************************************************
00272   Copy a Scalar to each component.
00273   \param s The value to copy
00274   \return Reference to self
00275   */
00276 template<class Scalar>
00277 inline const Vector3Dim<Scalar>&
00278 Vector3Dim<Scalar>::operator=(Scalar s)
00279 {
00280   value[0] = s;
00281   value[1] = s;
00282   value[2] = s;  
00283   return *this;
00284 }
00285 
00286 
00287 /*************************************************************************
00288   Add another Vector3Dim componentwise.
00289   \param v vector with values to be added
00290   \return Reference to self
00291   */
00292 template<class Scalar>
00293 inline const Vector3Dim<Scalar>&
00294 Vector3Dim<Scalar>::operator+=( const Vector3Dim<Scalar> &v )
00295 {
00296   value[0] += v.value[0];
00297   value[1] += v.value[1];
00298   value[2] += v.value[2];  
00299   return *this;
00300 }
00301 
00302 
00303 /*************************************************************************
00304   Add a Scalar value to each component.
00305   \param s Value to add
00306   \return Reference to self
00307   */
00308 template<class Scalar>
00309 inline const Vector3Dim<Scalar>&
00310 Vector3Dim<Scalar>::operator+=(Scalar s)
00311 {
00312   value[0] += s;
00313   value[1] += s;
00314   value[2] += s;  
00315   return *this;
00316 }
00317 
00318 
00319 /*************************************************************************
00320   Subtract another vector componentwise.
00321   \param v vector of values to subtract
00322   \return Reference to self
00323   */
00324 template<class Scalar>
00325 inline const Vector3Dim<Scalar>&
00326 Vector3Dim<Scalar>::operator-=( const Vector3Dim<Scalar> &v )
00327 {
00328   value[0] -= v.value[0];
00329   value[1] -= v.value[1];
00330   value[2] -= v.value[2];  
00331   return *this;
00332 }
00333 
00334 
00335 /*************************************************************************
00336   Subtract a Scalar value from each component.
00337   \param s Value to subtract
00338   \return Reference to self
00339   */
00340 template<class Scalar>
00341 inline const Vector3Dim<Scalar>&
00342 Vector3Dim<Scalar>::operator-=(Scalar s)
00343 {
00344   value[0]-= s;
00345   value[1]-= s;
00346   value[2]-= s;  
00347   return *this;
00348 }
00349 
00350 
00351 /*************************************************************************
00352   Multiply with another vector componentwise.
00353   \param v vector of values to multiply with
00354   \return Reference to self
00355   */
00356 template<class Scalar>
00357 inline const Vector3Dim<Scalar>&
00358 Vector3Dim<Scalar>::operator*=( const Vector3Dim<Scalar> &v )
00359 {
00360   value[0] *= v.value[0];
00361   value[1] *= v.value[1];
00362   value[2] *= v.value[2];  
00363   return *this;
00364 }
00365 
00366 
00367 /*************************************************************************
00368   Multiply each component with a Scalar value.
00369   \param s Value to multiply with
00370   \return Reference to self
00371   */
00372 template<class Scalar>
00373 inline const Vector3Dim<Scalar>&
00374 Vector3Dim<Scalar>::operator*=(Scalar s)
00375 {
00376   value[0] *= s;
00377   value[1] *= s;
00378   value[2] *= s;  
00379   return *this;
00380 }
00381 
00382 
00383 /*************************************************************************
00384   Divide by another Vector3Dim componentwise.
00385   \param v vector of values to divide by
00386   \return Reference to self
00387   */
00388 template<class Scalar>
00389 inline const Vector3Dim<Scalar>&
00390 Vector3Dim<Scalar>::operator/=( const Vector3Dim<Scalar> &v )
00391 {
00392   value[0] /= v.value[0];
00393   value[1] /= v.value[1];
00394   value[2] /= v.value[2];  
00395   return *this;
00396 }
00397 
00398 
00399 /*************************************************************************
00400   Divide each component by a Scalar value.
00401   \param s Value to divide by
00402   \return Reference to self
00403   */
00404 template<class Scalar>
00405 inline const Vector3Dim<Scalar>&
00406 Vector3Dim<Scalar>::operator/=(Scalar s)
00407 {
00408   value[0] /= s;
00409   value[1] /= s;
00410   value[2] /= s;
00411   return *this;
00412 }
00413 
00414 
00415 //------------------------------------------------------------------------------
00416 // unary operators
00417 //------------------------------------------------------------------------------
00418 
00419 
00420 /*************************************************************************
00421   Build componentwise the negative this vector.
00422   \return The new (negative) vector
00423   */
00424 template<class Scalar>
00425 inline Vector3Dim<Scalar>
00426 Vector3Dim<Scalar>::operator-() const
00427 {
00428   return Vector3Dim<Scalar>(-value[0], -value[1], -value[2]);
00429 }
00430 
00431 
00432 
00433 //------------------------------------------------------------------------------
00434 // binary operators
00435 //------------------------------------------------------------------------------
00436 
00437 
00438 /*************************************************************************
00439   Build a vector with another vector added componentwise.
00440   \param v The second vector to add
00441   \return The sum vector
00442   */
00443 template<class Scalar>
00444 inline Vector3Dim<Scalar>
00445 Vector3Dim<Scalar>::operator+( const Vector3Dim<Scalar> &v ) const
00446 {
00447   return Vector3Dim<Scalar>(value[0]+v.value[0],
00448             value[1]+v.value[1],
00449             value[2]+v.value[2]);
00450 }
00451 
00452 
00453 /*************************************************************************
00454   Build a vector with a Scalar value added to each component.
00455   \param s The Scalar value to add
00456   \return The sum vector
00457   */
00458 template<class Scalar>
00459 inline Vector3Dim<Scalar>
00460 Vector3Dim<Scalar>::operator+(Scalar s) const
00461 {
00462   return Vector3Dim<Scalar>(value[0]+s,
00463             value[1]+s,
00464             value[2]+s);
00465 }
00466 
00467 
00468 /*************************************************************************
00469   Build a vector with another vector subtracted componentwise.
00470   \param v The second vector to subtract
00471   \return The difference vector
00472   */
00473 template<class Scalar>
00474 inline Vector3Dim<Scalar>
00475 Vector3Dim<Scalar>::operator-( const Vector3Dim<Scalar> &v ) const
00476 {
00477   return Vector3Dim<Scalar>(value[0]-v.value[0],
00478             value[1]-v.value[1],
00479             value[2]-v.value[2]);
00480 }
00481 
00482 
00483 /*************************************************************************
00484   Build a vector with a Scalar value subtracted componentwise.
00485   \param s The Scalar value to subtract
00486   \return The difference vector
00487   */
00488 template<class Scalar>
00489 inline Vector3Dim<Scalar>
00490 Vector3Dim<Scalar>::operator-(Scalar s ) const
00491 {
00492   return Vector3Dim<Scalar>(value[0]-s,
00493             value[1]-s,
00494             value[2]-s);
00495 }
00496 
00497 
00498 
00499 /*************************************************************************
00500   Build a vector with another vector multiplied by componentwise.
00501   \param v The second vector to muliply with
00502   \return The product vector
00503   */
00504 template<class Scalar>
00505 inline Vector3Dim<Scalar>
00506 Vector3Dim<Scalar>::operator*( const Vector3Dim<Scalar>& v) const
00507 {
00508   return Vector3Dim<Scalar>(value[0]*v.value[0],
00509             value[1]*v.value[1],
00510             value[2]*v.value[2]);
00511 }
00512 
00513 
00514 /*************************************************************************
00515   Build a Vector3Dim with a Scalar value multiplied to each component.
00516   \param s The Scalar value to multiply with
00517   \return The product vector
00518   */
00519 template<class Scalar>
00520 inline Vector3Dim<Scalar>
00521 Vector3Dim<Scalar>::operator*(Scalar s) const
00522 {
00523   return Vector3Dim<Scalar>(value[0]*s, value[1]*s, value[2]*s);
00524 }
00525 
00526 
00527 /*************************************************************************
00528   Build a vector divided componentwise by another vector.
00529   \param v The second vector to divide by
00530   \return The ratio vector
00531   */
00532 template<class Scalar>
00533 inline Vector3Dim<Scalar>
00534 Vector3Dim<Scalar>::operator/(const Vector3Dim<Scalar>& v) const
00535 {
00536   return Vector3Dim<Scalar>(value[0]/v.value[0],
00537             value[1]/v.value[1],
00538             value[2]/v.value[2]);
00539 }
00540 
00541 
00542 
00543 /*************************************************************************
00544   Build a vector divided componentwise by a Scalar value.
00545   \param s The Scalar value to divide by
00546   \return The ratio vector
00547   */
00548 template<class Scalar>
00549 inline Vector3Dim<Scalar>
00550 Vector3Dim<Scalar>::operator/(Scalar s) const
00551 {
00552   return Vector3Dim<Scalar>(value[0]/s,
00553             value[1]/s,
00554             value[2]/s);
00555 }
00556 
00557 
00558 
00559 
00560 
00561 /*************************************************************************
00562   Get a particular component of the vector.
00563   \param i Number of Scalar to get
00564   \return Reference to the component
00565   */
00566 template<class Scalar>
00567 inline Scalar&
00568 Vector3Dim<Scalar>::operator[]( unsigned int i )
00569 {
00570   return value[i];
00571 }
00572 
00573 
00574 /*************************************************************************
00575   Get a particular component of a constant vector.
00576   \param i Number of Scalar to get
00577   \return Reference to the component
00578   */
00579 template<class Scalar>
00580 inline const Scalar&
00581 Vector3Dim<Scalar>::operator[]( unsigned int i ) const
00582 {
00583   return value[i];
00584 }
00585 
00586 
00587 
00588 //------------------------------------------------------------------------------
00589 // BLITZ compatibility functions
00590 //------------------------------------------------------------------------------
00591 
00592 
00593 
00594 /*************************************************************************
00595   Compute the scalar product with another vector.
00596   \param v The second vector to work with
00597   \return The value of the scalar product
00598   */
00599 template<class Scalar>
00600 inline Scalar dot(const Vector3Dim<Scalar> &t, const Vector3Dim<Scalar> &v )
00601 {
00602   //return t.value[0]*v.value[0] + t.value[1]*v.value[1] + t.value[2]*v.value[2];
00603   return ((t[0]*v[0]) + (t[1]*v[1]) + (t[2]*v[2]));
00604 }
00605 
00606 
00607 /*************************************************************************
00608   Calculate the cross product of this and another vector
00609  */
00610 template<class Scalar>
00611 inline Vector3Dim<Scalar> cross(const Vector3Dim<Scalar> &t, const Vector3Dim<Scalar> &v)
00612 {
00613   Vector3Dim<Scalar> cp( 
00614             ((t[1]*v[2]) - (t[2]*v[1])),
00615           ((t[2]*v[0]) - (t[0]*v[2])),
00616           ((t[0]*v[1]) - (t[1]*v[0])) );
00617   return cp;
00618 }
00619 
00620 
00621 
00622 
00623 /*************************************************************************
00624   Compute a vector that is orthonormal to self. Nothing else can be assumed
00625   for the direction of the new vector.
00626   \return The orthonormal vector
00627   */
00628 template<class Scalar>
00629 Vector3Dim<Scalar>
00630 Vector3Dim<Scalar>::getOrthogonalntlVector3Dim() const
00631 {
00632   // Determine the  component with max. absolute value
00633   int max= (fabs(value[0]) > fabs(value[1])) ? 0 : 1;
00634   max= (fabs(value[max]) > fabs(value[2])) ? max : 2;
00635 
00636   /*************************************************************************
00637     Choose another axis than the one with max. component and project
00638     orthogonal to self
00639     */
00640   Vector3Dim<Scalar> vec(0.0);
00641   vec[(max+1)%3]= 1;
00642   vec.normalize();
00643   vec.projectNormalTo(this->getNormalized());
00644   return vec;
00645 }
00646 
00647 
00648 /*************************************************************************
00649   Projects the vector into a plane normal to the given vector, which must
00650   have unit length. Self is modified.
00651   \param v The plane normal
00652   \return The projected vector
00653   */
00654 template<class Scalar>
00655 inline const Vector3Dim<Scalar>&
00656 Vector3Dim<Scalar>::projectNormalTo(const Vector3Dim<Scalar> &v)
00657 {
00658   Scalar sprod = dot(*this,v);
00659   value[0]= value[0] - v.value[0] * sprod;
00660   value[1]= value[1] - v.value[1] * sprod;
00661   value[2]= value[2] - v.value[2] * sprod;  
00662   return *this;
00663 }
00664 
00665 
00666 
00667 //------------------------------------------------------------------------------
00668 // Other helper functions
00669 //------------------------------------------------------------------------------
00670 
00671 
00672 
00673 /*************************************************************************
00674   Minimize the vector, i.e. set each entry of the vector to the minimum
00675   of both values.
00676   \param pnt The second vector to compare with
00677   \return Reference to the modified self
00678   */
00679 template<class Scalar>
00680 inline const Vector3Dim<Scalar> &
00681 Vector3Dim<Scalar>::minimize(const Vector3Dim<Scalar> &pnt)
00682 {
00683   for (unsigned int i = 0; i < 3; i++)
00684     value[i] = MIN(value[i],pnt[i]);
00685   return *this;
00686 }
00687 
00688 
00689 
00690 /*************************************************************************
00691   Maximize the vector, i.e. set each entry of the vector to the maximum
00692   of both values.
00693   \param pnt The second vector to compare with
00694   \return Reference to the modified self
00695   */
00696 template<class Scalar>
00697 inline const Vector3Dim<Scalar> &
00698 Vector3Dim<Scalar>::maximize(const Vector3Dim<Scalar> &pnt)
00699 {
00700   for (unsigned int i = 0; i < 3; i++)
00701     value[i] = MAX(value[i],pnt[i]);
00702   return *this;
00703 }
00704 
00705 
00706 
00707 
00708 
00709 
00710 /************************************************************************/
00711 // HELPER FUNCTIONS, independent of implementation
00712 /************************************************************************/
00713 
00714 #define VECTOR_TYPE Vector3Dim<Scalar>
00715 
00716 
00717 /*************************************************************************
00718   Compute the length (norm) of the vector.
00719   \return The value of the norm
00720   */
00721 template<class Scalar>
00722 inline Scalar norm( const VECTOR_TYPE &v)
00723 {
00724   Scalar l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
00725   return (fabs(l-1.) < VECTOR_EPSILON*VECTOR_EPSILON) ? 1. : sqrt(l);
00726 }
00727 
00728 // for e.g. min max operator
00729 inline Real normHelper(const Vector3Dim<Real> &v) {
00730     return norm(v);
00731 }   
00732 inline Real normHelper(const Real &v) {
00733     return (0. < v) ? v : -v ; 
00734 }   
00735 inline Real normHelper(const int &v) {
00736     return (0 < v) ? (Real)(v) : (Real)(-v) ; 
00737 }   
00738 
00739 
00740 /*************************************************************************
00741   Same as getNorm but doesnt sqrt  
00742   */
00743 template<class Scalar>
00744 inline Scalar normNoSqrt( const VECTOR_TYPE &v)
00745 {
00746   return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
00747 }
00748 
00749 
00750 /*************************************************************************
00751   Compute a normalized vector based on this vector.
00752   \return The new normalized vector
00753   */
00754 template<class Scalar>
00755 inline VECTOR_TYPE getNormalized( const VECTOR_TYPE &v)
00756 {
00757   Scalar l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
00758   if (fabs(l-1.) < VECTOR_EPSILON*VECTOR_EPSILON)
00759     return v; /* normalized "enough"... */
00760   else if (l > VECTOR_EPSILON*VECTOR_EPSILON)
00761   {
00762     Scalar fac = 1./sqrt(l);
00763     return VECTOR_TYPE(v[0]*fac, v[1]*fac, v[2]*fac);
00764   }
00765   else
00766     return VECTOR_TYPE((Scalar)0);
00767 }
00768 
00769 
00770 /*************************************************************************
00771   Compute the norm of the vector and normalize it.
00772   \return The value of the norm
00773   */
00774 template<class Scalar>
00775 inline Scalar normalize( VECTOR_TYPE &v) 
00776 {
00777   Scalar norm;
00778   Scalar l = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];  
00779   if (fabs(l-1.) < VECTOR_EPSILON*VECTOR_EPSILON) {
00780     norm = 1.;
00781     } else if (l > VECTOR_EPSILON*VECTOR_EPSILON) {
00782     norm = sqrt(l);
00783     Scalar fac = 1./norm;
00784     v[0] *= fac;
00785     v[1] *= fac;
00786     v[2] *= fac; 
00787     } else {
00788     v[0]= v[1]= v[2]= 0;
00789     norm = 0.;
00790   }
00791   return (Scalar)norm;
00792 }
00793 
00794 
00795 /*************************************************************************
00796   Compute a vector, that is self (as an incoming
00797   vector) reflected at a surface with a distinct normal vector. Note
00798   that the normal is reversed, if the scalar product with it is positive.
00799   \param n The surface normal
00800   \return The new reflected vector
00801   */
00802 template<class Scalar>
00803 inline VECTOR_TYPE reflectVector(const VECTOR_TYPE &t, const VECTOR_TYPE &n) 
00804 {
00805   VECTOR_TYPE nn= (dot(t, n) > 0.0) ? (n*-1.0) : n;
00806   return ( t - nn * (2.0 * dot(nn, t)) );
00807 }
00808 
00809 
00810 
00811 /*************************************************************************
00812  * My own refraction calculation
00813  * Taken from Glassner's book, section 5.2 (Heckberts method)
00814  */
00815 template<class Scalar>
00816 inline VECTOR_TYPE refractVector(const VECTOR_TYPE &t, const VECTOR_TYPE &normal, Scalar nt, Scalar nair, int &refRefl) 
00817 {
00818     Scalar eta = nair / nt;
00819     Scalar n = -dot(t, normal);
00820     Scalar tt = 1.0 + eta*eta* (n*n-1.0);
00821     if(tt<0.0) {
00822         // we have total reflection!
00823         refRefl = 1;
00824     } else {
00825         // normal reflection
00826         tt = eta*n - sqrt(tt);
00827         return( t*eta + normal*tt );
00828     }
00829     return t;
00830 }
00831 
00832 
00833 /*************************************************************************
00834   Test two ntlVector3Dims for equality based on the equality of their
00835   values within a small threshold.
00836   \param c The second vector to compare
00837   \return TRUE if both are equal
00838   \sa getEpsilon()
00839   */
00840 template<class Scalar>
00841 inline bool equal(const VECTOR_TYPE &v, const VECTOR_TYPE &c)
00842 {
00843   return (ABS(v[0]-c[0]) + 
00844       ABS(v[1]-c[1]) + 
00845       ABS(v[2]-c[2]) < VECTOR_EPSILON);
00846 }
00847 
00848 
00849 /*************************************************************************
00850  * Assume this vector is an RGB color, and convert it to HSV
00851  */
00852 template<class Scalar>
00853 inline void rgbToHsv( VECTOR_TYPE &V )
00854 {
00855     Scalar h=0,s=0,v=0;
00856     Scalar maxrgb, minrgb, delta;
00857     // convert to hsv...
00858     maxrgb = V[0];
00859     int maxindex = 1;
00860     if(V[2] > maxrgb){ maxrgb = V[2]; maxindex = 2; }
00861     if(V[1] > maxrgb){ maxrgb = V[1]; maxindex = 3; }
00862     minrgb = V[0];
00863     if(V[2] < minrgb) minrgb = V[2];
00864     if(V[1] < minrgb) minrgb = V[1];
00865 
00866     v = maxrgb;
00867     delta = maxrgb-minrgb;
00868 
00869     if(maxrgb > 0) s = delta/maxrgb;
00870     else s = 0;
00871 
00872     h = 0;
00873     if(s > 0) {
00874         if(maxindex == 1) {
00875             h = ((V[1]-V[2])/delta)  + 0.0; }
00876         if(maxindex == 2) {
00877             h = ((V[2]-V[0])/delta)  + 2.0; }
00878         if(maxindex == 3) {
00879             h = ((V[0]-V[1])/delta)  + 4.0; }
00880         h *= 60.0;
00881         if(h < 0.0) h += 360.0;
00882     }
00883 
00884     V[0] = h;
00885     V[1] = s;
00886     V[2] = v;
00887 }
00888 
00889 /*************************************************************************
00890  * Assume this vector is HSV and convert to RGB
00891  */
00892 template<class Scalar>
00893 inline void hsvToRgb( VECTOR_TYPE &V )
00894 {
00895     Scalar h = V[0], s = V[1], v = V[2];
00896     Scalar r=0,g=0,b=0;
00897     Scalar p,q,t, fracth;
00898     int floorh;
00899     // ...and back to rgb
00900     if(s == 0) {
00901         r = g = b = v; }
00902     else {
00903         h /= 60.0;
00904         floorh = (int)h;
00905         fracth = h - floorh;
00906         p = v * (1.0 - s);
00907         q = v * (1.0 - (s * fracth));
00908         t = v * (1.0 - (s * (1.0 - fracth)));
00909         switch (floorh) {
00910         case 0: r = v; g = t; b = p; break;
00911         case 1: r = q; g = v; b = p; break;
00912         case 2: r = p; g = v; b = t; break;
00913         case 3: r = p; g = q; b = v; break;
00914         case 4: r = t; g = p; b = v; break;
00915         case 5: r = v; g = p; b = q; break;
00916         }
00917     }
00918 
00919     V[0] = r;
00920     V[1] = g;
00921     V[2] = b;
00922 }
00923 
00924 //------------------------------------------------------------------------------
00925 // STREAM FUNCTIONS
00926 //------------------------------------------------------------------------------
00927 
00928 
00929 
00931 //extern const char *globVecFormatStr;
00932 #if 0
00933 static const char *globVecFormatStr = "[%6.4f,%6.4f,%6.4f]";
00934 #endif
00935 
00936 /*************************************************************************
00937   Outputs the object in human readable form using the format
00938   [x,y,z]
00939   */
00940 template<class Scalar>
00941 std::ostream&
00942 operator<<( std::ostream& os, const BasicVector::Vector3Dim<Scalar>& i )
00943 {
00944 #if 0
00945     char buf[256];
00946 #if _WIN32
00947   sprintf(buf,globVecFormatStr, (double)i[0],(double)i[1],(double)i[2]);
00948 #else
00949   snprintf(buf,256,globVecFormatStr, (double)i[0],(double)i[1],(double)i[2]);
00950 #endif
00951     os << std::string(buf); 
00952 #endif
00953   return os;
00954 }
00955 
00956 
00957 /*************************************************************************
00958   Reads the contents of the object from a stream using the same format
00959   as the output operator.
00960   */
00961 template<class Scalar>
00962 std::istream&
00963 operator>>( std::istream& is, BasicVector::Vector3Dim<Scalar>& i )
00964 {
00965   char c;
00966   char dummy[3];
00967   is >> c >> i[0] >> dummy >> i[1] >> dummy >> i[2] >> c;
00968   return is;
00969 }
00970 
00971 
00972 /**************************************************************************/
00973 // typedefs!
00974 /**************************************************************************/
00975 
00976 /* get minimal vector length value that can be discriminated.  */
00977 inline Real getVecEpsilon() { return (Real)VECTOR_EPSILON; }
00978 
00979 // a 3D integer vector
00980 typedef Vector3Dim<int> Vec3Int; 
00981 
00982 // a 3D vector 
00983 typedef Vector3Dim<Real> Vec3; 
00984 
00985 
00986 }; // namespace 
00987 
00988 
00989 #endif /* BASICVECTOR_H */