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