Blender V2.61 - r43446

ntl_vector3dim.h

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