00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "pbrt.h"
00026 #include "timer.h"
00027 #include <map>
00028 using std::map;
00029
00030 #include <stdarg.h>
00031
00032 #define PBRT_ERROR_IGNORE 0
00033 #define PBRT_ERROR_CONTINUE 1
00034 #define PBRT_ERROR_ABORT 2
00035
00036 static void processError(const char *format, va_list args,
00037 const char *message, int disposition) {
00038 #ifndef WIN32
00039 char *errorBuf;
00040 vasprintf(&errorBuf, format, args);
00041 #else
00042 char errorBuf[2048];
00043 _vsnprintf(errorBuf, sizeof(errorBuf), format, args);
00044 #endif
00045
00046 switch (disposition) {
00047 case PBRT_ERROR_IGNORE:
00048 return;
00049 case PBRT_ERROR_CONTINUE:
00050 fprintf(stderr, "%s: %s\n", message, errorBuf);
00051
00052 extern int line_num;
00053 if (line_num != 0) {
00054 extern string current_file;
00055 fprintf(stderr, "\tLine %d, file %s\n", line_num,
00056 current_file.c_str());
00057 }
00058 break;
00059 case PBRT_ERROR_ABORT:
00060 fprintf(stderr, "%s: %s\n", message, errorBuf);
00061
00062 extern int line_num;
00063 if (line_num != 0) {
00064 extern string current_file;
00065 fprintf(stderr, "\tLine %d, file %s\n", line_num,
00066 current_file.c_str());
00067 }
00068 exit(1);
00069 }
00070 #ifndef WIN32
00071 free(errorBuf);
00072 #endif
00073 }
00074 COREDLL void Info(const char *format, ...) {
00075 va_list args;
00076 va_start(args, format);
00077 processError(format, args, "Notice", PBRT_ERROR_CONTINUE);
00078 va_end(args);
00079 }
00080 COREDLL void Warning(const char *format, ...) {
00081 va_list args;
00082 va_start(args, format);
00083 processError(format, args, "Warning", PBRT_ERROR_CONTINUE);
00084 va_end(args);
00085 }
00086 COREDLL void Error(const char *format, ...) {
00087 va_list args;
00088 va_start(args, format);
00089 processError(format, args, "Error", PBRT_ERROR_CONTINUE);
00090 va_end(args);
00091 }
00092 COREDLL void Severe(const char *format, ...) {
00093 va_list args;
00094 va_start(args, format);
00095 processError(format, args, "Fatal Error", PBRT_ERROR_ABORT);
00096 va_end(args);
00097 }
00098
00099 COREDLL bool SolveLinearSystem2x2(const float A[2][2],
00100 const float B[2], float x[2]) {
00101 float det = A[0][0]*A[1][1] - A[0][1]*A[1][0];
00102 if (fabsf(det) < 1e-5)
00103 return false;
00104 float invDet = 1.0f/det;
00105 x[0] = (A[1][1]*B[0] - A[0][1]*B[1]) * invDet;
00106 x[1] = (A[0][0]*B[1] - A[1][0]*B[0]) * invDet;
00107 return true;
00108 }
00109 Matrix4x4::Matrix4x4(float mat[4][4]) {
00110 memcpy(m, mat, 16*sizeof(float));
00111 }
00112 Matrix4x4::Matrix4x4(float t00, float t01, float t02, float t03,
00113 float t10, float t11, float t12, float t13,
00114 float t20, float t21, float t22, float t23,
00115 float t30, float t31, float t32, float t33) {
00116 m[0][0] = t00; m[0][1] = t01; m[0][2] = t02; m[0][3] = t03;
00117 m[1][0] = t10; m[1][1] = t11; m[1][2] = t12; m[1][3] = t13;
00118 m[2][0] = t20; m[2][1] = t21; m[2][2] = t22; m[2][3] = t23;
00119 m[3][0] = t30; m[3][1] = t31; m[3][2] = t32; m[3][3] = t33;
00120 }
00121 Reference<Matrix4x4> Matrix4x4::Transpose() const {
00122 return new Matrix4x4(m[0][0], m[1][0], m[2][0], m[3][0],
00123 m[0][1], m[1][1], m[2][1], m[3][1],
00124 m[0][2], m[1][2], m[2][2], m[3][2],
00125 m[0][3], m[1][3], m[2][3], m[3][3]);
00126 }
00127 Reference<Matrix4x4> Matrix4x4::Inverse() const {
00128 int indxc[4], indxr[4];
00129 int ipiv[4] = { 0, 0, 0, 0 };
00130 float minv[4][4];
00131 memcpy(minv, m, 4*4*sizeof(float));
00132 for (int i = 0; i < 4; i++) {
00133 int irow = -1, icol = -1;
00134 float big = 0.;
00135
00136 for (int j = 0; j < 4; j++) {
00137 if (ipiv[j] != 1) {
00138 for (int k = 0; k < 4; k++) {
00139 if (ipiv[k] == 0) {
00140 if (fabsf(minv[j][k]) >= big) {
00141 big = float(fabsf(minv[j][k]));
00142 irow = j;
00143 icol = k;
00144 }
00145 }
00146 else if (ipiv[k] > 1)
00147 Error("Singular matrix in MatrixInvert");
00148 }
00149 }
00150 }
00151 ++ipiv[icol];
00152
00153 if (irow != icol) {
00154 for (int k = 0; k < 4; ++k)
00155 swap(minv[irow][k], minv[icol][k]);
00156 }
00157 indxr[i] = irow;
00158 indxc[i] = icol;
00159 if (minv[icol][icol] == 0.)
00160 Error("Singular matrix in MatrixInvert");
00161
00162 float pivinv = 1.f / minv[icol][icol];
00163 minv[icol][icol] = 1.f;
00164 for (int j = 0; j < 4; j++)
00165 minv[icol][j] *= pivinv;
00166
00167 for (int j = 0; j < 4; j++) {
00168 if (j != icol) {
00169 float save = minv[j][icol];
00170 minv[j][icol] = 0;
00171 for (int k = 0; k < 4; k++)
00172 minv[j][k] -= minv[icol][k]*save;
00173 }
00174 }
00175 }
00176
00177 for (int j = 3; j >= 0; j--) {
00178 if (indxr[j] != indxc[j]) {
00179 for (int k = 0; k < 4; k++)
00180 swap(minv[k][indxr[j]], minv[k][indxc[j]]);
00181 }
00182 }
00183 return new Matrix4x4(minv);
00184 }
00185
00186 struct COREDLL StatTracker {
00187 StatTracker(const string &cat, const string &n,
00188 StatsCounterType *pa, StatsCounterType *pb = NULL,
00189 bool percentage = true);
00190 string category, name;
00191 StatsCounterType *ptra, *ptrb;
00192 bool percentage;
00193 };
00194 typedef map<std::pair<string, string>, StatTracker *> TrackerMap;
00195 static TrackerMap trackers;
00196 static void addTracker(StatTracker *newTracker) {
00197 std::pair<string, string> s = std::make_pair(newTracker->category, newTracker->name);
00198 if (trackers.find(s) != trackers.end()) {
00199 newTracker->ptra = trackers[s]->ptra;
00200 newTracker->ptrb = trackers[s]->ptrb;
00201 return;
00202 }
00203 trackers[s] = newTracker;
00204 }
00205 static void StatsPrintVal(FILE *f, StatsCounterType v);
00206 static void StatsPrintVal(FILE *f, StatsCounterType v1, StatsCounterType v2);
00207
00208 StatTracker::StatTracker(const string &cat, const string &n,
00209 StatsCounterType *pa, StatsCounterType *pb, bool p) {
00210 category = cat;
00211 name = n;
00212 ptra = pa;
00213 ptrb = pb;
00214 percentage = p;
00215 }
00216 StatsCounter::StatsCounter(const string &category, const string &name) {
00217 num = 0;
00218 addTracker(new StatTracker(category, name, &num));
00219 }
00220 StatsRatio::StatsRatio(const string &category, const string &name) {
00221 na = nb = 0;
00222 addTracker(new StatTracker(category, name, &na, &nb, false));
00223 }
00224 StatsPercentage::StatsPercentage(const string &category, const string &name) {
00225 na = nb = 0;
00226 addTracker(new StatTracker(category, name, &na, &nb, true));
00227 }
00228 void StatsPrint(FILE *dest) {
00229 fprintf(dest, "Statistics:\n");
00230 TrackerMap::iterator iter = trackers.begin();
00231 string lastCategory;
00232 while (iter != trackers.end()) {
00233
00234 StatTracker *tr = iter->second;
00235 if (tr->category != lastCategory) {
00236 fprintf(dest, "%s\n", tr->category.c_str());
00237 lastCategory = tr->category;
00238 }
00239 fprintf(dest, " %s", tr->name.c_str());
00240
00241 int resultsColumn = 56;
00242 int paddingSpaces = resultsColumn - (int) tr->name.size();
00243 while (paddingSpaces-- > 0)
00244 putc(' ', dest);
00245 if (tr->ptrb == NULL)
00246 StatsPrintVal(dest, *tr->ptra);
00247 else {
00248 if (*tr->ptrb > 0) {
00249 float ratio = (float)*tr->ptra / (float)*tr->ptrb;
00250 StatsPrintVal(dest, *tr->ptra, *tr->ptrb);
00251 if (tr->percentage)
00252 fprintf(dest, " (%3.2f%%)", 100. * ratio);
00253 else
00254 fprintf(dest, " (%.2fx)", ratio);
00255 }
00256 else
00257 StatsPrintVal(dest, *tr->ptra, *tr->ptrb);
00258 }
00259 fprintf(dest, "\n");
00260 ++iter;
00261 }
00262 }
00263 static void StatsPrintVal(FILE *f, StatsCounterType v) {
00264 if (v > 1e9) fprintf(f, "%.3fB", v / 1e9f);
00265 else if (v > 1e6) fprintf(f, "%.3fM", v / 1e6f);
00266 else if (v > 1e4) fprintf(f, "%.1fk", v / 1e3f);
00267 else fprintf(f, "%.0f", (float)v);
00268 }
00269 static void StatsPrintVal(FILE *f, StatsCounterType v1,
00270 StatsCounterType v2) {
00271 StatsCounterType m = min(v1, v2);
00272 if (m > 1e9) fprintf(f, "%.3fB:%.3fB", v1 / 1e9f, v2 / 1e9f);
00273 else if (m > 1e6) fprintf(f, "%.3fM:%.3fM", v1 / 1e6f, v2 / 1e6f);
00274 else if (m > 1e4) fprintf(f, "%.1fk:%.1fk", v1 / 1e3f, v2 / 1e3f);
00275 else fprintf(f, "%.0f:%.0f", v1, v2);
00276 }
00277 void StatsCleanup() {
00278 TrackerMap::iterator iter = trackers.begin();
00279 string lastCategory;
00280 while (iter != trackers.end()) {
00281 delete iter->second;
00282 ++iter;
00283 }
00284 trackers.erase(trackers.begin(), trackers.end());
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 #define N 624
00319 #define M 397
00320 #define MATRIX_A 0x9908b0dfUL
00321 #define UPPER_MASK 0x80000000UL
00322 #define LOWER_MASK 0x7fffffffUL
00323
00324 static unsigned long mt[N];
00325 static int mti=N+1;
00326
00327 static void init_genrand(u_long seed) {
00328 mt[0]= seed & 0xffffffffUL;
00329 for (mti=1; mti<N; mti++) {
00330 mt[mti] =
00331 (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
00332
00333
00334
00335
00336 mt[mti] &= 0xffffffffUL;
00337
00338 }
00339 }
00340 COREDLL unsigned long genrand_int32(void)
00341 {
00342 unsigned long y;
00343 static unsigned long mag01[2]={0x0UL, MATRIX_A};
00344
00345
00346 if (mti >= N) {
00347 int kk;
00348
00349 if (mti == N+1)
00350 init_genrand(5489UL);
00351
00352 for (kk=0;kk<N-M;kk++) {
00353 y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
00354 mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
00355 }
00356 for (;kk<N-1;kk++) {
00357 y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
00358 mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
00359 }
00360 y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
00361 mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
00362
00363 mti = 0;
00364 }
00365
00366 y = mt[mti++];
00367
00368
00369 y ^= (y >> 11);
00370 y ^= (y << 7) & 0x9d2c5680UL;
00371 y ^= (y << 15) & 0xefc60000UL;
00372 y ^= (y >> 18);
00373
00374 return y;
00375 }
00376
00377 COREDLL float genrand_real1(void)
00378 {
00379 return genrand_int32()*((float)1.0/(float)4294967295.0);
00380
00381 }
00382
00383 COREDLL float genrand_real2(void)
00384 {
00385 return genrand_int32()*((float)1.0/(float)4294967296.0);
00386
00387 }
00388
00389 COREDLL void *AllocAligned(size_t size) {
00390 #ifndef L1_CACHE_LINE_SIZE
00391 #define L1_CACHE_LINE_SIZE 64
00392 #endif
00393 return memalign(L1_CACHE_LINE_SIZE, size);
00394 }
00395 COREDLL void FreeAligned(void *ptr) {
00396 #ifdef WIN32 // NOBOOK
00397 _aligned_free(ptr);
00398 #else // NOBOOK
00399 free(ptr);
00400 #endif // NOBOOK
00401 }
00402
00403 ProgressReporter::ProgressReporter(int totalWork, const string &title, int bar_length)
00404 : totalPlusses(bar_length - title.size()) {
00405 plussesPrinted = 0;
00406 frequency = (float)totalWork / (float)totalPlusses;
00407 count = frequency;
00408 timer = new Timer();
00409 timer->Start();
00410 outFile = stdout;
00411
00412 const int bufLen = title.size() + totalPlusses + 64;
00413 buf = new char[bufLen];
00414 snprintf(buf, bufLen, "\r%s: [", title.c_str());
00415 curSpace = buf + strlen(buf);
00416 char *s = curSpace;
00417 for (int i = 0; i < totalPlusses; ++i)
00418 *s++ = ' ';
00419 *s++ = ']';
00420 *s++ = ' ';
00421 *s++ = '\0';
00422 fprintf(outFile, buf);
00423 fflush(outFile);
00424 }
00425 ProgressReporter::~ProgressReporter() { delete[] buf; delete timer; }
00426 void ProgressReporter::Update(int num) const {
00427 count -= num;
00428 bool updatedAny = false;
00429 while (count <= 0) {
00430 count += frequency;
00431 if (plussesPrinted++ < totalPlusses)
00432 *curSpace++ = '+';
00433 updatedAny = true;
00434 }
00435 if (updatedAny) {
00436 fputs(buf, outFile);
00437
00438 float percentDone = (float)plussesPrinted / (float)totalPlusses;
00439 float seconds = (float) timer->Time();
00440 float estRemaining = seconds / percentDone - seconds;
00441 if (percentDone == 1.f)
00442 fprintf(outFile, " (%.1fs) ", seconds);
00443 else
00444 fprintf(outFile, " (%.1fs|%.1fs) ", seconds, max(0.f, estRemaining));
00445 fflush(outFile);
00446 }
00447 }
00448 void ProgressReporter::Done() const {
00449 while (plussesPrinted++ < totalPlusses)
00450 *curSpace++ = '+';
00451 fputs(buf, outFile);
00452 float seconds = (float) timer->Time();
00453 fprintf(outFile, " (%.1fs) \n", seconds);
00454 fflush(outFile);
00455 }