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
00026 #include "stdafx.h"
00027 #include "paramset.h"
00028 #include "floatfile.h"
00029 #include "textures/constant.h"
00030
00031
00032 #define ADD_PARAM_TYPE(T, vec) \
00033 (vec).push_back(new ParamSetItem<T>(name, (T *)data, nItems))
00034 #define LOOKUP_PTR(vec) \
00035 for (uint32_t i = 0; i < (vec).size(); ++i) \
00036 if ((vec)[i]->name == name) { \
00037 *nItems = (vec)[i]->nItems; \
00038 (vec)[i]->lookedUp = true; \
00039 return (vec)[i]->data; \
00040 } \
00041 return NULL
00042 #define LOOKUP_ONE(vec) \
00043 for (uint32_t i = 0; i < (vec).size(); ++i) { \
00044 if ((vec)[i]->name == name && \
00045 (vec)[i]->nItems == 1) { \
00046 (vec)[i]->lookedUp = true; \
00047 return *((vec)[i]->data); \
00048 } } \
00049 return d
00050
00051
00052 void ParamSet::AddFloat(const string &name, const float *data,
00053 int nItems) {
00054 EraseFloat(name);
00055 floats.push_back(new ParamSetItem<float>(name, data, nItems));
00056 }
00057
00058
00059 void ParamSet::AddInt(const string &name, const int *data, int nItems) {
00060 EraseInt(name);
00061 ADD_PARAM_TYPE(int, ints);
00062 }
00063
00064
00065 void ParamSet::AddBool(const string &name, const bool *data, int nItems) {
00066 EraseBool(name);
00067 ADD_PARAM_TYPE(bool, bools);
00068 }
00069
00070
00071 void ParamSet::AddPoint(const string &name, const Point *data, int nItems) {
00072 ErasePoint(name);
00073 ADD_PARAM_TYPE(Point, points);
00074 }
00075
00076
00077 void ParamSet::AddVector(const string &name, const Vector *data, int nItems) {
00078 EraseVector(name);
00079 ADD_PARAM_TYPE(Vector, vectors);
00080 }
00081
00082
00083 void ParamSet::AddNormal(const string &name, const Normal *data, int nItems) {
00084 EraseNormal(name);
00085 ADD_PARAM_TYPE(Normal, normals);
00086 }
00087
00088
00089 void ParamSet::AddRGBSpectrum(const string &name, const float *data, int nItems) {
00090 EraseSpectrum(name);
00091 Assert(nItems % 3 == 0);
00092 nItems /= 3;
00093 Spectrum *s = new Spectrum[nItems];
00094 for (int i = 0; i < nItems; ++i)
00095 s[i] = Spectrum::FromRGB(&data[3*i]);
00096 spectra.push_back(new ParamSetItem<Spectrum>(name, s, nItems));
00097 delete[] s;
00098 }
00099
00100
00101 void ParamSet::AddXYZSpectrum(const string &name, const float *data, int nItems) {
00102 EraseSpectrum(name);
00103 Assert(nItems % 3 == 0);
00104 nItems /= 3;
00105 Spectrum *s = new Spectrum[nItems];
00106 for (int i = 0; i < nItems; ++i)
00107 s[i] = Spectrum::FromXYZ(&data[3*i]);
00108 spectra.push_back(new ParamSetItem<Spectrum>(name, s, nItems));
00109 delete[] s;
00110 }
00111
00112
00113 void ParamSet::AddBlackbodySpectrum(const string &name, const float *data,
00114 int nItems) {
00115 EraseSpectrum(name);
00116 Assert(nItems % 2 == 0);
00117 nItems /= 2;
00118 Spectrum *s = new Spectrum[nItems];
00119 float *v = new float[nCIESamples];
00120 for (int i = 0; i < nItems; ++i) {
00121 Blackbody(CIE_lambda, nCIESamples, data[2*i], v);
00122 s[i] = data[2*i+1] * Spectrum::FromSampled(CIE_lambda, v, nCIESamples);
00123 }
00124 spectra.push_back(new ParamSetItem<Spectrum>(name, s, nItems));
00125 delete[] s;
00126 delete[] v;
00127 }
00128
00129
00130 void ParamSet::AddSampledSpectrum(const string &name, const float *data,
00131 int nItems) {
00132 EraseSpectrum(name);
00133 Assert(nItems % 2 == 0);
00134 nItems /= 2;
00135 float *wl = new float[nItems], *v = new float[nItems];
00136 for (int i = 0; i < nItems; ++i) {
00137 wl[i] = data[2*i];
00138 v[i] = data[2*i+1];
00139 }
00140 Spectrum s = Spectrum::FromSampled(wl, v, nItems);
00141 spectra.push_back(new ParamSetItem<Spectrum>(name, &s, 1));
00142 }
00143
00144
00145 void ParamSet::AddSampledSpectrumFiles(const string &name, const char **names,
00146 int nItems) {
00147 EraseSpectrum(name);
00148 Spectrum *s = new Spectrum[nItems];
00149 for (int i = 0; i < nItems; ++i) {
00150 if (cachedSpectra.find(names[i]) != cachedSpectra.end()) {
00151 s[i] = cachedSpectra[names[i]];
00152 continue;
00153 }
00154
00155 vector<float> vals;
00156 if (!ReadFloatFile(names[i], &vals)) {
00157 Warning("Unable to read SPD file \"%s\". Using black distribution.",
00158 names[i]);
00159 s[i] = Spectrum(0.);
00160 }
00161 else {
00162 if (vals.size() % 2) {
00163 Warning("Extra value found in spectrum file \"%s\". "
00164 "Ignoring it.", names[i]);
00165 }
00166 vector<float> wls, v;
00167 for (uint32_t j = 0; j < vals.size() / 2; ++j) {
00168 wls.push_back(vals[2*j]);
00169 v.push_back(vals[2*j+1]);
00170 }
00171 s[i] = Spectrum::FromSampled(&wls[0], &v[0], wls.size());
00172 }
00173 cachedSpectra[names[i]] = s[i];
00174 }
00175
00176 spectra.push_back(new ParamSetItem<Spectrum>(name, s, nItems));
00177 delete[] s;
00178 }
00179
00180
00181 map<string, Spectrum> ParamSet::cachedSpectra;
00182 void ParamSet::AddString(const string &name, const string *data, int nItems) {
00183 EraseString(name);
00184 ADD_PARAM_TYPE(string, strings);
00185 }
00186
00187
00188 void ParamSet::AddTexture(const string &name, const string &value) {
00189 EraseTexture(name);
00190 textures.push_back(new ParamSetItem<string>(name, (string *)&value, 1));
00191 }
00192
00193
00194 bool ParamSet::EraseInt(const string &n) {
00195 for (uint32_t i = 0; i < ints.size(); ++i)
00196 if (ints[i]->name == n) {
00197 ints.erase(ints.begin() + i);
00198 return true;
00199 }
00200 return false;
00201 }
00202
00203
00204 bool ParamSet::EraseBool(const string &n) {
00205 for (uint32_t i = 0; i < bools.size(); ++i)
00206 if (bools[i]->name == n) {
00207 bools.erase(bools.begin() + i);
00208 return true;
00209 }
00210 return false;
00211 }
00212
00213
00214 bool ParamSet::EraseFloat(const string &n) {
00215 for (uint32_t i = 0; i < floats.size(); ++i)
00216 if (floats[i]->name == n) {
00217 floats.erase(floats.begin() + i);
00218 return true;
00219 }
00220 return false;
00221 }
00222
00223
00224 bool ParamSet::ErasePoint(const string &n) {
00225 for (uint32_t i = 0; i < points.size(); ++i)
00226 if (points[i]->name == n) {
00227 points.erase(points.begin() + i);
00228 return true;
00229 }
00230 return false;
00231 }
00232
00233
00234 bool ParamSet::EraseVector(const string &n) {
00235 for (uint32_t i = 0; i < vectors.size(); ++i)
00236 if (vectors[i]->name == n) {
00237 vectors.erase(vectors.begin() + i);
00238 return true;
00239 }
00240 return false;
00241 }
00242
00243
00244 bool ParamSet::EraseNormal(const string &n) {
00245 for (uint32_t i = 0; i < normals.size(); ++i)
00246 if (normals[i]->name == n) {
00247 normals.erase(normals.begin() + i);
00248 return true;
00249 }
00250 return false;
00251 }
00252
00253
00254 bool ParamSet::EraseSpectrum(const string &n) {
00255 for (uint32_t i = 0; i < spectra.size(); ++i)
00256 if (spectra[i]->name == n) {
00257 spectra.erase(spectra.begin() + i);
00258 return true;
00259 }
00260 return false;
00261 }
00262
00263
00264 bool ParamSet::EraseString(const string &n) {
00265 for (uint32_t i = 0; i < strings.size(); ++i)
00266 if (strings[i]->name == n) {
00267 strings.erase(strings.begin() + i);
00268 return true;
00269 }
00270 return false;
00271 }
00272
00273
00274 bool ParamSet::EraseTexture(const string &n) {
00275 for (uint32_t i = 0; i < textures.size(); ++i)
00276 if (textures[i]->name == n) {
00277 textures.erase(textures.begin() + i);
00278 return true;
00279 }
00280 return false;
00281 }
00282
00283
00284 float ParamSet::FindOneFloat(const string &name, float d) const {
00285 for (uint32_t i = 0; i < floats.size(); ++i)
00286 if (floats[i]->name == name && floats[i]->nItems == 1) {
00287 floats[i]->lookedUp = true;
00288 return *(floats[i]->data);
00289 }
00290 return d;
00291 }
00292
00293
00294 const float *ParamSet::FindFloat(const string &name, int *n) const {
00295 for (uint32_t i = 0; i < floats.size(); ++i)
00296 if (floats[i]->name == name) {
00297 *n = floats[i]->nItems;
00298 floats[i]->lookedUp = true;
00299 return floats[i]->data;
00300 }
00301 return NULL;
00302 }
00303
00304
00305 const int *ParamSet::FindInt(const string &name, int *nItems) const {
00306 LOOKUP_PTR(ints);
00307 }
00308
00309
00310 const bool *ParamSet::FindBool(const string &name, int *nItems) const {
00311 LOOKUP_PTR(bools);
00312 }
00313
00314
00315 int ParamSet::FindOneInt(const string &name, int d) const {
00316 LOOKUP_ONE(ints);
00317 }
00318
00319
00320 bool ParamSet::FindOneBool(const string &name, bool d) const {
00321 LOOKUP_ONE(bools);
00322 }
00323
00324
00325 const Point *ParamSet::FindPoint(const string &name, int *nItems) const {
00326 LOOKUP_PTR(points);
00327 }
00328
00329
00330 Point ParamSet::FindOnePoint(const string &name, const Point &d) const {
00331 LOOKUP_ONE(points);
00332 }
00333
00334
00335 const Vector *ParamSet::FindVector(const string &name, int *nItems) const {
00336 LOOKUP_PTR(vectors);
00337 }
00338
00339
00340 Vector ParamSet::FindOneVector(const string &name, const Vector &d) const {
00341 LOOKUP_ONE(vectors);
00342 }
00343
00344
00345 const Normal *ParamSet::FindNormal(const string &name, int *nItems) const {
00346 LOOKUP_PTR(normals);
00347 }
00348
00349
00350 Normal ParamSet::FindOneNormal(const string &name, const Normal &d) const {
00351 LOOKUP_ONE(normals);
00352 }
00353
00354
00355 const Spectrum *ParamSet::FindSpectrum(const string &name, int *nItems) const {
00356 LOOKUP_PTR(spectra);
00357 }
00358
00359
00360 Spectrum ParamSet::FindOneSpectrum(const string &name, const Spectrum &d) const {
00361 LOOKUP_ONE(spectra);
00362 }
00363
00364
00365 const string *ParamSet::FindString(const string &name, int *nItems) const {
00366 LOOKUP_PTR(strings);
00367 }
00368
00369
00370 string ParamSet::FindOneString(const string &name, const string &d) const {
00371 LOOKUP_ONE(strings);
00372 }
00373
00374
00375 string ParamSet::FindTexture(const string &name) const {
00376 string d = "";
00377 LOOKUP_ONE(textures);
00378 }
00379
00380
00381 void ParamSet::ReportUnused() const {
00382 #define CHECK_UNUSED(v) \
00383 for (i = 0; i < (v).size(); ++i) \
00384 if (!(v)[i]->lookedUp) \
00385 Warning("Parameter \"%s\" not used", \
00386 (v)[i]->name.c_str())
00387 uint32_t i;
00388 CHECK_UNUSED(ints); CHECK_UNUSED(bools);
00389 CHECK_UNUSED(floats); CHECK_UNUSED(points);
00390 CHECK_UNUSED(vectors); CHECK_UNUSED(normals);
00391 CHECK_UNUSED(spectra); CHECK_UNUSED(strings);
00392 CHECK_UNUSED(textures);
00393 }
00394
00395
00396 void ParamSet::Clear() {
00397 #define DEL_PARAMS(name) \
00398 (name).erase((name).begin(), (name).end())
00399 DEL_PARAMS(ints); DEL_PARAMS(bools);
00400 DEL_PARAMS(floats); DEL_PARAMS(points);
00401 DEL_PARAMS(vectors); DEL_PARAMS(normals);
00402 DEL_PARAMS(spectra); DEL_PARAMS(strings);
00403 DEL_PARAMS(textures);
00404 #undef DEL_PARAMS
00405 }
00406
00407
00408 string ParamSet::ToString() const {
00409 string ret;
00410 uint32_t i;
00411 int j;
00412 string typeString;
00413 const int bufLen = 48*1024*1024;
00414 static char *buf = new char[bufLen];
00415 char *bufEnd = buf + bufLen;
00416 for (i = 0; i < ints.size(); ++i) {
00417 char *bufp = buf;
00418 *bufp = '\0';
00419 const Reference<ParamSetItem<int> > &item = ints[i];
00420 typeString = "integer ";
00421
00422 int nPrint = item->nItems;
00423 ret += string("\"");
00424 ret += typeString;
00425 ret += item->name;
00426 ret += string("\"");
00427 ret += string(" [");
00428 for (j = 0; j < nPrint; ++j)
00429 bufp += snprintf(bufp, bufEnd - bufp, "%d ", item->data[j]);
00430 ret += buf;
00431 ret += string("] ");
00432 }
00433 for (i = 0; i < bools.size(); ++i) {
00434 char *bufp = buf;
00435 *bufp = '\0';
00436 const Reference<ParamSetItem<bool> > &item = bools[i];
00437 typeString = "bool ";
00438
00439 int nPrint = item->nItems;
00440 ret += string("\"");
00441 ret += typeString;
00442 ret += item->name;
00443 ret += string("\"");
00444 ret += string(" [");
00445 for (j = 0; j < nPrint; ++j)
00446 bufp += snprintf(bufp, bufEnd - bufp, "\"%s\" ", item->data[j] ? "true" : "false");
00447 ret += buf;
00448 ret += string("] ");
00449 }
00450 for (i = 0; i < floats.size(); ++i) {
00451 char *bufp = buf;
00452 *bufp = '\0';
00453 const Reference<ParamSetItem<float> > &item = floats[i];
00454 typeString = "float ";
00455
00456 int nPrint = item->nItems;
00457 ret += string("\"");
00458 ret += typeString;
00459 ret += item->name;
00460 ret += string("\"");
00461 ret += string(" [");
00462 for (j = 0; j < nPrint; ++j)
00463 bufp += snprintf(bufp, bufEnd - bufp, "%.8g ", item->data[j]);
00464 ret += buf;
00465 ret += string("] ");
00466 }
00467 for (i = 0; i < points.size(); ++i) {
00468 char *bufp = buf;
00469 *bufp = '\0';
00470 const Reference<ParamSetItem<Point> > &item = points[i];
00471 typeString = "point ";
00472
00473 int nPrint = item->nItems;
00474 ret += string("\"");
00475 ret += typeString;
00476 ret += item->name;
00477 ret += string("\"");
00478 ret += string(" [");
00479 for (j = 0; j < nPrint; ++j)
00480 bufp += snprintf(bufp, bufEnd - bufp, "%.8g %.8g %.8g ", item->data[j].x,
00481 item->data[j].y, item->data[j].z);
00482 ret += buf;
00483 ret += string("] ");
00484 }
00485 for (i = 0; i < vectors.size(); ++i) {
00486 char *bufp = buf;
00487 *bufp = '\0';
00488 const Reference<ParamSetItem<Vector> > &item = vectors[i];
00489 typeString = "vector ";
00490
00491 int nPrint = item->nItems;
00492 ret += string("\"");
00493 ret += typeString;
00494 ret += item->name;
00495 ret += string("\"");
00496 ret += string(" [");
00497 for (j = 0; j < nPrint; ++j)
00498 bufp += snprintf(bufp, bufEnd - bufp, "%.8g %.8g %.8g ", item->data[j].x,
00499 item->data[j].y, item->data[j].z);
00500 ret += buf;
00501 ret += string("] ");
00502 }
00503 for (i = 0; i < normals.size(); ++i) {
00504 char *bufp = buf;
00505 *bufp = '\0';
00506 const Reference<ParamSetItem<Normal> > &item = normals[i];
00507 typeString = "normal ";
00508
00509 int nPrint = item->nItems;
00510 ret += string("\"");
00511 ret += typeString;
00512 ret += item->name;
00513 ret += string("\"");
00514 ret += string(" [");
00515 for (j = 0; j < nPrint; ++j)
00516 bufp += snprintf(bufp, bufEnd - bufp, "%.8g %.8g %.8g ", item->data[j].x,
00517 item->data[j].y, item->data[j].z);
00518 ret += buf;
00519 ret += string("] ");
00520 }
00521 for (i = 0; i < strings.size(); ++i) {
00522 char *bufp = buf;
00523 *bufp = '\0';
00524 const Reference<ParamSetItem<string> > &item = strings[i];
00525 typeString = "string ";
00526
00527 int nPrint = item->nItems;
00528 ret += string("\"");
00529 ret += typeString;
00530 ret += item->name;
00531 ret += string("\"");
00532 ret += string(" [");
00533 for (j = 0; j < nPrint; ++j)
00534 bufp += snprintf(bufp, bufEnd - bufp, "\"%s\" ", item->data[j].c_str());
00535 ret += buf;
00536 ret += string("] ");
00537 }
00538 for (i = 0; i < textures.size(); ++i) {
00539 char *bufp = buf;
00540 *bufp = '\0';
00541 const Reference<ParamSetItem<string> > &item = textures[i];
00542 typeString = "texture ";
00543
00544 int nPrint = item->nItems;
00545 ret += string("\"");
00546 ret += typeString;
00547 ret += item->name;
00548 ret += string("\"");
00549 ret += string(" [");
00550 for (j = 0; j < nPrint; ++j)
00551 bufp += snprintf(bufp, bufEnd - bufp, "\"%s\" ", item->data[j].c_str());
00552 ret += buf;
00553 ret += string("] ");
00554 }
00555 for (i = 0; i < spectra.size(); ++i) {
00556 char *bufp = buf;
00557 *bufp = '\0';
00558 const Reference<ParamSetItem<Spectrum> > &item = spectra[i];
00559 typeString = "color ";
00560
00561 int nPrint = item->nItems;
00562 ret += string("\"");
00563 ret += typeString;
00564 ret += item->name;
00565 ret += string("\"");
00566 ret += string(" [");
00567 for (j = 0; j < nPrint; ++j) {
00568 float rgb[3];
00569 item->data[j].ToRGB(rgb);
00570 bufp += snprintf(bufp, bufEnd - bufp, "%.8g %.8g %.8g ", rgb[0], rgb[1], rgb[2]);
00571 }
00572 ret += buf;
00573 ret += string("] ");
00574 }
00575 return ret;
00576 }
00577
00578
00579
00580
00581 Reference<Texture<Spectrum> >
00582 TextureParams::GetSpectrumTexture(const string &n,
00583 const Spectrum &def) const {
00584 string name = geomParams.FindTexture(n);
00585 if (name == "") name = materialParams.FindTexture(n);
00586 if (name != "") {
00587 if (spectrumTextures.find(name) != spectrumTextures.end())
00588 return spectrumTextures[name];
00589 else
00590 Error("Couldn't find spectrum texture named \"%s\" "
00591 "for parameter \"%s\"", name.c_str(), n.c_str());
00592 }
00593 Spectrum val = geomParams.FindOneSpectrum(n,
00594 materialParams.FindOneSpectrum(n, def));
00595 return new ConstantTexture<Spectrum>(val);
00596 }
00597
00598
00599 Reference<Texture<float> > TextureParams::GetFloatTexture(const string &n,
00600 float def) const {
00601 string name = geomParams.FindTexture(n);
00602 if (name == "") name = materialParams.FindTexture(n);
00603 if (name != "") {
00604 if (floatTextures.find(name) != floatTextures.end())
00605 return floatTextures[name];
00606 else
00607 Error("Couldn't find float texture named \"%s\" for parameter \"%s\"",
00608 name.c_str(), n.c_str());
00609 }
00610 float val = geomParams.FindOneFloat(n,
00611 materialParams.FindOneFloat(n, def));
00612 return new ConstantTexture<float>(val);
00613 }
00614
00615