gKitGL
Geometry.h
00001 /* version restructuree mailto:jean-claude.iehl@liris.cnrs.fr */
00002 
00003 /*
00004  * pbrt source code Copyright(c) 1998-2005 Matt Pharr and Greg Humphreys
00005  *
00006  * All Rights Reserved.
00007  * For educational use only; commercial use expressly forbidden.
00008  * NO WARRANTY, express or implied, for this software.
00009  * (See file License.txt for complete license)
00010  */
00011 
00012 #ifndef PBRT_GEOMETRY_H
00013 #define PBRT_GEOMETRY_H
00014 
00015 #include <algorithm>
00016 #include <iostream>
00017 #include <cstdlib>
00018 #include <cstdio>
00019 #include <cassert>
00020 #include <cmath>
00021 
00022 #include "Image.h"
00023 
00024 //! namespace pour regrouper les types et les fonctions.
00025 namespace gk {
00026 
00027 #define RAY_EPSILON 0.0001f
00028 #define EPSILON 0.00001f
00029 
00030 // Geometry Declarations
00031 class Point;
00032 class Normal;
00033 class Vector;
00034 
00035 //! \defgroup Geometry representation de points, vecteurs, normales, couleurs, etc.
00036 //@{
00037     
00038 //! point en dimension 2, utilise pour representer les coordonnees de textures d'un sommet, par exemple. 
00039 class Point2
00040 {
00041 public:
00042     // Vector Public Methods
00043 
00044     //! constructeur.
00045     Point2( const float _x = 0.f, const float _y = 0.f )
00046         : 
00047         x( _x ), y( _y )
00048     {}
00049     
00050     //! addition de 2 vecteurs, w= u + v, renvoie w.
00051     Point2 operator+( const Point2 &v ) const
00052     {
00053         return Point2( x + v.x, y + v.y );
00054     }
00055     
00056     //! addition de 2 vecteurs, u= u + v.
00057     Point2& operator+=( const Point2 &v )
00058     {
00059         x += v.x;
00060         y += v.y;
00061         
00062         return *this;
00063     }
00064     
00065     //! soustraction de 2 vecteurs, w = u - v, renvoie w.
00066     Point2 operator-( const Point2 &v ) const
00067     {
00068         return Point2( x - v.x, y - v.y );
00069     }
00070     
00071     //! soustraction de 2 vecteurs, u= u - v.
00072     Point2& operator-=( const Point2 &v )
00073     {
00074         x -= v.x;
00075         y -= v.y;
00076         
00077         return *this;
00078     }
00079     
00080     //! comparaison de 2 vecteurs.
00081     bool operator==( const Point2 &v ) const
00082     {
00083         return (x == v.x && y == v.y);
00084     }
00085     
00086     //! produit par un reel, w= k * u, renvoie w.
00087     Point2 operator*( const float f ) const
00088     {
00089         return Point2( f*x, f*y );
00090     }
00091     
00092     //! produit par un reel, u= k * u.
00093     Point2 &operator*=( const float f )
00094     {
00095         x *= f;
00096         y *= f;
00097         
00098         return *this;
00099     }
00100     
00101     //! division par un reel, w= u / k, renvoie w.
00102     Point2 operator/( const float f ) const
00103     {
00104         assert( f != 0 );
00105         float inv = 1.f / f;
00106         return Point2( x * inv, y * inv );
00107     }
00108     
00109     //! division par un reel, u= u / k.
00110     Point2 &operator/=( const float f )
00111     {
00112         assert( f != 0 );
00113         float inv = 1.f / f;
00114         x *= inv;
00115         y *= inv;
00116         
00117         return *this;
00118     }
00119     
00120     //! negation d'un vecteur, w= -u, renvoie w.
00121     Point2 operator-( ) const
00122     {
00123         return Point2( -x, -y );
00124     }
00125     
00126     //! renvoie une composante du vecteur.
00127     const float& operator[]( const unsigned int i ) const
00128     {
00129         return ( &x )[i];
00130     }
00131     
00132     //! renvoie reference sur une composante du vecteur.
00133     float &operator[]( const unsigned int i )
00134     {
00135         return ( &x )[i];
00136     }
00137     
00138     //! renvoie le carre de la longueur du vecteur.
00139     float LengthSquared() const 
00140     { 
00141         return x*x + y*y; 
00142     }
00143     
00144     //! renvoie la longueur du vecteur.
00145     float Length() const 
00146     {
00147         return sqrtf( LengthSquared() ); 
00148     }
00149     
00150     // Vector Public Data
00151     //! les 2 composantes du vecteur.
00152     float x, y;
00153 };
00154 
00155 //! vecteur en dimension 3.
00156 //! represente une direction, cf. Point et Normal pour representer un point et une normale.
00157 class Vector
00158 {
00159 public:
00160     // Vector Public Methods
00161     //! constructeur.
00162     Vector( const float _x = 0.f, const float _y = 0.f, const float _z = 0.f )
00163         : 
00164         x( _x ), y( _y ), z( _z )
00165     {}
00166     
00167     //! construit un vecteur a partir des coordonnees d'un point.
00168     explicit Vector( const Point &p );
00169     
00170     //! construit un vecteur a partir des coordonnees d'une normale.
00171     explicit Vector( const Normal &n );
00172     
00173     //! construit le vecteur pq, origine p, direction q - p.
00174     Vector( const Point& p, const Point& q );
00175     
00176     //! affiche un vecteur.
00177     void print( ) const
00178     {
00179         printf("% -.8f % -.8f % -.8f\n", x, y, z);
00180     }
00181     
00182     //! addition de 2 vecteurs, w= u + v, renvoie w.
00183     Vector operator+( const Vector &v ) const
00184     {
00185         return Vector( x + v.x, y + v.y, z + v.z );
00186     }
00187     
00188     //! addition de 2 vecteurs, u= u + v.
00189     Vector& operator+=( const Vector &v )
00190     {
00191         x += v.x;
00192         y += v.y;
00193         z += v.z;
00194         
00195         return *this;
00196     }
00197     
00198     //! soustraction de 2 vecteurs, w= u - v, renvoie w.
00199     Vector operator-( const Vector &v ) const
00200     {
00201         return Vector( x - v.x, y - v.y, z - v.z );
00202     }
00203     
00204     //! soustraction de 2 vecteurs, u= u - v.
00205     Vector& operator-=( const Vector &v )
00206     {
00207         x -= v.x;
00208         y -= v.y;
00209         z -= v.z;
00210         
00211         return *this;
00212     }
00213     
00214     //! comparaison de 2 vecteurs.
00215     bool operator==( const Vector &v ) const
00216     {
00217         return (x == v.x && y == v.y && z == v.z);
00218     }
00219     
00220     //! produit par un vector, w= k * u, renvoie w.
00221     Vector operator*( const Vector& v ) const
00222     {
00223         return Vector( v.x*x, v.y*y, v.z*z );
00224     }
00225     
00226     //! produit par un reel, w= k * u, renvoie w.
00227     Vector operator*( const float f ) const
00228     {
00229         return Vector( f*x, f*y, f*z );
00230     }
00231     
00232     //! produit par un reel, u= k * u.
00233     Vector &operator*=( const float f )
00234     {
00235         x *= f;
00236         y *= f;
00237         z *= f;
00238         
00239         return *this;
00240     }
00241     
00242     //! division par un reel, w= u / k, renvoie w.
00243     Vector operator/( const float f ) const
00244     {
00245         assert( f != 0 );
00246         float inv = 1.f / f;
00247         return Vector( x * inv, y * inv, z * inv );
00248     }
00249     
00250     //! division par un reel, u= u / k.
00251     Vector &operator/=( const float f )
00252     {
00253         assert( f != 0 );
00254         float inv = 1.f / f;
00255         x *= inv;
00256         y *= inv;
00257         z *= inv;
00258         
00259         return *this;
00260     }
00261     
00262     //! negation d'un vecteur, w= -u, renvoie w.
00263     Vector operator-( ) const
00264     {
00265         return Vector( -x, -y, -z );
00266     }
00267     
00268     //! renvoie une composante du vecteur.
00269     const float& operator[]( const unsigned int i ) const
00270     {
00271         return ( &x )[i];
00272     }
00273     
00274     //! renvoie une reference sur une composante du vecteur.
00275     float &operator[]( const unsigned int i )
00276     {
00277         return ( &x )[i];
00278     }
00279     
00280     //! renvoie le carre de la longueur du vecteur.
00281     float LengthSquared() const 
00282     { 
00283         return x*x + y*y + z*z; 
00284     }
00285     
00286     //! renvoie la longueur du vecteur.
00287     float Length() const 
00288     {
00289         return sqrtf( LengthSquared() ); 
00290     }
00291     
00292     // Vector Public Data
00293     //! composantes du vecteur.
00294     float x, y, z;
00295 };
00296 
00297 //! par habitude, declare le type Vecteur3
00298 typedef Vector Vector3;
00299 
00300 float Clamp( const float value , const float low, const float high );
00301 
00302 
00303 //! represente une quantite d'energie, un tuple <rgba>.
00304 class Color
00305 {
00306 public:
00307     // Color Public Methods
00308     //! constructeur.
00309     Color( )
00310         :
00311         r(0.f), g(0.f), b(0.f), a(1.f)
00312     {}
00313     
00314     Color( const float _r, const float _g, const float _b, const float _a= 1.f )
00315         : 
00316         r( _r ), g( _g ), b( _b ), a( _a )
00317     {}
00318     
00319     //! constructeur.
00320     Color( const float _v, const float _a= 1.f )
00321         :
00322         r( _v ), g( _v ), b( _v ), a( _a )
00323     {}
00324     
00325     //! constructeur, conversion depuis un HDRPixel.
00326     Color( const HDRPixel& pixel )
00327         :
00328         r(pixel.r),
00329         g(pixel.g),
00330         b(pixel.b),
00331         a(pixel.a)
00332     {}
00333     
00334     //! constructeur, conversion depuis un Pixel.
00335     Color( const Pixel& pixel )
00336         :
00337         r((float) pixel.r / 255.f),
00338         g((float) pixel.g / 255.f),
00339         b((float) pixel.b / 255.f),
00340         a((float) pixel.a / 255.f)
00341     {}
00342 
00343     operator Pixel( ) const
00344     {
00345         return Pixel(
00346             Clamp(r * 255.f, 0.f, 255.f), 
00347             Clamp(g * 255.f, 0.f, 255.f),
00348             Clamp(b * 255.f, 0.f, 255.f),
00349             Clamp(a * 255.f, 0.f, 255.f));
00350     }
00351     
00352     operator HDRPixel( ) const
00353     {
00354         return HDRPixel(r, g, b, a);
00355     }
00356     
00357     //! affiche une couleur.
00358     void print( ) const
00359     {
00360         printf("% -.6f % -.6f % -.6f % -.6f\n", r, g, b, a);
00361     }
00362         
00363     //! addition de 2 couleurs, w= u + v, renvoie w.
00364     Color operator+( const Color &v ) const
00365     {
00366         return Color( r + v.r, g + v.g, b + v.b, a + v.a );
00367     }
00368     
00369     //! addition de 2 vecteurs, u= u + v.
00370     Color& operator+=( const Color &v )
00371     {
00372         r += v.r;
00373         g += v.g;
00374         b += v.b;
00375         a+= v.a;
00376         
00377         return *this;
00378     }
00379     
00380     //! soustraction de 2 vecteurs, w= u - v, renvoie w.
00381     Color operator-( const Color &v ) const
00382     {
00383         return Color( r - v.r, g - v.g, b - v.b, a - v.a );
00384     }
00385     
00386     //! soustraction de 2 vecteurs, u= u - v.
00387     Color& operator-=( const Color &v )
00388     {
00389         r -= v.r;
00390         g -= v.g;
00391         b -= v.b;
00392         a -= v.a;
00393         
00394         return *this;
00395     }
00396     
00397     Color operator*( const Color& v ) const
00398     {
00399         return Color( r * v.r, g * v.g, b * v.b, a * v.a );
00400     }
00401     
00402     Color& operator*=( const Color& v)
00403     {
00404         r *= v.r;
00405         g *= v.g;
00406         b *= v.b;
00407         a *= v.a;
00408         
00409         return *this;
00410     }
00411     
00412     //! comparaison de 2 couleurs.
00413     bool operator==( const Color &v ) const
00414     {
00415         return (r == v.r && g == v.g && b == v.b && a == v.a );
00416     }
00417     
00418     //! produit par un reel, w= k * u, renvoie w.
00419     Color operator*( const float f ) const
00420     {
00421         return Color( f*r, f*g, f*b, f*a );
00422     }
00423     
00424     //! produit par un reel, u= k * u.
00425     Color &operator*=( const float f )
00426     {
00427         r *= f;
00428         g *= f;
00429         b *= f;
00430         a *= f;
00431         
00432         return *this;
00433     }
00434     
00435     //! division par un reel.
00436     Color operator/( const float f ) const
00437     {
00438         assert( f != 0 );
00439         float inv = 1.f / f;
00440         return Color( r * inv, g * inv, b * inv, a * inv );
00441     }
00442     
00443     //! division par un reel.
00444     Color &operator/=( const float f )
00445     {
00446         assert( f != 0 );
00447         float inv = 1.f / f;
00448         r *= inv;
00449         g *= inv;
00450         b *= inv;
00451         a *= inv;
00452         
00453         return *this;
00454     }
00455     
00456     //! negation d'un vecteur, w= -u, renvoie w.
00457     Color operator-( ) const
00458     {
00459         return Color( -r, -g, -b, -a );
00460     }
00461     
00462     //! renvoie la quantite d'energie associe
00463     float power( ) const
00464     {
00465         return (r + g + b) / 3.f;
00466     }
00467     
00468     //! renvoie vrai la quantite d'energie est nulle
00469     bool isBlack( ) const
00470     {
00471         return (r + g + b) == 0.f;
00472     }
00473     
00474     //! renvoie une composante du vecteur.
00475     const float& operator[]( const unsigned int i ) const
00476     {
00477         return ( &r )[i];
00478     }
00479     
00480     //! renvoie une reference sur une composante du vecteur.
00481     float &operator[]( const unsigned int i )
00482     {
00483         return ( &r )[i];
00484     }
00485     
00486     // Color Public Data
00487     //! composantes du vecteur.
00488     float r, g, b, a;
00489 };
00490 
00491 //! declare une couleur, un tripet <rgb> comme une couleur.
00492 typedef Color Energy;
00493 
00494 
00495 //! representation d'un point de dimension 3. memes operations que sur Vector.
00496 //! memes operations que sur un Vector. 
00497 class Point
00498 {
00499 public:
00500     // Point Methods
00501     Point( )
00502         :
00503         x(0.f), y(0.f), z(0.f)
00504     {}
00505     
00506     Point( const float v )
00507         :
00508         x(v), y(v), z(v)
00509     {}
00510     
00511     Point( const float _x, const float _y, const float _z )
00512         :
00513         x( _x ), y( _y ), z( _z )
00514     {}
00515     
00516     explicit Point( const Vector &v )
00517         : 
00518         x( v.x ), y( v.y ), z( v.z ) 
00519     {}
00520     
00521     //! affiche un point.
00522     void print( ) const
00523     {
00524         printf("%.10f %.10f %.10f\n", x, y, z);
00525     }
00526     
00527     //! addition d'un point et d'un vecteur, q= p + v, renvoie le point q.
00528     Point operator+( const Vector &v ) const
00529     {
00530         return Point( x + v.x, y + v.y, z + v.z );
00531     }
00532     
00533     //! addition d'un point et d'un vecteur, p= p + v.
00534     Point &operator+=( const Vector &v )
00535     {
00536         x += v.x;
00537         y += v.y;
00538         z += v.z;
00539         
00540         return *this;
00541     }
00542     
00543     //! soustraction de 2 points, v= p - q, renvoie le vecteur v.
00544     Vector operator-( const Point &q ) const
00545     {
00546         return Vector( x - q.x, y - q.y, z - q.z );
00547     }
00548     
00549     //! soustraction d'un point et d'un vecteur, q= p - v, renvoie le point q.
00550     Point operator-( const Vector &v ) const
00551     {
00552         return Point( x - v.x, y - v.y, z - v.z );
00553     }
00554     
00555     //! soutraction d'un point et d'un vecteur, p= p - v.
00556     Point &operator-=( const Vector &v )
00557     {
00558         x -= v.x;
00559         y -= v.y;
00560         z -= v.z;
00561         
00562         return *this;
00563     }
00564     
00565     //! addition de 2 points, ca n'existe pas, mais c'est pratique ! p= p + q.
00566     Point &operator+=( const Point &q )
00567     {
00568         x += q.x;
00569         y += q.y;
00570         z += q.z;
00571         
00572         return *this;
00573     }
00574     
00575     Point operator+( const Point &q ) const
00576     {
00577         return Point( x + q.x, y + q.y, z + q.z );
00578     }
00579     
00580     Point operator*( const float f ) const
00581     {
00582         return Point( f*x, f*y, f*z );
00583     }
00584     
00585     Point &operator*=( const float f )
00586     {
00587         x *= f;
00588         y *= f;
00589         z *= f;
00590         
00591         return *this;
00592     }
00593     
00594     Point operator/ ( const float f ) const
00595     {
00596         float inv = 1.f / f;
00597         return Point( inv*x, inv*y, inv*z );
00598     }
00599     
00600     Point &operator/=( const float f )
00601     {
00602         float inv = 1.f / f;
00603         x *= inv;
00604         y *= inv;
00605         z *= inv;
00606         
00607         return *this;
00608     }
00609     
00610     bool operator== ( const Point& p ) const
00611     {
00612         return (x == p.x && y == p.y && z == p.z);
00613     }
00614     
00615     const float& operator[]( const unsigned int i ) const
00616     {
00617         return ( &x )[i];
00618     }
00619     
00620     float &operator[]( const unsigned int i )
00621     {
00622         return ( &x )[i];
00623     }
00624     
00625     // Point Public Data
00626     float x, y, z;
00627 };
00628 
00629 //! representation d'un point homogene de dimension 4, transformation d'un Point par une projection (cf Perspective() et Transform).
00630 class HPoint
00631 {
00632 public:
00633     // Point Methods
00634     //! constructeur.
00635     HPoint( const float _x = 0.f, const float _y = 0.f, const float _z = 0.f, const float _w= 1.f )
00636         :
00637         x( _x ), y( _y ), z( _z ), w( _w )
00638     {}
00639     
00640     //! construit un point homogene a partir d'un point 3d.
00641     HPoint( const Point& p )
00642         :
00643         x(p.x), y(p.y), z(p.z), w(1.f)
00644     {}
00645     
00646     //! renvoie le point 3d associe au point homogene.
00647     Point project( ) const
00648     {
00649         assert( w != 0.f );
00650         return Point(x / w, y / w, z / w);
00651     }
00652     
00653     //! determine si le point est visible apres avoir subit une projection, cf Perspective() et Transform.
00654     bool isVisible( ) const
00655     {
00656         return 
00657           (-w < x && x < w
00658         && -w < y && y < w
00659         && -w < z && z < w);
00660     }
00661 
00662     //! determine si le point est rejette apres avoir subit une projection, cf isVisible().
00663     bool isCulled( ) const
00664     {
00665         return !isVisible();
00666     }
00667     
00668     //! acces indexe aux composantes du point, \param i compris entre 0 et 3 inclus.
00669     const float& operator[]( const unsigned int i ) const
00670     {
00671         return ( &x )[i];
00672     }
00673     
00674     //! acces indexe aux composantes du point, \param i compris entre 0 et 3 inclus.
00675     float &operator[]( const unsigned int i )
00676     {
00677         return ( &x )[i];
00678     }
00679     
00680     //! acces direct aux composantes du point homogene.
00681     float x, y, z, w;
00682 };
00683 
00684 //! representation d'une normale de dimension 3, cf. Vector pour la description des operations.
00685 class Normal
00686 {
00687 public:
00688     // Normal Methods
00689     Normal( const float _x = 0.f, const float _y = 0.f, const float _z = 0.f )
00690         : 
00691         x( _x ), y( _y ), z( _z ) 
00692     {}
00693     
00694     Normal operator-( ) const
00695     {
00696         return Normal( -x, -y, -z );
00697     }
00698     
00699     Normal operator+ ( const Normal &v ) const
00700     {
00701         return Normal( x + v.x, y + v.y, z + v.z );
00702     }
00703     
00704     Normal& operator+=( const Normal &v )
00705     {
00706         x += v.x;
00707         y += v.y;
00708         z += v.z;
00709         
00710         return *this;
00711     }
00712     
00713     Normal operator- ( const Normal &v ) const
00714     {
00715         return Normal( x - v.x, y - v.y, z - v.z );
00716     }
00717     
00718     Normal& operator-=( const Normal &v )
00719     {
00720         x -= v.x;
00721         y -= v.y;
00722         z -= v.z;
00723         
00724         return *this;
00725     }
00726     
00727     Normal operator*( const float f ) const
00728     {
00729         return Normal( f*x, f*y, f*z );
00730     }
00731     
00732     Normal &operator*=( const float f )
00733     {
00734         x *= f;
00735         y *= f;
00736         z *= f;
00737         
00738         return *this;
00739     }
00740     
00741     Normal operator/ ( const float f ) const
00742     {
00743         float inv = 1.f / f;
00744         return Normal( x * inv, y * inv, z * inv );
00745     }
00746     
00747     Normal &operator/=( float f )
00748     {
00749         float inv = 1.f / f;
00750         x *= inv;
00751         y *= inv;
00752         z *= inv;
00753         
00754         return *this;
00755     }
00756     
00757     float LengthSquared() const
00758     {
00759         return x*x + y*y + z*z;
00760     }
00761     
00762     float Length() const
00763     {
00764         return sqrtf( LengthSquared() );
00765     }
00766     
00767     explicit Normal( const Vector &v )
00768         : 
00769         x( v.x ), y( v.y ), z( v.z ) 
00770     {}
00771     
00772     const float& operator[]( const unsigned int i ) const 
00773     {
00774         return ( &x )[i];
00775     }
00776     
00777     float &operator[]( const unsigned int i )
00778     {
00779         return ( &x )[i]; 
00780     }
00781     
00782     // Normal Public Data
00783     float x, y, z;
00784 };
00785 
00786 typedef Normal Tangent; //!< une tangente se transforme de la meme maniere qu'une normale.
00787 
00788 
00789 //! representation minimale d'un rayon.
00790 struct BasicRay
00791 {
00792     // Ray Public Methods
00793     BasicRay( const unsigned int _id= -1 )
00794         : 
00795         tmax( HUGE_VAL ),
00796         id(_id)
00797         //~ , intersect(0),
00798         //~ intersect_bounds(0)
00799     {}
00800 
00801     //! constructeur (origine, direction). direction est un vecteur unitaire.
00802     BasicRay( const Point &origin, const Vector &direction,
00803         const unsigned int _id= -1 )
00804         : 
00805         o( origin ), 
00806         tmax( HUGE_VAL ),
00807         d( direction ), 
00808         id(_id)
00809         //~ , intersect(0),
00810         //~ intersect_bounds(0)
00811     {}
00812     
00813     //! constructeur (origine, destination).
00814     BasicRay( const Point &origin, const Point& destination,
00815         const unsigned int _id= -1 )
00816         :
00817         o( origin ),
00818         tmax( 1.f - RAY_EPSILON ),
00819         d( origin, destination ), 
00820         id(_id)
00821         //~ , intersect(0),
00822         //~ intersect_bounds(0)
00823     {}
00824     
00825     //! construit le point a l'abscisse 't'.
00826     Point operator( )( const float t ) const
00827     {
00828         return o + d * t; 
00829     }
00830     
00831     // Ray Public Data
00832     Point o;    //!< origine.
00833     float tmax;   //!< intervalle valide le long du rayon.
00834     Vector d;   //!< direction.
00835     unsigned int id;    //!< identifiant du rayon
00836     
00837     //~ mutable unsigned int intersect;
00838     //~ mutable unsigned int intersect_bounds;
00839 };
00840 
00841 
00842 //! representation 'pre-calculee' d'un rayon.
00843 struct Ray : public BasicRay
00844 {
00845     // Ray Public Methods
00846     Ray()
00847         : 
00848         BasicRay()
00849     {}
00850 
00851     //! constructeur (origine, direction). direction est un vecteur unitaire.
00852     Ray( const Point &origin, const Vector &direction,
00853         const float start = RAY_EPSILON, const float end = HUGE_VAL,
00854         unsigned int _id= -1)
00855         : 
00856         //~ BasicRay(origin, direction, start, end, id)
00857         BasicRay(origin, direction, id)
00858     {
00859         inv_d= Vector(1.f / d.x, 1.f / d.y, 1.f / d.z);
00860         sign_d[0]= (inv_d[0] < 0.f) ? 1 : 0;
00861         sign_d[1]= (inv_d[1] < 0.f) ? 1 : 0;
00862         sign_d[2]= (inv_d[2] < 0.f) ? 1 : 0;
00863         sign_d[3]= 0;
00864     }
00865     
00866     //! constructeur (origine, destination).
00867     Ray( const Point &origin, const Point& destination,
00868         const float start = RAY_EPSILON, const float end = 1.f - RAY_EPSILON,
00869         unsigned int _id= -1 )
00870         :
00871         //~ BasicRay(origin, destination, start, end, id )
00872         BasicRay(origin, destination, id )
00873     {
00874         inv_d= Vector(1.f / d.x, 1.f / d.y, 1.f / d.z);
00875         sign_d[0]= (inv_d[0] < 0.f) ? 1 : 0;
00876         sign_d[1]= (inv_d[1] < 0.f) ? 1 : 0;
00877         sign_d[2]= (inv_d[2] < 0.f) ? 1 : 0;
00878         sign_d[3]= 0;
00879     }
00880     
00881     //! renvoie vrai si la direction du rayon est < 0 pour l'axe 'axis'.
00882     bool isBackward( const int axis ) const
00883     {
00884         return (sign_d[axis]);
00885     }
00886     
00887     Vector inv_d;       //!< 1 / direction.
00888     unsigned char sign_d[4];    //!< vrai (==1) si direction[i] < 0.
00889 };
00890 
00891 
00892 //! representation d'un point d'intersection rayon / objet.
00893 struct Hit
00894 {
00895     Hit( )
00896         :
00897         tmin(RAY_EPSILON),
00898         t(HUGE_VAL),
00899         object_id(-1), 
00900         node_id(-1),
00901         child_id(-1),
00902         user_data(0.f)
00903     {}
00904     
00905     Hit( const Ray& ray )
00906         :
00907         //~ tmin(ray.tmin),
00908         tmin(RAY_EPSILON),
00909         t(ray.tmax),
00910         object_id(-1),
00911         node_id(-1),
00912         child_id(-1),
00913         user_data(0.f)
00914     {}
00915     
00916     ~Hit( ) {}
00917     
00918     // Hit public data
00919     Point p;    //!< point d'intersection
00920     Normal n;   //!< normale
00921     Tangent t1, t2;      //!< repere tangent
00922     float tmin;    //!< abscisse min le long du rayon
00923     float t;    //!< abscisse le long du rayon
00924     float u, v; //!< coordonnees de textures / parametres de surface
00925     int object_id;      //!< identifiant de l'objet/triangle intersecte
00926     int node_id;      //!< identifiant du noeud / pere du noeud intersecte
00927     int child_id;       //! identifiant du fils intersecte
00928     float user_data;    //!< donnee collectee pendant le suivi de rayon
00929 };
00930 
00931 
00932 //! representation d'une boite englobante alignee sur les axes (aabox).
00933 class BBox
00934 {
00935 public:
00936     // BBox Public Methods
00937     //! constructeur par defaut.
00938     BBox()
00939     {
00940         clear();
00941     }
00942     
00943     //! re-initialise les extremites.
00944     void clear( )
00945     {
00946         pMin = Point( (float) HUGE_VAL,  (float) HUGE_VAL,  (float) HUGE_VAL );
00947         pMax = Point( (float) -HUGE_VAL, (float) -HUGE_VAL, (float) -HUGE_VAL );
00948     }
00949     
00950     //! construction de l'aabbox d'un point, cf. Union( aabox, q ) pour ajouter d'autres points.
00951     BBox( const Point &p ) 
00952         : 
00953         pMin( p ), pMax( p ) 
00954     { }
00955     
00956     //! construction d'une aabox connaissant 2 points.
00957     BBox( const Point &p1, const Point &p2 )
00958     {
00959         pMin = Point( 
00960             std::min( p1.x, p2.x ),
00961             std::min( p1.y, p2.y ),
00962             std::min( p1.z, p2.z ) );
00963         
00964         pMax = Point( 
00965             std::max( p1.x, p2.x ),
00966             std::max( p1.y, p2.y ),
00967             std::max( p1.z, p2.z ) );
00968     }
00969     
00970     friend inline std::ostream &
00971     operator<<( std::ostream &os, const BBox &b );
00972     
00973     void print( ) const
00974     {
00975         printf("[ %.10f %.10f %.10f ] x [ %.10f %.10f %.10f ] ", 
00976             pMin.x, pMin.y, pMin.z, 
00977             pMax.x, pMax.y, pMax.z);
00978         
00979         Vector d(pMin, pMax);
00980         printf("extents (%.10f %.10f %.10f)\n",
00981             d.x, d.y, d.z);
00982     }
00983     
00984     //! ajoute un point dans l'aabox.
00985     friend BBox Union( const BBox &b, const Point &p );
00986     
00987     //! ajoute une autre aabox.
00988     friend BBox Union( const BBox &b, const BBox &b2 );
00989     
00990     //! ajoute une autre aabox
00991     void Union( const BBox& bbox )
00992     {
00993     #if 0
00994         pMin.x= std::min(pMin.x, bbox.pMin.x);
00995         pMin.y= std::min(pMin.y, bbox.pMin.y);
00996         pMin.z= std::min(pMin.z, bbox.pMin.z);
00997         pMax.x= std::max(pMax.x, bbox.pMax.x);
00998         pMax.y= std::max(pMax.y, bbox.pMax.y);
00999         pMax.z= std::max(pMax.z, bbox.pMax.z);        
01000     #else
01001         // plus rapide ... 
01002         if(bbox.pMin.x < pMin.x)
01003             pMin.x= bbox.pMin.x;
01004         if(bbox.pMin.y < pMin.y)
01005             pMin.y= bbox.pMin.y;
01006         if(bbox.pMin.z < pMin.z)
01007             pMin.z= bbox.pMin.z;
01008         
01009         if(bbox.pMax.x > pMax.x)
01010             pMax.x= bbox.pMax.x;
01011         if(bbox.pMax.y > pMax.y)
01012             pMax.y= bbox.pMax.y;
01013         if(bbox.pMax.z > pMax.z)
01014             pMax.z= bbox.pMax.z;
01015     #endif
01016     }
01017     
01018     //! ajoute un point a la bbox.
01019     void Union( const Point& p )
01020     {
01021     #if 0
01022         pMin.x= std::min(pMin.x, p.x);
01023         pMin.y= std::min(pMin.y, p.y);
01024         pMin.z= std::min(pMin.z, p.z);
01025         pMax.x= std::max(pMax.x, p.x);
01026         pMax.y= std::max(pMax.y, p.y);
01027         pMax.z= std::max(pMax.z, p.z);
01028     #else
01029         // plus rapide ... 
01030         if(p.x < pMin.x)
01031             pMin.x= p.x;
01032         if(p.y < pMin.y)
01033             pMin.y= p.y;
01034         if(p.z < pMin.z)
01035             pMin.z= p.z;
01036         
01037         if(p.x > pMax.x)
01038             pMax.x= p.x;
01039         if(p.y > pMax.y)
01040             pMax.y= p.y;
01041         if(p.z > pMax.z)
01042             pMax.z= p.z;
01043     #endif
01044     }
01045     
01046     //! verifie l'intersection de 2 aabbox.
01047     bool Overlaps( const BBox &b ) const
01048     {
01049         bool x = ( pMax.x >= b.pMin.x ) && ( pMin.x <= b.pMax.x );
01050         bool y = ( pMax.y >= b.pMin.y ) && ( pMin.y <= b.pMax.y );
01051         bool z = ( pMax.z >= b.pMin.z ) && ( pMin.z <= b.pMax.z );
01052         return ( x && y && z );
01053     }
01054     
01055     void Intersection( const BBox& b )
01056     {
01057         pMin.x= std::max(pMin.x, b.pMin.x);
01058         pMin.y= std::max(pMin.y, b.pMin.y);
01059         pMin.z= std::max(pMin.z, b.pMin.z);
01060         pMax.x= std::min(pMax.x, b.pMax.x);
01061         pMax.y= std::min(pMax.y, b.pMax.y);
01062         pMax.z= std::min(pMax.z, b.pMax.z);        
01063     }
01064     
01065     friend BBox Intersection( const BBox& a, const BBox& b );
01066     
01067     bool isEmpty( ) const
01068     {
01069         bool x = ( pMax.x < pMin.x );
01070         bool y = ( pMax.y < pMin.y );
01071         bool z = ( pMax.z < pMin.z );
01072         return ( x && y && z );
01073     }
01074     
01075     //! verifie l'inclusion d'un point dans l'aabox.
01076     bool Inside( const Point &pt ) const
01077     {
01078         return ( pt.x >= pMin.x && pt.x <= pMax.x 
01079             && pt.y >= pMin.y && pt.y <= pMax.y 
01080             && pt.z >= pMin.z && pt.z <= pMax.z );
01081     }
01082     
01083     //! dilate l'aabox de 'delta' dans toutes les directions.
01084     void Expand( float delta )
01085     {
01086         pMin -= Vector( delta, delta, delta );
01087         pMax += Vector( delta, delta, delta );
01088     }
01089     
01090     //! renvoie le centre de la boite.
01091     const Point getCenter( ) const
01092     {
01093         return (pMin + pMax) * .5f;
01094     }
01095     
01096     //! renvoie le centre de la boite, sur un axe particulier.
01097     float getCenter( const int axis) const
01098     {
01099         return (pMin[axis] + pMax[axis]) * .5f;
01100     }
01101     
01102     //! renvoie le centre de la boite
01103     void getCenter( Point& center ) const
01104     {
01105         center= getCenter();
01106     }
01107     
01108     //! renvoie le volume de l'aabox.
01109     float Volume( ) const
01110     {
01111         const Vector d(pMin, pMax);
01112         return d.x * d.y * d.z;
01113     }
01114     
01115     //! renvoie l'aire de l'aabox
01116     float SurfaceArea( ) const
01117     {
01118         const Vector d(pMin, pMax);
01119         const float area= 2.f * d.x * d.y + 2.f * d.x * d.z + 2.f * d.y * d.z;
01120         return area;
01121     }
01122     
01123     //! renvoie l'indice de l'axe le plus long de l'aabox, 0 pour X, 1 pour Y et 2 pour Z.
01124     int MaximumExtent( ) const
01125     {
01126         const Vector d(pMin, pMax);
01127         if ( d.x > d.y && d.x > d.z )
01128             return 0;
01129         if ( d.y > d.z )
01130             return 1;
01131         else
01132             return 2;
01133     }
01134     
01135     //! renvoie une sphere englobante de l'aabox.
01136     void BoundingSphere( Point &c, float &r ) const;
01137     
01138     //! intersection avec rayon.
01139     //! renvoie faux si une intersection existe mais n'est pas dans l'intervalle [0 htmax]. \n
01140     //! renvoie vrai + la position du point d'entree (rtmin) et celle du point de sortie (rtmax). \n
01141     /*! "An Efficient and Robust Ray-Box Intersection Algorithm"
01142         cf http://cag.csail.mit.edu/%7Eamy/papers/box-jgt.pdf
01143     */
01144     
01145     /*! le parametre htmax permet de trouver tres facilement l'intersection la plus proche de l'origine du rayon.
01146     \code
01147         float t= ray.tmax;      // ou t= HUGE_VAL; la plus grande distance le long du rayon.
01148         // rechercher la bbox la plus proche de l'origine du rayon
01149         for(int i= 0; i < n; i++)
01150         {
01151             float tmin;
01152             float tmax;
01153             if(bbox[i].Intersect(ray, t, tmin, tmax))
01154                 // t= tmin; ne suffit pas si l'intervalle [tmin tmax] est en partie negatif, tmin < 0
01155                 t= std::max(0.f, tmin);
01156         }
01157     \endcode
01158     */
01159     bool Intersect( const Ray &ray, const float htmax, 
01160         float &rtmin, float &rtmax ) const
01161     {
01162         float tmin= ((*this)[ray.sign_d[0]].x - ray.o.x) * ray.inv_d.x;
01163         float tmax= ((*this)[1u - ray.sign_d[0]].x - ray.o.x) * ray.inv_d.x;
01164         
01165         // y slab
01166         const float tymin= ((*this)[ray.sign_d[1]].y - ray.o.y) * ray.inv_d.y;
01167         const float tymax= ((*this)[1u - ray.sign_d[1]].y - ray.o.y) * ray.inv_d.y;
01168 
01169         if((tmin > tymax) || (tymin > tmax))
01170             return false;
01171         if(tymin > tmin)
01172             tmin= tymin;
01173         if(tymax < tmax)
01174             tmax= tymax;
01175         
01176         // z slab
01177         const float tzmin= ((*this)[ray.sign_d[2]].z - ray.o.z) * ray.inv_d.z;
01178         const float tzmax= ((*this)[1u - ray.sign_d[2]].z - ray.o.z) * ray.inv_d.z;
01179 
01180         if((tmin > tzmax) || (tzmin > tmax))
01181             return false;
01182         if(tzmin > tmin)
01183             tmin= tzmin;
01184         if(tzmax < tmax)
01185             tmax= tzmax;
01186         
01187         // ne renvoie vrai que si l'intersection est valide
01188         rtmin= tmin;
01189         rtmax= tmax;
01190         //~ return ((tmin < htmax) && (tmax > ray.tmin));
01191         return ((tmin < htmax) && (tmax > RAY_EPSILON));
01192     }
01193 
01194     bool Occluded( const Ray& ray ) const
01195     {
01196         float rtmin;
01197         float rtmax;
01198         return Intersect(ray, ray.tmax, rtmin, rtmax);
01199     }
01200     
01201     bool Occluded( const Ray& ray, const float tmax ) const
01202     {
01203         float rtmin;
01204         float rtmax;
01205         return Intersect(ray, tmax, rtmin, rtmax);
01206     }
01207     
01208     //! renvoie egalement la normale de l'intersection.
01209     bool Intersect( const Ray &ray, const float htmax, 
01210         float &rtmin, float &rtmax, Normal& rn ) const
01211     {
01212         Normal n(-1.f, 0.f, 0.f);
01213         float tmin= ((*this)[ray.sign_d[0]].x - ray.o.x) * ray.inv_d.x;
01214         float tmax= ((*this)[1 - ray.sign_d[0]].x - ray.o.x) * ray.inv_d.x;
01215         
01216         // y slab
01217         const float tymin= ((*this)[ray.sign_d[1]].y - ray.o.y) * ray.inv_d.y;
01218         const float tymax= ((*this)[1 - ray.sign_d[1]].y - ray.o.y) * ray.inv_d.y;
01219 
01220         if((tmin > tymax) || (tymin > tmax))
01221             return false;
01222         if(tymin > tmin)
01223         {
01224             tmin= tymin;
01225             n= Normal(0.f, -1.f, 0.f);
01226         }
01227         if(tymax < tmax)
01228             tmax= tymax;
01229         
01230         // z slab
01231         const float tzmin= ((*this)[ray.sign_d[2]].z - ray.o.z) * ray.inv_d.z;
01232         const float tzmax= ((*this)[1 - ray.sign_d[2]].z - ray.o.z) * ray.inv_d.z;
01233 
01234         if((tmin > tzmax) || (tzmin > tmax))
01235             return false;
01236         if(tzmin > tmin)
01237         {
01238             tmin= tzmin;
01239             n= Normal(0.f, 0.f, -1.f);
01240         }
01241         if(tzmax < tmax)
01242             tmax= tzmax;
01243         
01244         // ne renvoie vrai que si l'intersection est valide
01245         rtmin= tmin;
01246         rtmax= tmax;
01247         rn= n;
01248         //~ return ((tmin < htmax) && (tmax > ray.tmin));
01249         return ((tmin < htmax) && (tmax > RAY_EPSILON));
01250     }
01251 
01252     //! intersection avec un rayon.
01253     bool Intersect( const BasicRay &ray, const float htmax, 
01254         float &rtmin, float &rtmax ) const
01255     {
01256         unsigned int sign_d[4];
01257         Vector inv_d= Vector(1.f / ray.d.x, 1.f / ray.d.y, 1.f / ray.d.z);
01258         
01259         sign_d[0]= (inv_d[0] < 0.f) ? 1u : 0u;
01260         float tmin= ((*this)[sign_d[0]].x - ray.o.x) * inv_d.x;
01261         float tmax= ((*this)[1u - sign_d[0]].x - ray.o.x) * inv_d.x;
01262         
01263         // y slab
01264         sign_d[1]= (inv_d[1] < 0.f) ? 1u : 0u;
01265         const float tymin= ((*this)[sign_d[1]].y - ray.o.y) * inv_d.y;
01266         const float tymax= ((*this)[1u - sign_d[1]].y - ray.o.y) * inv_d.y;
01267 
01268         if((tmin > tymax) || (tymin > tmax))
01269             return false;
01270         if(tymin > tmin)
01271             tmin= tymin;
01272         if(tymax < tmax)
01273             tmax= tymax;
01274         
01275         // z slab
01276         sign_d[2]= (inv_d[2] < 0.f) ? 1u : 0u;
01277         const float tzmin= ((*this)[sign_d[2]].z - ray.o.z) * inv_d.z;
01278         const float tzmax= ((*this)[1u - sign_d[2]].z - ray.o.z) * inv_d.z;
01279 
01280         if((tmin > tzmax) || (tzmin > tmax))
01281             return false;
01282         if(tzmin > tmin)
01283             tmin= tzmin;
01284         if(tzmax < tmax)
01285             tmax= tzmax;
01286         
01287         // ne renvoie vrai que si l'intersection est valide
01288         rtmin= tmin;
01289         rtmax= tmax;
01290         //~ return ((tmin < htmax) && (tmax > ray.tmin));
01291         return ((tmin < htmax) && (tmax > RAY_EPSILON));
01292     }
01293 
01294     bool Occluded( const BasicRay& ray ) const
01295     {
01296         float rtmin;
01297         float rtmax;
01298         return Intersect(ray, ray.tmax, rtmin, rtmax);
01299     }
01300     
01301     bool Occluded( const BasicRay& ray, const float tmax ) const
01302     {
01303         float rtmin;
01304         float rtmax;
01305         return Intersect(ray, tmax, rtmin, rtmax);
01306     }    
01307     
01308     //! acces indexe aux extremes de l'aabox.
01309     Point& operator[] ( const int id )
01310     {
01311         assert(id == 0 || id == 1);
01312         return (&pMin)[id];
01313     }
01314 
01315     //! acces indexe aux extremes de l'aabox.
01316     const Point& operator[] ( const int id ) const
01317     {
01318         assert(id == 0 || id == 1);
01319         return (&pMin)[id];
01320     }
01321     
01322     // BBox Public Data
01323     //! points extremes de l'aabox.
01324     Point pMin, pMax;
01325 };
01326 
01327 
01328 // Geometry Inline Functions
01329 inline 
01330 Vector::Vector( const Point &p )
01331     : 
01332     x( p.x ), y( p.y ), z( p.z )
01333 {}
01334 
01335 inline
01336 Vector::Vector( const Point& p, const Point& q )
01337     :
01338     x( q.x - p.x ), y( q.y - p.y ), z( q.z - p.z )
01339 {}
01340 
01341 inline 
01342 std::ostream &operator<<( std::ostream &os, const Vector &v )
01343 {
01344     os << v.x << ", " << v.y << ", " << v.z;
01345     return os;
01346 }
01347 
01348 //! scalaire * vecteur.
01349 inline 
01350 Vector operator*( float f, const Vector &v )
01351 {
01352     return v*f;
01353 }
01354 
01355 //! produit scalaire de 2 vecteurs.
01356  inline 
01357 float Dot( const Vector &v1, const Vector &v2 )
01358 {
01359     return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
01360 }
01361 
01362 //! valeur absolue du produit scalaire de 2 vecteurs.
01363  inline 
01364 float AbsDot( const Vector &v1, const Vector &v2 )
01365 {
01366     return fabsf( Dot( v1, v2 ) );
01367 }
01368 
01369 //! max(0, dot) du produit scalaire de 2 vecteurs.
01370  inline 
01371 float ZeroDot( const Vector &v1, const Vector &v2 )
01372 {
01373     return std::max( 0.f, Dot( v1, v2 ) );
01374 }
01375 
01376 //! produit vectoriel de 2 vecteurs.
01377  inline 
01378 Vector Cross( const Vector &v1, const Vector &v2 )
01379 {
01380     return Vector(
01381         ( v1.y * v2.z ) - ( v1.z * v2.y ),
01382         ( v1.z * v2.x ) - ( v1.x * v2.z ),
01383         ( v1.x * v2.y ) - ( v1.y * v2.x ) );
01384 }
01385 
01386 //! produit vectoriel d'un vecteur et d'une normale.
01387  inline 
01388 Vector Cross( const Vector &v1, const Normal &v2 )
01389 {
01390     return Vector(
01391         ( v1.y * v2.z ) - ( v1.z * v2.y ),
01392         ( v1.z * v2.x ) - ( v1.x * v2.z ),
01393         ( v1.x * v2.y ) - ( v1.y * v2.x ) );
01394 }
01395 
01396 //! produit vectoriel d'une normale et d'un vecteur.
01397  inline 
01398 Vector Cross( const Normal &v1, const Vector &v2 )
01399 {
01400     return Vector(
01401         ( v1.y * v2.z ) - ( v1.z * v2.y ),
01402         ( v1.z * v2.x ) - ( v1.x * v2.z ),
01403         ( v1.x * v2.y ) - ( v1.y * v2.x ) );
01404 }
01405 
01406 //! renvoie un vecteur de longueur 1 de meme direction que v.
01407 inline 
01408 Vector Normalize( const Vector &v )
01409 {
01410     return v / v.Length();
01411 }
01412 
01413 //! construit un repere orthogonal dont la normale est aligne sur un vecteur v1, v2 et v3 sont les 2 tangentes.
01414 inline 
01415 void CoordinateSystem( const Vector &v1, Vector *v2, Vector *v3 )
01416 {
01417     if ( fabsf( v1.x ) > fabsf( v1.y ) )
01418     {
01419         float invLen = 1.f / sqrtf( v1.x * v1.x + v1.z * v1.z );
01420         *v2 = Vector( -v1.z * invLen, 0.f, v1.x * invLen );
01421     }
01422     else
01423     {
01424         float invLen = 1.f / sqrtf( v1.y * v1.y + v1.z * v1.z );
01425         *v2 = Vector( 0.f, v1.z * invLen, -v1.y * invLen );
01426     }
01427     
01428     *v3 = Cross( v1, *v2 );
01429     //~ *v3 = Cross( *v2, v1 );
01430 }
01431 
01432 //! renvoie la distance entre 2 points.
01433 inline 
01434 float Distance( const Point &p1, const Point &p2 )
01435 {
01436     return ( p1 - p2 ).Length();
01437 }
01438 
01439 //! renvoie le carre de la distance entre 2 points.
01440 inline 
01441 float DistanceSquared( const Point &p1, const Point &p2 )
01442 {
01443     return ( p1 - p2 ).LengthSquared();
01444 }
01445 
01446 //! scalaire * point.
01447 inline 
01448 Point operator*( float f, const Point &p )
01449 {
01450     return p*f;
01451 }
01452 
01453 //! scalaire * normale.
01454 inline 
01455 Normal operator*( float f, const Normal &n )
01456 {
01457     return Normal( f*n.x, f*n.y, f*n.z );
01458 }
01459 
01460 //! renvoie une normale de meme direction, mais de longeur 1.
01461  inline 
01462 Normal Normalize( const Normal &n )
01463 {
01464     return n / n.Length();
01465 }
01466 
01467 inline 
01468 Vector::Vector( const Normal &n )
01469     :
01470     x( n.x ), y( n.y ), z( n.z )
01471 {}
01472 
01473 //! produit scalaire d'une normale et d'un vecteur.
01474  inline 
01475 float Dot( const Normal &n1, const Vector &v2 )
01476 {
01477     return n1.x * v2.x + n1.y * v2.y + n1.z * v2.z;
01478 }
01479 
01480 //! produit scalaire d'un vecteur et d'une normale.
01481  inline 
01482 float Dot( const Vector &v1, const Normal &n2 )
01483 {
01484     return v1.x * n2.x + v1.y * n2.y + v1.z * n2.z;
01485 }
01486 
01487 //! produit scalaire de 2 normales.
01488  inline 
01489 float Dot( const Normal &n1, const Normal &n2 )
01490 {
01491     return n1.x * n2.x + n1.y * n2.y + n1.z * n2.z;
01492 }
01493 
01494 //! valeur absolue du produit scalaire d'une normale et d'un vecteur.
01495  inline 
01496 float AbsDot( const Normal &n1, const Vector &v2 )
01497 {
01498     return fabsf( n1.x * v2.x + n1.y * v2.y + n1.z * v2.z );
01499 }
01500 
01501 //! valeur absolue du produit scalaire d'un vecteur et d'une normale.
01502  inline 
01503 float AbsDot( const Vector &v1, const Normal &n2 )
01504 {
01505     return fabsf( v1.x * n2.x + v1.y * n2.y + v1.z * n2.z );
01506 }
01507 
01508 //! valeur absolue du produit scalaire de 2 normales.
01509  inline 
01510 float AbsDot( const Normal &n1, const Normal &n2 )
01511 {
01512     return fabsf( n1.x * n2.x + n1.y * n2.y + n1.z * n2.z );
01513 }
01514 
01515 //! max(0, dot) du produit scalaire de 2 vecteurs.
01516  inline 
01517 float ZeroDot( const Normal &v1, const Vector &v2 )
01518 {
01519     return std::max( 0.f, Dot( v1, v2 ) );
01520 }
01521 
01522 //! max(0, dot) du produit scalaire de 2 vecteurs.
01523  inline 
01524 float ZeroDot( const Vector &v1, const Normal &v2 )
01525 {
01526     return std::max( 0.f, Dot( v1, v2 ) );
01527 }
01528 
01529 //! max(0, dot) du produit scalaire de 2 vecteurs.
01530  inline 
01531 float ZeroDot( const Normal &v1, const Normal &v2 )
01532 {
01533     return std::max( 0.f, Dot( v1, v2 ) );
01534 }
01535 
01536  inline 
01537 std::ostream &operator<<( std::ostream &os, const Normal &v )
01538 {
01539     os << v.x << ", " << v.y << ", " << v.z;
01540     return os;
01541 }
01542 
01543 inline 
01544 std::ostream &operator<<( std::ostream &os, const BBox &b )
01545 {
01546     os << b.pMin << " -> " << b.pMax;
01547     return os;
01548 }
01549 
01550 //! interpolation lineaire entre 2 reels, x= (1 - t) v1 + t v2 
01551  inline 
01552 float Lerp( const float t, const float v1, const float v2 ) 
01553 {
01554     return (1.f - t) * v1 + t * v2;
01555 }
01556 
01557 //! limite une valeur entre un min et un max.
01558 inline 
01559 float Clamp( const float value, const float low, const float high)
01560 {
01561     if(value < low) 
01562         return low;
01563     else if (value > high)
01564         return high;
01565     else 
01566         return value;
01567 }
01568 
01569 //! limite une valeur entre un min et un max.
01570 inline 
01571 int Clamp( const int value , const int low, const int high )
01572 {
01573     if(value < low) 
01574         return low;
01575     else if (value > high) 
01576         return high;
01577     else 
01578         return value;
01579 }
01580 
01581 //! conversion degres vers radians.
01582  inline 
01583 float Radians( const float deg )
01584 {
01585     return ( (float) M_PI / 180.f) * deg;
01586 }
01587 
01588 //! conversion radians vers degres.
01589  inline 
01590 float Degrees( const float rad )
01591 {
01592     return (180.f / (float) M_PI) * rad;
01593 }
01594 
01595 //! renvoie un vecteur dont la direction est representee en coordonness polaires.
01596  inline 
01597 Vector SphericalDirection( float sintheta, float costheta, float phi )
01598 {
01599     return Vector( 
01600         sintheta * cosf( phi ), 
01601         sintheta * sinf( phi ), 
01602         costheta );
01603 }
01604 
01605 //! renvoie les composantes d'un vecteur dont la direction est representee en coordonnees polaires, dans la base x, y, z.
01606  inline 
01607 Vector SphericalDirection( float sintheta, float costheta, float phi,
01608     const Vector &x, const Vector &y, const Vector &z )
01609 {
01610     return sintheta * cosf( phi ) * x 
01611         + sintheta * sinf( phi ) * y 
01612         + costheta * z;
01613 }
01614 
01615 //! renvoie l'angle theta d'un vecteur avec la normale, l'axe Z, (utilisation dans un repere local).
01616  inline 
01617 float SphericalTheta( const Vector &v )
01618 {
01619     return acosf( Clamp( v.z, -1.f, 1.f ) );
01620 }
01621 
01622 //! renvoie l'angle phi d'un vecteur avec un vecteur tangent, l'axe X, (utilisation dans un repere local).
01623  inline 
01624 float SphericalPhi( const Vector &v )
01625 {
01626     float p = atan2f( v.y, v.x );
01627     return ( p < 0.f ) ? p + 2.f*M_PI : p;
01628 }
01629 //@}
01630 
01631 } // namespace
01632 
01633 #endif // PBRT_GEOMETRY_H
 All Classes Namespaces Functions Variables Typedefs Enumerator Friends