pbrt.h

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

Generated on Wed Sep 26 14:01:21 2007 for pbrt by  doxygen 1.5.1