gKitGL
|
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