PBRT
/home/felix/UBC/projects/AdaptiveLightfieldSampling/pbrt_v2/src/core/geometry.h
00001 
00002 /*
00003     pbrt source code Copyright(c) 1998-2012 Matt Pharr and Greg Humphreys.
00004 
00005     This file is part of pbrt.
00006 
00007     Redistribution and use in source and binary forms, with or without
00008     modification, are permitted provided that the following conditions are
00009     met:
00010 
00011     - Redistributions of source code must retain the above copyright
00012       notice, this list of conditions and the following disclaimer.
00013 
00014     - Redistributions in binary form must reproduce the above copyright
00015       notice, this list of conditions and the following disclaimer in the
00016       documentation and/or other materials provided with the distribution.
00017 
00018     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00019     IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00020     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00021     PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00022     HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00023     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00024     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00025     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00026     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00028     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029 
00030  */
00031 
00032 #if defined(_MSC_VER)
00033 #pragma once
00034 #endif
00035 
00036 #ifndef PBRT_CORE_GEOMETRY_H
00037 #define PBRT_CORE_GEOMETRY_H
00038 
00039 // core/geometry.h*
00040 #include "pbrt.h"
00041 
00042 // Geometry Declarations
00043 class Vector {
00044 public:
00045     // Vector Public Methods
00046     Vector() { x = y = z = 0.f; }
00047     Vector(float xx, float yy, float zz)
00048         : x(xx), y(yy), z(zz) {
00049         Assert(!HasNaNs());
00050     }
00051     bool HasNaNs() const { return isnan(x) || isnan(y) || isnan(z); }
00052     explicit Vector(const Point &p);
00053 #ifndef NDEBUG
00054     // The default versions of these are fine for release builds; for debug
00055     // we define them so that we can add the Assert checks.
00056     Vector(const Vector &v) {
00057         Assert(!v.HasNaNs());
00058         x = v.x; y = v.y; z = v.z;
00059     }
00060     
00061     Vector &operator=(const Vector &v) {
00062         Assert(!v.HasNaNs());
00063         x = v.x; y = v.y; z = v.z;
00064         return *this;
00065     }
00066 #endif // !NDEBUG
00067     Vector operator+(const Vector &v) const {
00068         Assert(!v.HasNaNs());
00069         return Vector(x + v.x, y + v.y, z + v.z);
00070     }
00071     
00072     Vector& operator+=(const Vector &v) {
00073         Assert(!v.HasNaNs());
00074         x += v.x; y += v.y; z += v.z;
00075         return *this;
00076     }
00077     Vector operator-(const Vector &v) const {
00078         Assert(!v.HasNaNs());
00079         return Vector(x - v.x, y - v.y, z - v.z);
00080     }
00081     
00082     Vector& operator-=(const Vector &v) {
00083         Assert(!v.HasNaNs());
00084         x -= v.x; y -= v.y; z -= v.z;
00085         return *this;
00086     }
00087     Vector operator*(float f) const { return Vector(f*x, f*y, f*z); }
00088     
00089     Vector &operator*=(float f) {
00090         Assert(!isnan(f));
00091         x *= f; y *= f; z *= f;
00092         return *this;
00093     }
00094     Vector operator/(float f) const {
00095         Assert(f != 0);
00096         float inv = 1.f / f;
00097         return Vector(x * inv, y * inv, z * inv);
00098     }
00099     
00100     Vector &operator/=(float f) {
00101         Assert(f != 0);
00102         float inv = 1.f / f;
00103         x *= inv; y *= inv; z *= inv;
00104         return *this;
00105     }
00106     Vector operator-() const { return Vector(-x, -y, -z); }
00107     float operator[](int i) const {
00108         Assert(i >= 0 && i <= 2);
00109         return (&x)[i];
00110     }
00111     
00112     float &operator[](int i) {
00113         Assert(i >= 0 && i <= 2);
00114         return (&x)[i];
00115     }
00116     float LengthSquared() const { return x*x + y*y + z*z; }
00117     float Length() const { return sqrtf(LengthSquared()); }
00118     explicit Vector(const Normal &n);
00119 
00120     bool operator==(const Vector &v) const {
00121         return x == v.x && y == v.y && z == v.z;
00122     }
00123     bool operator!=(const Vector &v) const {
00124         return x != v.x || y != v.y || z != v.z;
00125     }
00126 
00127     // Vector Public Data
00128     float x, y, z;
00129 };
00130 
00131 
00132 class Point {
00133 public:
00134     // Point Public Methods
00135     Point() { x = y = z = 0.f; }
00136     Point(float xx, float yy, float zz)
00137         : x(xx), y(yy), z(zz) {
00138         Assert(!HasNaNs());
00139     }
00140 #ifndef NDEBUG
00141     Point(const Point &p) {
00142         Assert(!p.HasNaNs());
00143         x = p.x; y = p.y; z = p.z;
00144     }
00145     
00146     Point &operator=(const Point &p) {
00147         Assert(!p.HasNaNs());
00148         x = p.x; y = p.y; z = p.z;
00149         return *this;
00150     }
00151 #endif // !NDEBUG
00152     Point operator+(const Vector &v) const {
00153         Assert(!v.HasNaNs());
00154         return Point(x + v.x, y + v.y, z + v.z);
00155     }
00156     
00157     Point &operator+=(const Vector &v) {
00158         Assert(!v.HasNaNs());
00159         x += v.x; y += v.y; z += v.z;
00160         return *this;
00161     }
00162     Vector operator-(const Point &p) const {
00163         Assert(!p.HasNaNs());
00164         return Vector(x - p.x, y - p.y, z - p.z);
00165     }
00166     
00167     Point operator-(const Vector &v) const {
00168         Assert(!v.HasNaNs());
00169         return Point(x - v.x, y - v.y, z - v.z);
00170     }
00171     
00172     Point &operator-=(const Vector &v) {
00173         Assert(!v.HasNaNs());
00174         x -= v.x; y -= v.y; z -= v.z;
00175         return *this;
00176     }
00177     Point &operator+=(const Point &p) {
00178         Assert(!p.HasNaNs());
00179         x += p.x; y += p.y; z += p.z;
00180         return *this;
00181     }
00182     Point operator+(const Point &p) const {
00183         Assert(!p.HasNaNs());
00184         return Point(x + p.x, y + p.y, z + p.z);
00185     }
00186     Point operator* (float f) const {
00187         return Point(f*x, f*y, f*z);
00188     }
00189     Point &operator*=(float f) {
00190         x *= f; y *= f; z *= f;
00191         return *this;
00192     }
00193     Point operator/ (float f) const {
00194         float inv = 1.f/f;
00195         return Point(inv*x, inv*y, inv*z);
00196     }
00197     Point &operator/=(float f) {
00198         float inv = 1.f/f;
00199         x *= inv; y *= inv; z *= inv;
00200         return *this;
00201     }
00202     float operator[](int i) const {
00203         Assert(i >= 0 && i <= 2);
00204         return (&x)[i];
00205     }
00206     
00207     float &operator[](int i) {
00208         Assert(i >= 0 && i <= 2);
00209         return (&x)[i];
00210     }
00211     bool HasNaNs() const {
00212         return isnan(x) || isnan(y) || isnan(z);
00213     }
00214 
00215     bool operator==(const Point &p) const {
00216         return x == p.x && y == p.y && z == p.z;
00217     }
00218     bool operator!=(const Point &p) const {
00219         return x != p.x || y != p.y || z != p.z;
00220     }
00221 
00222     // Point Public Data
00223     float x, y, z;
00224 };
00225 
00226 
00227 class Normal {
00228 public:
00229     // Normal Public Methods
00230     Normal() { x = y = z = 0.f; }
00231     Normal(float xx, float yy, float zz)
00232         : x(xx), y(yy), z(zz) {
00233         Assert(!HasNaNs());
00234     }
00235     Normal operator-() const {
00236         return Normal(-x, -y, -z);
00237     }
00238     Normal operator+ (const Normal &n) const {
00239         Assert(!n.HasNaNs());
00240         return Normal(x + n.x, y + n.y, z + n.z);
00241     }
00242     
00243     Normal& operator+=(const Normal &n) {
00244         Assert(!n.HasNaNs());
00245         x += n.x; y += n.y; z += n.z;
00246         return *this;
00247     }
00248     Normal operator- (const Normal &n) const {
00249         Assert(!n.HasNaNs());
00250         return Normal(x - n.x, y - n.y, z - n.z);
00251     }
00252     
00253     Normal& operator-=(const Normal &n) {
00254         Assert(!n.HasNaNs());
00255         x -= n.x; y -= n.y; z -= n.z;
00256         return *this;
00257     }
00258     bool HasNaNs() const {
00259         return isnan(x) || isnan(y) || isnan(z);
00260     }
00261     Normal operator*(float f) const {
00262         return Normal(f*x, f*y, f*z);
00263     }
00264     
00265     Normal &operator*=(float f) {
00266         x *= f; y *= f; z *= f;
00267         return *this;
00268     }
00269     Normal operator/(float f) const {
00270         Assert(f != 0);
00271         float inv = 1.f/f;
00272         return Normal(x * inv, y * inv, z * inv);
00273     }
00274     
00275     Normal &operator/=(float f) {
00276         Assert(f != 0);
00277         float inv = 1.f/f;
00278         x *= inv; y *= inv; z *= inv;
00279         return *this;
00280     }
00281     float LengthSquared() const { return x*x + y*y + z*z; }
00282     float Length() const        { return sqrtf(LengthSquared()); }
00283     
00284 #ifndef NDEBUG
00285     Normal(const Normal &n) {
00286         Assert(!n.HasNaNs());
00287         x = n.x; y = n.y; z = n.z;
00288     }
00289     
00290     Normal &operator=(const Normal &n) {
00291         Assert(!n.HasNaNs());
00292         x = n.x; y = n.y; z = n.z;
00293         return *this;
00294     }
00295 #endif // !NDEBUG
00296     explicit Normal(const Vector &v)
00297       : x(v.x), y(v.y), z(v.z) {
00298         Assert(!v.HasNaNs());
00299     }
00300     float operator[](int i) const {
00301         Assert(i >= 0 && i <= 2);
00302         return (&x)[i];
00303     }
00304     
00305     float &operator[](int i) {
00306         Assert(i >= 0 && i <= 2);
00307         return (&x)[i];
00308     }
00309 
00310     bool operator==(const Normal &n) const {
00311         return x == n.x && y == n.y && z == n.z;
00312     }
00313     bool operator!=(const Normal &n) const {
00314         return x != n.x || y != n.y || z != n.z;
00315     }
00316 
00317     // Normal Public Data
00318     float x, y, z;
00319 };
00320 
00321 
00322 class Ray {
00323 public:
00324     // Ray Public Methods
00325     Ray() : mint(0.f), maxt(INFINITY), time(0.f), depth(0) { }
00326     Ray(const Point &origin, const Vector &direction,
00327         float start, float end = INFINITY, float t = 0.f, int d = 0)
00328         : o(origin), d(direction), mint(start), maxt(end), time(t), depth(d) { }
00329     Ray(const Point &origin, const Vector &direction, const Ray &parent,
00330         float start, float end = INFINITY)
00331         : o(origin), d(direction), mint(start), maxt(end),
00332           time(parent.time), depth(parent.depth+1) { }
00333     Point operator()(float t) const { return o + d * t; }
00334     bool HasNaNs() const {
00335         return (o.HasNaNs() || d.HasNaNs() ||
00336                 isnan(mint) || isnan(maxt));
00337     }
00338 
00339     // Ray Public Data
00340     Point o;
00341     Vector d;
00342     mutable float mint, maxt;
00343     float time;
00344     int depth;
00345 };
00346 
00347 
00348 class RayDifferential : public Ray {
00349 public:
00350     // RayDifferential Public Methods
00351     RayDifferential() { hasDifferentials = false; }
00352     RayDifferential(const Point &org, const Vector &dir, float start,
00353         float end = INFINITY, float t = 0.f, int d = 0)
00354             : Ray(org, dir, start, end, t, d) {
00355         hasDifferentials = false;
00356     }
00357     RayDifferential(const Point &org, const Vector &dir, const Ray &parent,
00358         float start, float end = INFINITY)
00359             : Ray(org, dir, start, end, parent.time, parent.depth+1) {
00360         hasDifferentials = false;
00361     }
00362     explicit RayDifferential(const Ray &ray) : Ray(ray) {
00363         hasDifferentials = false;
00364     }
00365     bool HasNaNs() const {
00366         return Ray::HasNaNs() ||
00367            (hasDifferentials && (rxOrigin.HasNaNs() || ryOrigin.HasNaNs() ||
00368                                  rxDirection.HasNaNs() || ryDirection.HasNaNs()));
00369     }
00370     void ScaleDifferentials(float s) {
00371         rxOrigin = o + (rxOrigin - o) * s;
00372         ryOrigin = o + (ryOrigin - o) * s;
00373         rxDirection = d + (rxDirection - d) * s;
00374         ryDirection = d + (ryDirection - d) * s;
00375     }
00376 
00377     // RayDifferential Public Data
00378     bool hasDifferentials;
00379     Point rxOrigin, ryOrigin;
00380     Vector rxDirection, ryDirection;
00381 };
00382 
00383 
00384 class BBox {
00385 public:
00386     // BBox Public Methods
00387     BBox() {
00388         pMin = Point( INFINITY,  INFINITY,  INFINITY);
00389         pMax = Point(-INFINITY, -INFINITY, -INFINITY);
00390     }
00391     BBox(const Point &p) : pMin(p), pMax(p) { }
00392     BBox(const Point &p1, const Point &p2) {
00393         pMin = Point(min(p1.x, p2.x), min(p1.y, p2.y), min(p1.z, p2.z));
00394         pMax = Point(max(p1.x, p2.x), max(p1.y, p2.y), max(p1.z, p2.z));
00395     }
00396     friend BBox Union(const BBox &b, const Point &p);
00397     friend BBox Union(const BBox &b, const BBox &b2);
00398     bool Overlaps(const BBox &b) const {
00399         bool x = (pMax.x >= b.pMin.x) && (pMin.x <= b.pMax.x);
00400         bool y = (pMax.y >= b.pMin.y) && (pMin.y <= b.pMax.y);
00401         bool z = (pMax.z >= b.pMin.z) && (pMin.z <= b.pMax.z);
00402         return (x && y && z);
00403     }
00404     bool Inside(const Point &pt) const {
00405         return (pt.x >= pMin.x && pt.x <= pMax.x &&
00406                 pt.y >= pMin.y && pt.y <= pMax.y &&
00407                 pt.z >= pMin.z && pt.z <= pMax.z);
00408     }
00409     void Expand(float delta) {
00410         pMin -= Vector(delta, delta, delta);
00411         pMax += Vector(delta, delta, delta);
00412     }
00413     float SurfaceArea() const {
00414         Vector d = pMax - pMin;
00415         return 2.f * (d.x * d.y + d.x * d.z + d.y * d.z);
00416     }
00417     float Volume() const {
00418         Vector d = pMax - pMin;
00419         return d.x * d.y * d.z;
00420     }
00421     int MaximumExtent() const {
00422         Vector diag = pMax - pMin;
00423         if (diag.x > diag.y && diag.x > diag.z)
00424             return 0;
00425         else if (diag.y > diag.z)
00426             return 1;
00427         else
00428             return 2;
00429     }
00430     const Point &operator[](int i) const;
00431     Point &operator[](int i);
00432     Point Lerp(float tx, float ty, float tz) const {
00433         return Point(::Lerp(tx, pMin.x, pMax.x), ::Lerp(ty, pMin.y, pMax.y),
00434                      ::Lerp(tz, pMin.z, pMax.z));
00435     }
00436     Vector Offset(const Point &p) const {
00437         return Vector((p.x - pMin.x) / (pMax.x - pMin.x),
00438                       (p.y - pMin.y) / (pMax.y - pMin.y),
00439                       (p.z - pMin.z) / (pMax.z - pMin.z));
00440     }
00441     void BoundingSphere(Point *c, float *rad) const;
00442     bool IntersectP(const Ray &ray, float *hitt0 = NULL, float *hitt1 = NULL) const;
00443 
00444     bool operator==(const BBox &b) const {
00445         return b.pMin == pMin && b.pMax == pMax;
00446     }
00447     bool operator!=(const BBox &b) const {
00448         return b.pMin != pMin || b.pMax != pMax;
00449     }
00450 
00451     // BBox Public Data
00452     Point pMin, pMax;
00453 };
00454 
00455 
00456 
00457 // Geometry Inline Functions
00458 inline Vector::Vector(const Point &p)
00459     : x(p.x), y(p.y), z(p.z) {
00460     Assert(!HasNaNs());
00461 }
00462 
00463 
00464 inline Vector operator*(float f, const Vector &v) { return v*f; }
00465 inline float Dot(const Vector &v1, const Vector &v2) {
00466     Assert(!v1.HasNaNs() && !v2.HasNaNs());
00467     return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
00468 }
00469 
00470 
00471 inline float AbsDot(const Vector &v1, const Vector &v2) {
00472     Assert(!v1.HasNaNs() && !v2.HasNaNs());
00473     return fabsf(Dot(v1, v2));
00474 }
00475 
00476 
00477 inline Vector Cross(const Vector &v1, const Vector &v2) {
00478     Assert(!v1.HasNaNs() && !v2.HasNaNs());
00479     double v1x = v1.x, v1y = v1.y, v1z = v1.z;
00480     double v2x = v2.x, v2y = v2.y, v2z = v2.z;
00481     return Vector((v1y * v2z) - (v1z * v2y),
00482                   (v1z * v2x) - (v1x * v2z),
00483                   (v1x * v2y) - (v1y * v2x));
00484 }
00485 
00486 
00487 inline Vector Cross(const Vector &v1, const Normal &v2) {
00488     Assert(!v1.HasNaNs() && !v2.HasNaNs());
00489     double v1x = v1.x, v1y = v1.y, v1z = v1.z;
00490     double v2x = v2.x, v2y = v2.y, v2z = v2.z;
00491     return Vector((v1y * v2z) - (v1z * v2y),
00492                   (v1z * v2x) - (v1x * v2z),
00493                   (v1x * v2y) - (v1y * v2x));
00494 }
00495 
00496 
00497 inline Vector Cross(const Normal &v1, const Vector &v2) {
00498     Assert(!v1.HasNaNs() && !v2.HasNaNs());
00499     double v1x = v1.x, v1y = v1.y, v1z = v1.z;
00500     double v2x = v2.x, v2y = v2.y, v2z = v2.z;
00501     return Vector((v1y * v2z) - (v1z * v2y),
00502                   (v1z * v2x) - (v1x * v2z),
00503                   (v1x * v2y) - (v1y * v2x));
00504 }
00505 
00506 
00507 inline Vector Normalize(const Vector &v) { return v / v.Length(); }
00508 inline void CoordinateSystem(const Vector &v1, Vector *v2, Vector *v3) {
00509     if (fabsf(v1.x) > fabsf(v1.y)) {
00510         float invLen = 1.f / sqrtf(v1.x*v1.x + v1.z*v1.z);
00511         *v2 = Vector(-v1.z * invLen, 0.f, v1.x * invLen);
00512     }
00513     else {
00514         float invLen = 1.f / sqrtf(v1.y*v1.y + v1.z*v1.z);
00515         *v2 = Vector(0.f, v1.z * invLen, -v1.y * invLen);
00516     }
00517     *v3 = Cross(v1, *v2);
00518 }
00519 
00520 
00521 inline float Distance(const Point &p1, const Point &p2) {
00522     return (p1 - p2).Length();
00523 }
00524 
00525 
00526 inline float DistanceSquared(const Point &p1, const Point &p2) {
00527     return (p1 - p2).LengthSquared();
00528 }
00529 
00530 
00531 inline Point operator*(float f, const Point &p) {
00532     Assert(!p.HasNaNs());
00533     return p*f;
00534 }
00535 
00536 
00537 inline Normal operator*(float f, const Normal &n) {
00538     return Normal(f*n.x, f*n.y, f*n.z);
00539 }
00540 
00541 
00542 inline Normal Normalize(const Normal &n) {
00543     return n / n.Length();
00544 }
00545 
00546 
00547 inline Vector::Vector(const Normal &n)
00548   : x(n.x), y(n.y), z(n.z) {
00549     Assert(!n.HasNaNs());
00550 }
00551 
00552 
00553 inline float Dot(const Normal &n1, const Vector &v2) {
00554     Assert(!n1.HasNaNs() && !v2.HasNaNs());
00555     return n1.x * v2.x + n1.y * v2.y + n1.z * v2.z;
00556 }
00557 
00558 
00559 inline float Dot(const Vector &v1, const Normal &n2) {
00560     Assert(!v1.HasNaNs() && !n2.HasNaNs());
00561     return v1.x * n2.x + v1.y * n2.y + v1.z * n2.z;
00562 }
00563 
00564 
00565 inline float Dot(const Normal &n1, const Normal &n2) {
00566     Assert(!n1.HasNaNs() && !n2.HasNaNs());
00567     return n1.x * n2.x + n1.y * n2.y + n1.z * n2.z;
00568 }
00569 
00570 
00571 inline float AbsDot(const Normal &n1, const Vector &v2) {
00572     Assert(!n1.HasNaNs() && !v2.HasNaNs());
00573     return fabsf(n1.x * v2.x + n1.y * v2.y + n1.z * v2.z);
00574 }
00575 
00576 
00577 inline float AbsDot(const Vector &v1, const Normal &n2) {
00578     Assert(!v1.HasNaNs() && !n2.HasNaNs());
00579     return fabsf(v1.x * n2.x + v1.y * n2.y + v1.z * n2.z);
00580 }
00581 
00582 
00583 inline float AbsDot(const Normal &n1, const Normal &n2) {
00584     Assert(!n1.HasNaNs() && !n2.HasNaNs());
00585     return fabsf(n1.x * n2.x + n1.y * n2.y + n1.z * n2.z);
00586 }
00587 
00588 
00589 inline Normal Faceforward(const Normal &n, const Vector &v) {
00590     return (Dot(n, v) < 0.f) ? -n : n;
00591 }
00592 
00593 
00594 inline Normal Faceforward(const Normal &n, const Normal &n2) {
00595     return (Dot(n, n2) < 0.f) ? -n : n;
00596 }
00597 
00598 
00599 
00600 inline Vector Faceforward(const Vector &v, const Vector &v2) {
00601     return (Dot(v, v2) < 0.f) ? -v : v;
00602 }
00603 
00604 
00605 
00606 inline Vector Faceforward(const Vector &v, const Normal &n2) {
00607     return (Dot(v, n2) < 0.f) ? -v : v;
00608 }
00609 
00610 
00611 inline const Point &BBox::operator[](int i) const {
00612     Assert(i == 0 || i == 1);
00613     return (&pMin)[i];
00614 }
00615 
00616 
00617 
00618 inline Point &BBox::operator[](int i) {
00619     Assert(i == 0 || i == 1);
00620     return (&pMin)[i];
00621 }
00622 
00623 
00624 inline Vector SphericalDirection(float sintheta,
00625                                  float costheta, float phi) {
00626     return Vector(sintheta * cosf(phi),
00627                   sintheta * sinf(phi),
00628                   costheta);
00629 }
00630 
00631 
00632 inline Vector SphericalDirection(float sintheta, float costheta,
00633                                  float phi, const Vector &x,
00634                                  const Vector &y, const Vector &z) {
00635     return sintheta * cosf(phi) * x +
00636            sintheta * sinf(phi) * y + costheta * z;
00637 }
00638 
00639 
00640 inline float SphericalTheta(const Vector &v) {
00641     return acosf(Clamp(v.z, -1.f, 1.f));
00642 }
00643 
00644 
00645 inline float SphericalPhi(const Vector &v) {
00646     float p = atan2f(v.y, v.x);
00647     return (p < 0.f) ? p + 2.f*M_PI : p;
00648 }
00649 
00650 
00651 
00652 #endif // PBRT_CORE_GEOMETRY_H