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 "materials/measured.h"
00028 #include "paramset.h"
00029 #include "floatfile.h"
00030
00031
00032 static map<string, float *> loadedRegularHalfangle;
00033 static map<string, KdTree<IrregIsotropicBRDFSample> *> loadedThetaPhi;
00034 MeasuredMaterial::MeasuredMaterial(const string &filename,
00035 Reference<Texture<float> > bump) {
00036 bumpMap = bump;
00037 const char *suffix = strrchr(filename.c_str(), '.');
00038 regularHalfangleData = NULL;
00039 thetaPhiData = NULL;
00040 if (!suffix)
00041 Error("No suffix in measured BRDF filename \"%s\". "
00042 "Can't determine file type (.brdf / .merl)", filename.c_str());
00043 if (!strcmp(suffix, ".brdf") || !strcmp(suffix, ".BRDF")) {
00044
00045 if (loadedThetaPhi.find(filename) != loadedThetaPhi.end()) {
00046 thetaPhiData = loadedThetaPhi[filename];
00047 return;
00048 }
00049
00050 vector<float> values;
00051 if (!ReadFloatFile(filename.c_str(), &values))
00052 Error("Unable to read BRDF data from file \"%s\"", filename.c_str());
00053
00054 uint32_t pos = 0;
00055 int numWls = int(values[pos++]);
00056 if ((values.size() - 1 - numWls) % (4 + numWls) != 0)
00057 Error("Excess or insufficient data in theta, phi BRDF file \"%s\"",
00058 filename.c_str());
00059 vector<float> wls;
00060 for (int i = 0; i < numWls; ++i)
00061 wls.push_back(values[pos++]);
00062
00063 BBox bbox;
00064 vector<IrregIsotropicBRDFSample> samples;
00065 while (pos < values.size()) {
00066 float thetai = values[pos++];
00067 float phii = values[pos++];
00068 float thetao = values[pos++];
00069 float phio = values[pos++];
00070 Vector wo = SphericalDirection(sinf(thetao), cosf(thetao), phio);
00071 Vector wi = SphericalDirection(sinf(thetai), cosf(thetai), phii);
00072 Spectrum s = Spectrum::FromSampled(&wls[0], &values[pos], numWls);
00073 pos += numWls;
00074 Point p = BRDFRemap(wo, wi);
00075 samples.push_back(IrregIsotropicBRDFSample(p, s));
00076 bbox = Union(bbox, p);
00077 }
00078 loadedThetaPhi[filename] = thetaPhiData = new KdTree<IrregIsotropicBRDFSample>(samples);
00079 }
00080 else {
00081
00082 nThetaH = 90;
00083 nThetaD = 90;
00084 nPhiD = 180;
00085
00086 if (loadedRegularHalfangle.find(filename) != loadedRegularHalfangle.end()) {
00087 regularHalfangleData = loadedRegularHalfangle[filename];
00088 return;
00089 }
00090
00091 FILE *f = fopen(filename.c_str(), "rb");
00092 if (!f) {
00093 Error("Unable to open BRDF data file \"%s\"", filename.c_str());
00094 return;
00095 }
00096 int dims[3];
00097 if (fread(dims, sizeof(int), 3, f) != 3) {
00098 Error("Premature end-of-file in measured BRDF data file \"%s\"",
00099 filename.c_str());
00100 fclose(f);
00101 return;
00102 }
00103 uint32_t n = dims[0] * dims[1] * dims[2];
00104 if (n != nThetaH * nThetaD * nPhiD) {
00105 Error("Dimensions don't match\n");
00106 fclose(f);
00107 return;
00108 }
00109
00110 regularHalfangleData = new float[3*n];
00111 const uint32_t chunkSize = 2*nPhiD;
00112 double *tmp = ALLOCA(double, chunkSize);
00113 uint32_t nChunks = n / chunkSize;
00114 Assert((n % chunkSize) == 0);
00115 float scales[3] = { 1.f/1500.f, 1.15f/1500.f, 1.66f/1500.f };
00116 for (int c = 0; c < 3; ++c) {
00117 int offset = 0;
00118 for (uint32_t i = 0; i < nChunks; ++i) {
00119 if (fread(tmp, sizeof(double), chunkSize, f) != chunkSize) {
00120 Error("Premature end-of-file in measured BRDF data file \"%s\"",
00121 filename.c_str());
00122 delete[] regularHalfangleData;
00123 regularHalfangleData = NULL;
00124 fclose(f);
00125 return;
00126 }
00127 for (uint32_t j = 0; j < chunkSize; ++j)
00128 regularHalfangleData[3 * offset++ + c] = max(0., tmp[j] * scales[c]);
00129 }
00130 }
00131
00132 loadedRegularHalfangle[filename] = regularHalfangleData;
00133 fclose(f);
00134 }
00135 }
00136
00137
00138 BSDF *MeasuredMaterial::GetBSDF(const DifferentialGeometry &dgGeom,
00139 const DifferentialGeometry &dgShading,
00140 MemoryArena &arena) const {
00141
00142 DifferentialGeometry dgs;
00143 if (bumpMap)
00144 Bump(bumpMap, dgGeom, dgShading, &dgs);
00145 else
00146 dgs = dgShading;
00147 BSDF *bsdf = BSDF_ALLOC(arena, BSDF)(dgs, dgGeom.nn);
00148 if (regularHalfangleData)
00149 bsdf->Add(BSDF_ALLOC(arena, RegularHalfangleBRDF)
00150 (regularHalfangleData, nThetaH, nThetaD, nPhiD));
00151 else if (thetaPhiData)
00152 bsdf->Add(BSDF_ALLOC(arena, IrregIsotropicBRDF)(thetaPhiData));
00153 return bsdf;
00154 }
00155
00156
00157 MeasuredMaterial *CreateMeasuredMaterial(const Transform &xform,
00158 const TextureParams &mp) {
00159 Reference<Texture<float> > bumpMap = mp.GetFloatTexture("bumpmap", 0.f);
00160 return new MeasuredMaterial(mp.FindString("filename"), bumpMap);
00161 }
00162
00163