00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef PBRT_PBRT_H
00025 #define PBRT_PBRT_H
00026
00027
00028 #if !defined(__APPLE__) && !defined(__OpenBSD__)
00029 #include <malloc.h>
00030 #endif
00031 #if !defined(WIN32) && !defined(__APPLE__) && !defined(__OpenBSD__)
00032 #include <alloca.h>
00033 #endif
00034 #ifdef __linux__
00035 #include <fpu_control.h>
00036 #endif
00037 #ifdef WIN32
00038 #include <float.h>
00039 #endif
00040 #include <math.h>
00041 #include <stdlib.h>
00042 #define _GNU_SOURCE 1 //NOBOOK
00043 #include <stdio.h>
00044 #include <string.h>
00045 #include <string>
00046 using std::string;
00047 #include <vector>
00048 using std::vector;
00049 #include <iostream>
00050 using std::ostream;
00051 #include <algorithm>
00052 using std::min;
00053 using std::max;
00054 using std::swap;
00055 using std::sort;
00056 #ifdef WIN32
00057 #define WIN32_LEAN_AND_MEAN
00058 #include <windows.h>
00059 #endif
00060 #include <assert.h>
00061
00062 #if defined(WIN32)
00063 #define memalign(a,b) _aligned_malloc(b, a)
00064 #elif defined(__APPLE__)
00065 #define memalign(a,b) valloc(b)
00066 #elif defined(__OpenBSD__)
00067 #define memalign(a,b) malloc(b)
00068 #endif
00069 #ifdef sgi
00070 #define for if (0) ; else for
00071 #endif
00072 #ifdef __APPLE__
00073 #define powf pow
00074 #define sinf sin
00075 #define cosf cos
00076 #define tanf tan
00077 #define asinf asin
00078 #define acosf acos
00079 #define atanf atan
00080 #define atan2f atan2
00081 #define logf log
00082 #define log10f log10
00083 #define expf exp
00084 #define sqrtf sqrt
00085 #if __GNUC__ == 3
00086 extern "C" {
00087 int isinf(double);
00088 int isnan(double);
00089 }
00090 #endif // ONLY GCC 3
00091 #endif // __APPLE__
00092
00093 #ifdef WIN32
00094 #pragma warning (disable: 4267 4251 4065 4102)
00095 #endif // WIN32
00096 #ifdef WIN32
00097 #pragma warning( disable: 4190 )
00098
00099 #endif
00100 #ifdef WIN32
00101 #ifdef CORE_SOURCE
00102 #define COREDLL __declspec(dllexport)
00103 #else
00104 #define COREDLL __declspec(dllimport)
00105 #endif
00106 #define DLLEXPORT __declspec(dllexport)
00107 #else
00108 #define COREDLL
00109 #define DLLEXPORT
00110 #endif
00111 #ifdef WIN32
00112 #define PBRT_PATH_SEP ";"
00113 #else
00114 #define PBRT_PATH_SEP ":"
00115 #endif
00116 #ifdef WIN32
00117 #define isnan _isnan
00118 #define isinf(f) (!_finite((f)))
00119 #endif
00120
00121 typedef double StatsCounterType;
00122 typedef unsigned char u_char;
00123 typedef unsigned short u_short;
00124 typedef unsigned int u_int;
00125 typedef unsigned long u_long;
00126
00127 class Timer;
00128 template<class T, int logBlockSize = 2> class BlockedArray;
00129 struct Matrix4x4;
00130 class ParamSet;
00131 template <class T> struct ParamSetItem;
00132 class TextureParams;
00133 class Shape;
00134 class Scene;
00135 class Vector;
00136 class Point;
00137 class Normal;
00138 class Ray;
00139 class RayDifferential;
00140 class BBox;
00141 class Transform;
00142 struct DifferentialGeometry;
00143 class Primitive;
00144 struct Intersection;
00145 class GeometricPrimitive;
00146 class Spectrum;
00147 class Camera;
00148 class ProjectiveCamera;
00149 class Sampler;
00150 struct Sample;
00151 #define BC_GRID_SIZE 40
00152 typedef vector<int> SampleGrid[BC_GRID_SIZE][BC_GRID_SIZE];
00153 #define GRID(v) (int((v) * BC_GRID_SIZE))
00154 class Filter;
00155 class Film;
00156 class ToneMap;
00157 class BxDF;
00158 class BRDF;
00159 class BTDF;
00160 class Fresnel;
00161 class FresnelConductor;
00162 class FresnelDielectric;
00163 class FresnelNoOp;
00164 class SpecularReflection;
00165 class SpecularTransmission;
00166 class Lambertian;
00167 class OrenNayar;
00168 class Microfacet;
00169 class MicrofacetDistribution;
00170 class BSDF;
00171 class Material;
00172 class TextureMapping2D;
00173 class UVMapping2D;
00174 class SphericalMapping2D;
00175 class CylindricalMapping2D;
00176 class PlanarMapping2D;
00177 class TextureMapping3D;
00178 class IdentityMapping3D;
00179 template <class T> class Texture;
00180 COREDLL float Noise(float x, float y = .5f, float z = .5f);
00181 COREDLL float Noise(const Point &P);
00182 COREDLL float FBm(const Point &P, const Vector &dpdx, const Vector &dpdy,
00183 float omega, int octaves);
00184 COREDLL float Turbulence(const Point &P, const Vector &dpdx, const Vector &dpdy,
00185 float omega, int octaves);
00186 class VolumeRegion;
00187 class Light;
00188 struct VisibilityTester;
00189 class AreaLight;
00190 class ShapeSet;
00191 class SurfaceIntegrator;
00192 class Integrator;
00193 class VolumeIntegrator;
00194
00195 #ifdef WIN32
00196 #define alloca _alloca
00197 #endif
00198 #ifdef M_PI
00199 #undef M_PI
00200 #endif
00201 #define M_PI 3.14159265358979323846f
00202 #define INV_PI 0.31830988618379067154f
00203 #define INV_TWOPI 0.15915494309189533577f
00204 #ifndef INFINITY
00205 #define INFINITY FLT_MAX
00206 #endif
00207 #define PBRT_VERSION 1.03
00208 #define RAY_EPSILON 1e-3f
00209 #define COLOR_SAMPLES 3
00210
00211
00212 #ifdef __GNUG__
00213 #define PRINTF_FUNC __attribute__ \
00214 ((__format__ (__printf__, 1, 2)))
00215 #else
00216 #define PRINTF_FUNC
00217 #endif // __GNUG__
00218 extern COREDLL void Info(const char *, ...) PRINTF_FUNC;
00219 extern COREDLL void Warning(const char *, ...) PRINTF_FUNC;
00220 extern COREDLL void Error(const char *, ...) PRINTF_FUNC;
00221 extern COREDLL void Severe(const char *, ...) PRINTF_FUNC;
00222 extern void StatsPrint(FILE *dest);
00223 extern void StatsCleanup();
00224 COREDLL void *AllocAligned(size_t size);
00225 COREDLL void FreeAligned(void *);
00226 COREDLL bool SolveLinearSystem2x2(const float A[2][2], const float B[2],
00227 float x[2]);
00228 COREDLL unsigned long genrand_int32(void);
00229 COREDLL extern float genrand_real1(void);
00230 COREDLL extern float genrand_real2(void);
00231 COREDLL Spectrum *ReadImage(const string &name, int *xSize,
00232 int *ySize);
00233 COREDLL void WriteRGBAImage(const string &name,
00234 float *pixels, float *alpha, int XRes, int YRes,
00235 int totalXRes, int totalYRes, int xOffset, int yOffset);
00236 COREDLL void pbrtInit();
00237 COREDLL void pbrtCleanup();
00238 COREDLL Transform Translate(const Vector &delta);
00239 COREDLL Transform Scale(float x, float y, float z);
00240 extern COREDLL Transform RotateX(float angle);
00241 extern COREDLL Transform RotateY(float angle);
00242 extern COREDLL Transform RotateZ(float angle);
00243 extern COREDLL Transform Rotate(float angle, const Vector &axis);
00244 extern COREDLL Transform LookAt(const Point &pos, const Point &look,
00245 const Vector &up);
00246 COREDLL Transform Orthographic(float znear, float zfar);
00247 COREDLL
00248 Transform Perspective(float fov, float znear, float zfar);
00249 COREDLL Spectrum FrDiel(float cosi, float cost,
00250 const Spectrum &etai,
00251 const Spectrum &etat);
00252 COREDLL Spectrum FrCond(float cosi,
00253 const Spectrum &n,
00254 const Spectrum &k);
00255 COREDLL
00256 Spectrum FresnelApproxEta(const Spectrum &intensity);
00257 COREDLL
00258 Spectrum FresnelApproxK(const Spectrum &intensity);
00259 COREDLL float Lanczos(float, float tau=2);
00260 COREDLL Spectrum EstimateDirect(const Scene *scene, const Light *light, const Point &p,
00261 const Normal &n, const Vector &wo, BSDF *bsdf,
00262 const Sample *sample, int lightSamp, int bsdfSamp,
00263 int bsdfComponent, u_int sampleNum);
00264 extern COREDLL void ComputeStep1dCDF(float *f, int nValues, float *c, float *cdf);
00265 extern COREDLL float SampleStep1d(float *f, float *cdf, float c,
00266 int nSteps, float u, float *weight);
00267 COREDLL void ConcentricSampleDisk(float u1, float u2, float *dx, float *dy);
00268 COREDLL void UniformSampleTriangle(float ud1, float ud2, float *u, float *v);
00269 COREDLL bool ParseFile(const char *filename);
00270
00271 struct COREDLL ProgressReporter {
00272
00273 ProgressReporter(int totalWork, const string &title,
00274 int barLength=58);
00275 ~ProgressReporter();
00276 void Update(int num = 1) const;
00277 void Done() const;
00278
00279 const int totalPlusses;
00280 float frequency;
00281 mutable float count;
00282 mutable int plussesPrinted;
00283 mutable Timer *timer;
00284 FILE *outFile;
00285 char *buf;
00286 mutable char *curSpace;
00287 };
00288 class COREDLL StatsCounter {
00289 public:
00290
00291 StatsCounter(const string &category, const string &name);
00292 void operator++() { ++num; }
00293 void operator++(int) { ++num; }
00294 void Max(StatsCounterType val) { num = max(val, num); }
00295 void Min(StatsCounterType val) { num = min(val, num); }
00296 operator double() const { return (double)num; }
00297 private:
00298
00299 StatsCounterType num;
00300 };
00301 class COREDLL StatsRatio {
00302 public:
00303
00304 StatsRatio(const string &category, const string &name);
00305 void Add(int a, int b) { na += a; nb += b; }
00306 private:
00307
00308 StatsCounterType na, nb;
00309 };
00310 class COREDLL StatsPercentage {
00311 public:
00312
00313 void Add(int a, int b) { na += a; nb += b; }
00314 StatsPercentage(const string &category, const string &name);
00315 private:
00316
00317 StatsCounterType na, nb;
00318 };
00319 class COREDLL ReferenceCounted {
00320 public:
00321 ReferenceCounted() { nReferences = 0; }
00322 int nReferences;
00323 private:
00324 ReferenceCounted(const ReferenceCounted &);
00325 ReferenceCounted &operator=(const ReferenceCounted &);
00326 };
00327 template <class T> class Reference {
00328 public:
00329
00330 Reference(T *p = NULL) {
00331 ptr = p;
00332 if (ptr) ++ptr->nReferences;
00333 }
00334 Reference(const Reference<T> &r) {
00335 ptr = r.ptr;
00336 if (ptr) ++ptr->nReferences;
00337 }
00338 Reference &operator=(const Reference<T> &r) {
00339 if (r.ptr) r.ptr->nReferences++;
00340 if (ptr && --ptr->nReferences == 0) delete ptr;
00341 ptr = r.ptr;
00342 return *this;
00343 }
00344 Reference &operator=(T *p) {
00345 if (p) p->nReferences++;
00346 if (ptr && --ptr->nReferences == 0) delete ptr;
00347 ptr = p;
00348 return *this;
00349 }
00350 ~Reference() {
00351 if (ptr && --ptr->nReferences == 0)
00352 delete ptr;
00353 }
00354 T *operator->() { return ptr; }
00355 const T *operator->() const { return ptr; }
00356 operator bool() const { return ptr != NULL; }
00357 bool operator<(const Reference<T> &t2) const {
00358 return ptr < t2.ptr;
00359 }
00360 private:
00361 T *ptr;
00362 };
00363 template <class T> class ObjectArena {
00364 public:
00365
00366 ObjectArena() {
00367 nAvailable = 0;
00368 }
00369 T *Alloc() {
00370 if (nAvailable == 0) {
00371 int nAlloc = max((unsigned long)16,
00372 (unsigned long)(65536/sizeof(T)));
00373 mem = (T *)AllocAligned(nAlloc * sizeof(T));
00374 nAvailable = nAlloc;
00375 toDelete.push_back(mem);
00376 }
00377 --nAvailable;
00378 return mem++;
00379 }
00380 operator T *() {
00381 return Alloc();
00382 }
00383 ~ObjectArena() { FreeAll(); }
00384 void FreeAll() {
00385 for (u_int i = 0; i < toDelete.size(); ++i)
00386 FreeAligned(toDelete[i]);
00387 toDelete.erase(toDelete.begin(), toDelete.end());
00388 nAvailable = 0;
00389 }
00390 private:
00391
00392 T *mem;
00393 int nAvailable;
00394 vector<T *> toDelete;
00395 };
00396 class COREDLL MemoryArena {
00397 public:
00398
00399 MemoryArena(u_int bs = 32768) {
00400 blockSize = bs;
00401 curBlockPos = 0;
00402 currentBlock = (char *)AllocAligned(blockSize);
00403 }
00404 ~MemoryArena() {
00405 FreeAligned(currentBlock);
00406 for (u_int i = 0; i < usedBlocks.size(); ++i)
00407 FreeAligned(usedBlocks[i]);
00408 for (u_int i = 0; i < availableBlocks.size(); ++i)
00409 FreeAligned(availableBlocks[i]);
00410 }
00411 void *Alloc(u_int sz) {
00412
00413 sz = ((sz + 7) & (~7));
00414 if (curBlockPos + sz > blockSize) {
00415
00416 usedBlocks.push_back(currentBlock);
00417 if (availableBlocks.size() && sz <= blockSize) {
00418 currentBlock = availableBlocks.back();
00419 availableBlocks.pop_back();
00420 }
00421 else
00422 currentBlock = (char *)AllocAligned(max(sz, blockSize));
00423 curBlockPos = 0;
00424 }
00425 void *ret = currentBlock + curBlockPos;
00426 curBlockPos += sz;
00427 return ret;
00428 }
00429 void FreeAll() {
00430 curBlockPos = 0;
00431 while (usedBlocks.size()) {
00432 availableBlocks.push_back(usedBlocks.back());
00433 usedBlocks.pop_back();
00434 }
00435 }
00436 private:
00437
00438 u_int curBlockPos, blockSize;
00439 char *currentBlock;
00440 vector<char *> usedBlocks, availableBlocks;
00441 };
00442 template<class T, int logBlockSize> class BlockedArray {
00443 public:
00444
00445 BlockedArray(int nu, int nv, const T *d = NULL) {
00446 uRes = nu;
00447 vRes = nv;
00448 uBlocks = RoundUp(uRes) >> logBlockSize;
00449 int nAlloc = RoundUp(uRes) * RoundUp(vRes);
00450 data = (T *)AllocAligned(nAlloc * sizeof(T));
00451 for (int i = 0; i < nAlloc; ++i)
00452 new (&data[i]) T();
00453 if (d)
00454 for (int v = 0; v < nv; ++v)
00455 for (int u = 0; u < nu; ++u)
00456 (*this)(u, v) = d[v * uRes + u];
00457 }
00458 int BlockSize() const { return 1 << logBlockSize; }
00459 int RoundUp(int x) const {
00460 return (x + BlockSize() - 1) & ~(BlockSize() - 1);
00461 }
00462 int uSize() const { return uRes; }
00463 int vSize() const { return vRes; }
00464 ~BlockedArray() {
00465 for (int i = 0; i < uRes * vRes; ++i)
00466 data[i].~T();
00467 FreeAligned(data);
00468 }
00469 int Block(int a) const { return a >> logBlockSize; }
00470 int Offset(int a) const { return (a & (BlockSize() - 1)); }
00471 T &operator()(int u, int v) {
00472 int bu = Block(u), bv = Block(v);
00473 int ou = Offset(u), ov = Offset(v);
00474 int offset = BlockSize() * BlockSize() *
00475 (uBlocks * bv + bu);
00476 offset += BlockSize() * ov + ou;
00477 return data[offset];
00478 }
00479 const T &operator()(int u, int v) const {
00480 int bu = Block(u), bv = Block(v);
00481 int ou = Offset(u), ov = Offset(v);
00482 int offset = BlockSize() * BlockSize() * (uBlocks * bv + bu);
00483 offset += BlockSize() * ov + ou;
00484 return data[offset];
00485 }
00486 void GetLinearArray(T *a) const {
00487 for (int v = 0; v < vRes; ++v)
00488 for (int u = 0; u < uRes; ++u)
00489 *a++ = (*this)(u, v);
00490 }
00491 private:
00492
00493 T *data;
00494 int uRes, vRes, uBlocks;
00495 };
00496 struct COREDLL Matrix4x4 : public ReferenceCounted {
00497
00498 Matrix4x4() {
00499 for (int i = 0; i < 4; ++i)
00500 for (int j = 0; j < 4; ++j)
00501 if (i == j) m[i][j] = 1.;
00502 else m[i][j] = 0.;
00503 }
00504 Matrix4x4(float mat[4][4]);
00505 Matrix4x4(float t00, float t01, float t02, float t03,
00506 float t10, float t11, float t12, float t13,
00507 float t20, float t21, float t22, float t23,
00508 float t30, float t31, float t32, float t33);
00509 Reference<Matrix4x4> Transpose() const;
00510 void Print(ostream &os) const {
00511 os << "[ ";
00512 for (int i = 0; i < 4; ++i) {
00513 os << "[ ";
00514 for (int j = 0; j < 4; ++j) {
00515 os << m[i][j];
00516 if (j != 3) os << ", ";
00517 }
00518 os << " ] ";
00519 }
00520 os << " ] ";
00521 }
00522 static Reference<Matrix4x4>
00523 Mul(const Reference<Matrix4x4> &m1,
00524 const Reference<Matrix4x4> &m2) {
00525 float r[4][4];
00526 for (int i = 0; i < 4; ++i)
00527 for (int j = 0; j < 4; ++j)
00528 r[i][j] = m1->m[i][0] * m2->m[0][j] +
00529 m1->m[i][1] * m2->m[1][j] +
00530 m1->m[i][2] * m2->m[2][j] +
00531 m1->m[i][3] * m2->m[3][j];
00532 return new Matrix4x4(r);
00533 }
00534 Reference<Matrix4x4> Inverse() const;
00535 float m[4][4];
00536 };
00537
00538 #ifdef NDEBUG
00539 #define Assert(expr) ((void)0)
00540 #else
00541 #define Assert(expr) \
00542 ((expr) ? (void)0 : \
00543 Severe("Assertion \"%s\" failed in %s, line %d", \
00544 #expr, __FILE__, __LINE__))
00545 #endif // NDEBUG
00546 inline float Lerp(float t, float v1, float v2) {
00547 return (1.f - t) * v1 + t * v2;
00548 }
00549 inline float Clamp(float val, float low, float high) {
00550 if (val < low) return low;
00551 else if (val > high) return high;
00552 else return val;
00553 }
00554 inline int Clamp(int val, int low, int high) {
00555 if (val < low) return low;
00556 else if (val > high) return high;
00557 else return val;
00558 }
00559 inline int Mod(int a, int b) {
00560 int n = int(a/b);
00561 a -= n*b;
00562 if (a < 0)
00563 a += b;
00564 return a;
00565 }
00566 inline float Radians(float deg) {
00567 return ((float)M_PI/180.f) * deg;
00568 }
00569 inline float Degrees(float rad) {
00570 return (180.f/(float)M_PI) * rad;
00571 }
00572 inline float Log2(float x) {
00573 static float invLog2 = 1.f / logf(2.f);
00574 return logf(x) * invLog2;
00575 }
00576 inline int Log2Int(float v) {
00577 #if 0
00578 return ((*reinterpret_cast<int *>(&v)) >> 23) - 127;
00579 #else
00580 #define _doublemagicroundeps (.5-1.4e-11)
00581 return int(Log2(v) + _doublemagicroundeps);
00582 #endif
00583 }
00584 inline bool IsPowerOf2(int v) {
00585 return (v & (v - 1)) == 0;
00586 }
00587 inline u_int RoundUpPow2(u_int v) {
00588 v--;
00589 v |= v >> 1;
00590 v |= v >> 2;
00591 v |= v >> 4;
00592 v |= v >> 8;
00593 v |= v >> 16;
00594 return v+1;
00595 }
00596 #if (defined(__linux__) && defined(__i386__)) || defined(WIN32)
00597
00598 #endif
00599 #define _doublemagicroundeps (.5-1.4e-11)
00600
00601 inline int Round2Int(double val) {
00602 #ifdef FAST_INT
00603 #define _doublemagic double (6755399441055744.0)
00604
00605 val = val + _doublemagic;
00606 return (reinterpret_cast<long*>(&val))[0];
00607 #else
00608 return int (val+_doublemagicroundeps);
00609 #endif
00610 }
00611 inline int Float2Int(double val) {
00612 #ifdef FAST_INT
00613 return (val<0) ? Round2Int(val+_doublemagicroundeps) :
00614 Round2Int(val-_doublemagicroundeps);
00615 #else
00616 return (int)val;
00617 #endif
00618 }
00619 inline int Floor2Int(double val) {
00620 #ifdef FAST_INT
00621 return Round2Int(val - _doublemagicroundeps);
00622 #else
00623 return (int)floor(val);
00624 #endif
00625 }
00626 inline int Ceil2Int(double val) {
00627 #ifdef FAST_INT
00628 return Round2Int(val + _doublemagicroundeps);
00629 #else
00630 return (int)ceil(val);
00631 #endif
00632 }
00633 inline float RandomFloat();
00634 inline unsigned long RandomUInt();
00635 inline float RandomFloat() {
00636 return genrand_real2();
00637 }
00638
00639 inline unsigned long RandomUInt() {
00640 return genrand_int32();
00641 }
00642 inline bool Quadratic(float A, float B, float C, float *t0,
00643 float *t1) {
00644
00645 float discrim = B * B - 4.f * A * C;
00646 if (discrim < 0.) return false;
00647 float rootDiscrim = sqrtf(discrim);
00648
00649 float q;
00650 if (B < 0) q = -.5f * (B - rootDiscrim);
00651 else q = -.5f * (B + rootDiscrim);
00652 *t0 = q / A;
00653 *t1 = C / q;
00654 if (*t0 > *t1) swap(*t0, *t1);
00655 return true;
00656 }
00657 inline float SmoothStep(float min, float max, float value) {
00658 float v = Clamp((value - min) / (max - min), 0.f, 1.f);
00659 return v * v * (-2.f * v + 3.f);
00660 }
00661 inline float ExponentialAverage(float avg,
00662 float val, float alpha) {
00663 return (1.f - alpha) * val + alpha * avg;
00664 }
00665 #endif // PBRT_PBRT_H