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