00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <cstdlib>
00023 #include <istream>
00024 #include <stdexcept>
00025 #include <sstream>
00026
00027 #include <boost/detail/container_fwd.hpp>
00028
00029 #include "luxrays/core/dataset.h"
00030 #include "luxrays/utils/properties.h"
00031 #include "luxrays/utils/sdl/scene.h"
00032
00033 using namespace luxrays;
00034 using namespace luxrays::sdl;
00035
00036 Scene::Scene(Context *ctx, const std::string &fileName, const int accelType) {
00037 extMeshCache = new ExtMeshCache(ctx);
00038 texMapCache = new TextureMapCache(ctx);
00039
00040 LR_LOG(ctx, "Reading scene: " << fileName);
00041
00042 scnProp = new Properties(fileName);
00043
00044
00045
00046
00047
00048 std::vector<float> vf = GetParameters(*scnProp, "scene.camera.lookat", 6, "10.0 0.0 0.0 0.0 0.0 0.0");
00049 Point o(vf.at(0), vf.at(1), vf.at(2));
00050 Point t(vf.at(3), vf.at(4), vf.at(5));
00051
00052 LR_LOG(ctx, "Camera postion: " << o);
00053 LR_LOG(ctx, "Camera target: " << t);
00054
00055 vf = GetParameters(*scnProp, "scene.camera.up", 3, "0.0 0.0 0.1");
00056 const Vector up(vf.at(0), vf.at(1), vf.at(2));
00057 camera = new PerspectiveCamera(o, t, up);
00058
00059 camera->lensRadius = scnProp->GetFloat("scene.camera.lensradius", 0.f);
00060 camera->focalDistance = scnProp->GetFloat("scene.camera.focaldistance", 10.f);
00061 camera->fieldOfView = scnProp->GetFloat("scene.camera.fieldofview", 45.f);
00062
00063
00064 if (scnProp->GetInt("scene.camera.motionblur.enable", 0)) {
00065 camera->motionBlur = true;
00066
00067 vf = GetParameters(*scnProp, "scene.camera.motionblur.lookat", 6, "10.0 1.0 0.0 0.0 1.0 0.0");
00068 camera->mbOrig = Point(vf.at(0), vf.at(1), vf.at(2));
00069 camera->mbTarget = Point(vf.at(3), vf.at(4), vf.at(5));
00070
00071 vf = GetParameters(*scnProp, "scene.camera.motionblur.up", 3, "0.0 0.0 0.1");
00072 camera->mbUp = Vector(vf.at(0), vf.at(1), vf.at(2));
00073 }
00074
00075
00076
00077
00078
00079 std::vector<std::string> matKeys = scnProp->GetAllKeys("scene.materials.");
00080 if (matKeys.size() == 0)
00081 throw std::runtime_error("No material definition found");
00082
00083 for (std::vector<std::string>::const_iterator matKey = matKeys.begin(); matKey != matKeys.end(); ++matKey) {
00084 const std::string &key = *matKey;
00085 const std::string matType = Properties::ExtractField(key, 2);
00086 if (matType == "")
00087 throw std::runtime_error("Syntax error in " + key);
00088 const std::string matName = Properties::ExtractField(key, 3);
00089 if (matName == "")
00090 throw std::runtime_error("Syntax error in " + key);
00091 LR_LOG(ctx, "Material definition: " << matName << " [" << matType << "]");
00092
00093 Material *mat = CreateMaterial(key, *scnProp);
00094
00095 materialIndices[matName] = materials.size();
00096 materials.push_back(mat);
00097 }
00098
00099
00100
00101
00102
00103 std::vector<std::string> objKeys = scnProp->GetAllKeys("scene.objects.");
00104 if (objKeys.size() == 0)
00105 throw std::runtime_error("Unable to find object definitions");
00106
00107 double lastPrint = WallClockTime();
00108 unsigned int objCount = 0;
00109 for (std::vector<std::string>::const_iterator objKey = objKeys.begin(); objKey != objKeys.end(); ++objKey) {
00110 const std::string &key = *objKey;
00111
00112
00113 const size_t dot1 = key.find(".", std::string("scene.objects.").length());
00114 if (dot1 == std::string::npos)
00115 continue;
00116 const size_t dot2 = key.find(".", dot1 + 1);
00117 if (dot2 != std::string::npos)
00118 continue;
00119
00120 const std::string objName = Properties::ExtractField(key, 3);
00121 if (objName == "")
00122 throw std::runtime_error("Syntax error in " + key);
00123
00124
00125 const std::vector<std::string> args = scnProp->GetStringVector(key, "");
00126 const std::string plyFileName = args.at(0);
00127 const double now = WallClockTime();
00128 if (now - lastPrint > 2.0) {
00129 LR_LOG(ctx, "PLY object count: " << objCount);
00130 lastPrint = now;
00131 }
00132 ++objCount;
00133
00134
00135
00136 const bool usePlyNormals = (scnProp->GetInt(key + ".useplynormals", 0) != 0);
00137
00138
00139 ExtMesh *meshObject;
00140 if (scnProp->IsDefined(key + ".transformation")) {
00141 const std::vector<float> vf = GetParameters(*scnProp, key + ".transformation", 16, "1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0");
00142 const Matrix4x4 mat(
00143 vf.at(0), vf.at(4), vf.at(8), vf.at(12),
00144 vf.at(1), vf.at(5), vf.at(9), vf.at(13),
00145 vf.at(2), vf.at(6), vf.at(10), vf.at(14),
00146 vf.at(3), vf.at(7), vf.at(11), vf.at(15));
00147 const Transform trans(mat);
00148
00149 meshObject = extMeshCache->GetExtMesh(plyFileName, usePlyNormals, trans);
00150 } else
00151 meshObject = extMeshCache->GetExtMesh(plyFileName, usePlyNormals);
00152
00153 objectIndices[objName] = objects.size();
00154 objects.push_back(meshObject);
00155
00156
00157 const std::string matName = Properties::ExtractField(key, 2);
00158 if (matName == "")
00159 throw std::runtime_error("Syntax error in material name: " + matName);
00160 if (materialIndices.count(matName) < 1)
00161 throw std::runtime_error("Unknown material: " + matName);
00162 Material *mat = materials[materialIndices[matName]];
00163
00164
00165 if (mat->IsLightSource()) {
00166 LR_LOG(ctx, "The " << objName << " object is a light sources with " << meshObject->GetTotalTriangleCount() << " triangles");
00167
00168 AreaLightMaterial *light = (AreaLightMaterial *)mat;
00169 objectMaterials.push_back(mat);
00170 for (unsigned int i = 0; i < meshObject->GetTotalTriangleCount(); ++i) {
00171 TriangleLight *tl = new TriangleLight(light, objects.size() - 1, i, objects);
00172 lights.push_back(tl);
00173 }
00174 } else {
00175 SurfaceMaterial *surfMat = (SurfaceMaterial *)mat;
00176 objectMaterials.push_back(surfMat);
00177 }
00178
00179
00180 if (args.size() > 1) {
00181
00182 if (!meshObject->HasUVs())
00183 throw std::runtime_error("PLY object " + plyFileName + " is missing UV coordinates for texture mapping");
00184
00185 TexMapInstance *tm = texMapCache->GetTexMapInstance(args.at(1));
00186 objectTexMaps.push_back(tm);
00187 objectBumpMaps.push_back(NULL);
00188 objectNormalMaps.push_back(NULL);
00189 } else {
00190
00191 const std::string texMap = scnProp->GetString(key + ".texmap", "");
00192 if (texMap != "") {
00193
00194 if (!meshObject->HasUVs())
00195 throw std::runtime_error("PLY object " + plyFileName + " is missing UV coordinates for texture mapping");
00196
00197 TexMapInstance *tm = texMapCache->GetTexMapInstance(texMap);
00198 objectTexMaps.push_back(tm);
00199 } else
00200 objectTexMaps.push_back(NULL);
00201
00202
00203 const std::string bumpMap = scnProp->GetString(key + ".bumpmap", "");
00204 if (bumpMap != "") {
00205
00206 if (!meshObject->HasUVs())
00207 throw std::runtime_error("PLY object " + plyFileName + " is missing UV coordinates for bump mapping");
00208
00209 const float scale = scnProp->GetFloat(key + ".bumpmap.scale", 1.f);
00210
00211 BumpMapInstance *bm = texMapCache->GetBumpMapInstance(bumpMap, scale);
00212 objectBumpMaps.push_back(bm);
00213 } else
00214 objectBumpMaps.push_back(NULL);
00215
00216
00217 const std::string normalMap = scnProp->GetString(key + ".normalmap", "");
00218 if (normalMap != "") {
00219
00220 if (!meshObject->HasUVs())
00221 throw std::runtime_error("PLY object " + plyFileName + " is missing UV coordinates for normal mapping");
00222
00223 NormalMapInstance *nm = texMapCache->GetNormalMapInstance(normalMap);
00224 objectNormalMaps.push_back(nm);
00225 } else
00226 objectNormalMaps.push_back(NULL);
00227 }
00228 }
00229 LR_LOG(ctx, "PLY object count: " << objCount);
00230
00231
00232
00233
00234
00235 const std::vector<std::string> ilParams = scnProp->GetStringVector("scene.infinitelight.file", "");
00236 if (ilParams.size() > 0) {
00237 TexMapInstance *tex = texMapCache->GetTexMapInstance(ilParams.at(0));
00238
00239
00240 if (scnProp->GetInt("scene.infinitelight.usebruteforce", 0)) {
00241 LR_LOG(ctx, "Using brute force infinite light sampling");
00242 infiniteLight = new InfiniteLightBF(tex);
00243 useInfiniteLightBruteForce = true;
00244 } else {
00245 if (ilParams.size() == 2)
00246 infiniteLight = new InfiniteLightPortal(ctx, tex, ilParams.at(1));
00247 else
00248 infiniteLight = new InfiniteLightIS(tex);
00249
00250
00251 lights.push_back(infiniteLight);
00252
00253 useInfiniteLightBruteForce = false;
00254 }
00255
00256 std::vector<float> vf = GetParameters(*scnProp, "scene.infinitelight.gain", 3, "1.0 1.0 1.0");
00257 infiniteLight->SetGain(Spectrum(vf.at(0), vf.at(1), vf.at(2)));
00258
00259 vf = GetParameters(*scnProp, "scene.infinitelight.shift", 2, "0.0 0.0");
00260 infiniteLight->SetShift(vf.at(0), vf.at(1));
00261
00262 infiniteLight->Preprocess();
00263 } else {
00264 infiniteLight = NULL;
00265 useInfiniteLightBruteForce = false;
00266 }
00267
00268
00269
00270
00271
00272 const std::vector<std::string> silParams = scnProp->GetStringVector("scene.skylight.dir", "");
00273 if (silParams.size() > 0) {
00274 if (infiniteLight)
00275 throw std::runtime_error("Can not define a skylight when there is already an infinitelight defined");
00276
00277 std::vector<float> sdir = GetParameters(*scnProp, "scene.skylight.dir", 3, "0.0 0.0 1.0");
00278 const float turb = scnProp->GetFloat("scene.skylight.turbidity", 2.2f);
00279 std::vector<float> gain = GetParameters(*scnProp, "scene.skylight.gain", 3, "1.0 1.0 1.0");
00280
00281 SkyLight *sl = new SkyLight(turb, Vector(sdir.at(0), sdir.at(1), sdir.at(2)));
00282 infiniteLight = sl;
00283 sl->SetGain(Spectrum(gain.at(0), gain.at(1), gain.at(2)));
00284 sl->Init();
00285
00286 useInfiniteLightBruteForce = true;
00287 }
00288
00289
00290
00291
00292
00293 const std::vector<std::string> sulParams = scnProp->GetStringVector("scene.sunlight.dir", "");
00294 if (sulParams.size() > 0) {
00295 std::vector<float> sdir = GetParameters(*scnProp, "scene.sunlight.dir", 3, "0.0 0.0 1.0");
00296 const float turb = scnProp->GetFloat("scene.sunlight.turbidity", 2.2f);
00297 const float relSize = scnProp->GetFloat("scene.sunlight.relsize", 1.0f);
00298 std::vector<float> gain = GetParameters(*scnProp, "scene.sunlight.gain", 3, "1.0 1.0 1.0");
00299
00300 SunLight *sunLight = new SunLight(turb, relSize, Vector(sdir.at(0), sdir.at(1), sdir.at(2)));
00301 sunLight->SetGain(Spectrum(gain.at(0), gain.at(1), gain.at(2)));
00302 sunLight->Init();
00303
00304 lights.push_back(sunLight);
00305 }
00306
00307
00308
00309
00310
00311 dataSet = new DataSet(ctx);
00312
00313
00314 switch (accelType) {
00315 case -1:
00316
00317 break;
00318 case 0:
00319 dataSet->SetAcceleratorType(ACCEL_BVH);
00320 break;
00321 case 1:
00322 case 2:
00323 dataSet->SetAcceleratorType(ACCEL_QBVH);
00324 break;
00325 case 3:
00326 dataSet->SetAcceleratorType(ACCEL_MQBVH);
00327 break;
00328 default:
00329 throw std::runtime_error("Unknown accelerator.type");
00330 break;
00331 }
00332
00333
00334 for (std::vector<ExtMesh *>::const_iterator obj = objects.begin(); obj != objects.end(); ++obj)
00335 dataSet->Add(*obj);
00336
00337 dataSet->Preprocess();
00338 }
00339
00340 Scene::~Scene() {
00341 delete camera;
00342
00343 for (std::vector<LightSource *>::const_iterator l = lights.begin(); l != lights.end(); ++l)
00344 delete *l;
00345 if (useInfiniteLightBruteForce)
00346 delete infiniteLight;
00347
00348 delete dataSet;
00349
00350 delete extMeshCache;
00351 delete texMapCache;
00352 delete scnProp;
00353 }
00354
00355 std::vector<float> Scene::GetParameters(const Properties &prop, const std::string ¶mName,
00356 const unsigned int paramCount, const std::string &defaultValue) {
00357 const std::vector<float> vf = prop.GetFloatVector(paramName, defaultValue);
00358 if (vf.size() != paramCount) {
00359 std::stringstream ss;
00360 ss << "Syntax error in " << paramName << " (required " << paramCount << " parameters)";
00361 throw std::runtime_error(ss.str());
00362 }
00363
00364 return vf;
00365 }
00366
00367 Material *Scene::CreateMaterial(const std::string &propName, const Properties &prop) {
00368 const std::string matType = Properties::ExtractField(propName, 2);
00369 if (matType == "")
00370 throw std::runtime_error("Syntax error in " + propName);
00371 const std::string matName = Properties::ExtractField(propName, 3);
00372 if (matName == "")
00373 throw std::runtime_error("Syntax error in " + propName);
00374
00375 if (matType == "matte") {
00376 const std::vector<float> vf = GetParameters(prop, propName, 3, "1.0 1.0 1.0");
00377 const Spectrum col(vf.at(0), vf.at(1), vf.at(2));
00378
00379 return new MatteMaterial(col);
00380 } else if (matType == "light") {
00381 const std::vector<float> vf = GetParameters(prop, propName, 3, "1.0 1.0 1.0");
00382 const Spectrum gain(vf.at(0), vf.at(1), vf.at(2));
00383
00384 return new AreaLightMaterial(gain);
00385 } else if (matType == "mirror") {
00386 const std::vector<float> vf = GetParameters(prop, propName, 4, "1.0 1.0 1.0 1.0");
00387 const Spectrum col(vf.at(0), vf.at(1), vf.at(2));
00388
00389 return new MirrorMaterial(col, vf.at(3) != 0.f);
00390 } else if (matType == "mattemirror") {
00391 const std::vector<float> vf = GetParameters(prop, propName, 7, "1.0 1.0 1.0 1.0 1.0 1.0 1.0");
00392 const Spectrum Kd(vf.at(0), vf.at(1), vf.at(2));
00393 const Spectrum Kr(vf.at(3), vf.at(4), vf.at(5));
00394
00395 return new MatteMirrorMaterial(Kd, Kr, vf.at(6) != 0.f);
00396 } else if (matType == "glass") {
00397 const std::vector<float> vf = GetParameters(prop, propName, 10, "1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.5 1.0 1.0");
00398 const Spectrum Krfl(vf.at(0), vf.at(1), vf.at(2));
00399 const Spectrum Ktrn(vf.at(3), vf.at(4), vf.at(5));
00400
00401 return new GlassMaterial(Krfl, Ktrn, vf.at(6), vf.at(7), vf.at(8) != 0.f, vf.at(9) != 0.f);
00402 } else if (matType == "metal") {
00403 const std::vector<float> vf = GetParameters(prop, propName, 5, "1.0 1.0 1.0 10.0 1.0");
00404 const Spectrum col(vf.at(0), vf.at(1), vf.at(2));
00405
00406 return new MetalMaterial(col, vf.at(3), vf.at(4) != 0.f);
00407 } else if (matType == "mattemetal") {
00408 const std::vector<float> vf = GetParameters(prop, propName, 8, "1.0 1.0 1.0 1.0 1.0 1.0 10.0 1.0");
00409 const Spectrum Kd(vf.at(0), vf.at(1), vf.at(2));
00410 const Spectrum Kr(vf.at(3), vf.at(4), vf.at(5));
00411
00412 return new MatteMetalMaterial(Kd, Kr, vf.at(6), vf.at(7) != 0.f);
00413 } else if (matType == "archglass") {
00414 const std::vector<float> vf = GetParameters(prop, propName, 8, "1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0");
00415 const Spectrum Krfl(vf.at(0), vf.at(1), vf.at(2));
00416 const Spectrum Ktrn(vf.at(3), vf.at(4), vf.at(5));
00417
00418 return new ArchGlassMaterial(Krfl, Ktrn, vf.at(6) != 0.f, vf.at(7) != 0.f);
00419 } else if (matType == "alloy") {
00420 const std::vector<float> vf = GetParameters(prop, propName, 9, "1.0 1.0 1.0 1.0 1.0 1.0 10.0 0.8 1.0");
00421 const Spectrum Kdiff(vf.at(0), vf.at(1), vf.at(2));
00422 const Spectrum Krfl(vf.at(3), vf.at(4), vf.at(5));
00423
00424 return new AlloyMaterial(Kdiff, Krfl, vf.at(6), vf.at(7), vf.at(8) != 0.f);
00425 } else
00426 throw std::runtime_error("Unknown material type " + matType);
00427 }