Scene::Scene(const std::string &fileName,uint width, uint height ,const int aType ) { accelType = aType; extMeshCache = new ExtMeshCache(); texMapCache = new TextureMapCache(); SDL_LOG("Reading scene: " << fileName); scnProp = new Properties(fileName); //-------------------------------------------------------------------------- // Read camera position and target //-------------------------------------------------------------------------- std::vector<float> vf = GetParameters(*scnProp, "scene.camera.lookat", 6, "10.0 0.0 0.0 0.0 0.0 0.0"); Point o(vf.at(0), vf.at(1), vf.at(2)); Point t(vf.at(3), vf.at(4), vf.at(5)); SDL_LOG("Camera postion: " << o); SDL_LOG("Camera target: " << t); vf = GetParameters(*scnProp, "scene.camera.up", 3, "0.0 0.0 0.1"); const Vector up(vf.at(0), vf.at(1), vf.at(2)); camera = new PerspectiveCamera(o, t, up); camera->lensRadius = scnProp->GetFloat("scene.camera.lensradius", 0.f); camera->focalDistance = scnProp->GetFloat("scene.camera.focaldistance", 10.f); camera->fieldOfView = scnProp->GetFloat("scene.camera.fieldofview", 45.f); // Check if camera motion blur is enabled if (scnProp->GetInt("scene.camera.motionblur.enable", 0)) { camera->motionBlur = true; vf = GetParameters(*scnProp, "scene.camera.motionblur.lookat", 6, "10.0 1.0 0.0 0.0 1.0 0.0"); camera->mbOrig = Point(vf.at(0), vf.at(1), vf.at(2)); camera->mbTarget = Point(vf.at(3), vf.at(4), vf.at(5)); vf = GetParameters(*scnProp, "scene.camera.motionblur.up", 3, "0.0 0.0 0.1"); camera->mbUp = Vector(vf.at(0), vf.at(1), vf.at(2)); } //-------------------------------------------------------------------------- // Read all materials //-------------------------------------------------------------------------- std::vector<std::string> matKeys = scnProp->GetAllKeys("scene.materials."); if (matKeys.size() == 0) throw std::runtime_error("No material definition found"); for (std::vector<std::string>::const_iterator matKey = matKeys.begin(); matKey != matKeys.end(); ++matKey) { const std::string &key = *matKey; const std::string matType = Properties::ExtractField(key, 2); if (matType == "") throw std::runtime_error("Syntax error in " + key); const std::string matName = Properties::ExtractField(key, 3); if (matName == "") throw std::runtime_error("Syntax error in " + key); SDL_LOG("Material definition: " << matName << " [" << matType << "]"); Material *mat = CreateMaterial(key, *scnProp); materialIndices[matName] = materials.size(); materials.push_back(mat); } //-------------------------------------------------------------------------- // Read all objects .ply file //-------------------------------------------------------------------------- std::vector<std::string> objKeys = scnProp->GetAllKeys("scene.objects."); if (objKeys.size() == 0) throw std::runtime_error("Unable to find object definitions"); double lastPrint = WallClockTime(); unsigned int objCount = 0; for (std::vector<std::string>::const_iterator objKey = objKeys.begin(); objKey != objKeys.end(); ++objKey) { const std::string &key = *objKey; // Check if it is the root of the definition of an object otherwise skip const size_t dot1 = key.find(".", std::string("scene.objects.").length()); if (dot1 == std::string::npos) continue; const size_t dot2 = key.find(".", dot1 + 1); if (dot2 != std::string::npos) continue; const std::string objName = Properties::ExtractField(key, 3); if (objName == "") throw std::runtime_error("Syntax error in " + key); // Build the object const std::vector<std::string> args = scnProp->GetStringVector(key, ""); const std::string plyFileName = args.at(0); const double now = WallClockTime(); if (now - lastPrint > 2.0) { SDL_LOG("PLY object count: " << objCount); lastPrint = now; } ++objCount; //SDL_LOG("PLY object [" << objName << "] file name: " << plyFileName); // Check if I have to calculate normal or not const bool usePlyNormals = (scnProp->GetInt(key + ".useplynormals", 0) != 0); // Check if I have to use an instance mesh or not ExtMesh *meshObject; if (scnProp->IsDefined(key + ".transformation")) { 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"); const Matrix4x4 mat( vf.at(0), vf.at(4), vf.at(8), vf.at(12), vf.at(1), vf.at(5), vf.at(9), vf.at(13), vf.at(2), vf.at(6), vf.at(10), vf.at(14), vf.at(3), vf.at(7), vf.at(11), vf.at(15)); const Transform trans(mat); meshObject = extMeshCache->GetExtMesh(plyFileName, usePlyNormals, trans); } else meshObject = extMeshCache->GetExtMesh(plyFileName, usePlyNormals); objectIndices[objName] = objects.size(); objects.push_back(meshObject); // Get the material const std::string matName = Properties::ExtractField(key, 2); if (matName == "") throw std::runtime_error("Syntax error in material name: " + matName); if (materialIndices.count(matName) < 1) throw std::runtime_error("Unknown material: " + matName); Material *mat = materials[materialIndices[matName]]; // Check if it is a light sources if (mat->IsLightSource()) { SDL_LOG("The " << objName << " object is a light sources with " << meshObject->GetTotalTriangleCount() << " triangles"); AreaLightMaterial *light = (AreaLightMaterial *)mat; objectMaterials.push_back(mat); for (unsigned int i = 0; i < meshObject->GetTotalTriangleCount(); ++i) { TriangleLight *tl = new TriangleLight(light, static_cast<unsigned int>(objects.size()) - 1, i, objects); lights.push_back(tl); } } else { SurfaceMaterial *surfMat = (SurfaceMaterial *)mat; objectMaterials.push_back(surfMat); } // [old deprecated syntax] Check if there is a texture map associated to the object if (args.size() > 1) { // Check if the object has UV coords if (!meshObject->HasUVs()) throw std::runtime_error("PLY object " + plyFileName + " is missing UV coordinates for texture mapping"); TexMapInstance *tm = texMapCache->GetTexMapInstance(args.at(1), 2.2f); objectTexMaps.push_back(tm); objectBumpMaps.push_back(NULL); objectNormalMaps.push_back(NULL); } else { // Check for if there is a texture map associated to the object with the new syntax const std::string texMap = scnProp->GetString(key + ".texmap", ""); if (texMap != "") { // Check if the object has UV coords if (!meshObject->HasUVs()) throw std::runtime_error("PLY object " + plyFileName + " is missing UV coordinates for texture mapping"); const float gamma = scnProp->GetFloat(key + ".texmap.gamma", 2.2f); TexMapInstance *tm = texMapCache->GetTexMapInstance(texMap, gamma); objectTexMaps.push_back(tm); } else objectTexMaps.push_back(NULL); /** * Check if there is an alpha map associated to the object * If there is, the map is added to a previously added texturemap. * If no texture map (diffuse map) is detected, a black texture * is created and the alpha map is added to it. --PC */ const std::string alphaMap = scnProp->GetString(key + ".alphamap", ""); if (alphaMap != "") { // Got an alpha map, retrieve the textureMap and add the alpha channel to it. const std::string texMap = scnProp->GetString(key + ".texmap", ""); const float gamma = scnProp->GetFloat(key + ".texmap.gamma", 2.2f); TextureMap *tm; if (!(tm = texMapCache->FindTextureMap(texMap, gamma))) { SDL_LOG("Alpha map " << alphaMap << " is for a materials without texture. A black texture has been created for support!"); // We have an alpha map without a diffuse texture. In this case we need to create // a texture map filled with black tm = new TextureMap(alphaMap, gamma, 1.0, 1.0, 1.0); tm->AddAlpha(alphaMap); TexMapInstance *tmi = texMapCache->AddTextureMap(alphaMap, tm); // Remove the NULL inserted above, when no texmap was found. Without doing this the whole thing will not work objectTexMaps.pop_back(); // Add the new texture to the chain objectTexMaps.push_back(tmi); } else { // Add an alpha map to the pre-existing diffuse texture tm->AddAlpha(alphaMap); } } // Check for if there is a bump map associated to the object const std::string bumpMap = scnProp->GetString(key + ".bumpmap", ""); if (bumpMap != "") { // Check if the object has UV coords if (!meshObject->HasUVs()) throw std::runtime_error("PLY object " + plyFileName + " is missing UV coordinates for bump mapping"); const float scale = scnProp->GetFloat(key + ".bumpmap.scale", 1.f); BumpMapInstance *bm = texMapCache->GetBumpMapInstance(bumpMap, scale); objectBumpMaps.push_back(bm); } else objectBumpMaps.push_back(NULL); // Check for if there is a normal map associated to the object const std::string normalMap = scnProp->GetString(key + ".normalmap", ""); if (normalMap != "") { // Check if the object has UV coords if (!meshObject->HasUVs()) throw std::runtime_error("PLY object " + plyFileName + " is missing UV coordinates for normal mapping"); NormalMapInstance *nm = texMapCache->GetNormalMapInstance(normalMap); objectNormalMaps.push_back(nm); } else objectNormalMaps.push_back(NULL); } } SDL_LOG("PLY object count: " << objCount); //-------------------------------------------------------------------------- // Check if there is an infinitelight source defined //-------------------------------------------------------------------------- const std::vector<std::string> ilParams = scnProp->GetStringVector("scene.infinitelight.file", ""); if (ilParams.size() > 0) { const float gamma = scnProp->GetFloat("scene.infinitelight.gamma", 2.2f); TexMapInstance *tex = texMapCache->GetTexMapInstance(ilParams.at(0), gamma); // Check if I have to use InfiniteLightBF method if (scnProp->GetInt("scene.infinitelight.usebruteforce", 0)) { SDL_LOG("Using brute force infinite light sampling"); infiniteLight = new InfiniteLightBF(tex); useInfiniteLightBruteForce = true; } else { if (ilParams.size() == 2) infiniteLight = new InfiniteLightPortal(tex, ilParams.at(1)); else infiniteLight = new InfiniteLightIS(tex); // Add the infinite light to the list of light sources lights.push_back(infiniteLight); useInfiniteLightBruteForce = false; } std::vector<float> vf = GetParameters(*scnProp, "scene.infinitelight.gain", 3, "1.0 1.0 1.0"); infiniteLight->SetGain(Spectrum(vf.at(0), vf.at(1), vf.at(2))); vf = GetParameters(*scnProp, "scene.infinitelight.shift", 2, "0.0 0.0"); infiniteLight->SetShift(vf.at(0), vf.at(1)); infiniteLight->Preprocess(); } else { infiniteLight = NULL; useInfiniteLightBruteForce = false; } //-------------------------------------------------------------------------- // Check if there is a SkyLight defined //-------------------------------------------------------------------------- const std::vector<std::string> silParams = scnProp->GetStringVector("scene.skylight.dir", ""); if (silParams.size() > 0) { if (infiniteLight) throw std::runtime_error("Can not define a skylight when there is already an infinitelight defined"); std::vector<float> sdir = GetParameters(*scnProp, "scene.skylight.dir", 3, "0.0 0.0 1.0"); const float turb = scnProp->GetFloat("scene.skylight.turbidity", 2.2f); std::vector<float> gain = GetParameters(*scnProp, "scene.skylight.gain", 3, "1.0 1.0 1.0"); SkyLight *sl = new SkyLight(turb, Vector(sdir.at(0), sdir.at(1), sdir.at(2))); infiniteLight = sl; sl->SetGain(Spectrum(gain.at(0), gain.at(1), gain.at(2))); sl->Init(); useInfiniteLightBruteForce = true; } //-------------------------------------------------------------------------- // Check if there is a SunLight defined //-------------------------------------------------------------------------- const std::vector<std::string> sulParams = scnProp->GetStringVector("scene.sunlight.dir", ""); if (sulParams.size() > 0) { std::vector<float> sdir = GetParameters(*scnProp, "scene.sunlight.dir", 3, "0.0 0.0 1.0"); const float turb = scnProp->GetFloat("scene.sunlight.turbidity", 2.2f); const float relSize = scnProp->GetFloat("scene.sunlight.relsize", 1.0f); std::vector<float> gain = GetParameters(*scnProp, "scene.sunlight.gain", 3, "1.0 1.0 1.0"); SunLight *sunLight = new SunLight(turb, relSize, Vector(sdir.at(0), sdir.at(1), sdir.at(2))); sunLight->SetGain(Spectrum(gain.at(0), gain.at(1), gain.at(2))); sunLight->Init(); lights.push_back(sunLight); } //-------------------------------------------------------------------------- camera->Update(width, height); }
void Scene::ParseShapes(const Properties &props) { vector<string> shapeKeys = props.GetAllUniqueSubNames("scene.shapes"); if (shapeKeys.size() == 0) { // There are not shape definitions return; } double lastPrint = WallClockTime(); u_int shapeCount = 0; BOOST_FOREACH(const string &key, shapeKeys) { // Extract the shape name const string shapeName = Property::ExtractField(key, 2); if (shapeName == "") throw runtime_error("Syntax error in shape definition: " + shapeName); ExtMesh *mesh = CreateShape(shapeName, props); if (extMeshCache.IsExtMeshDefined(shapeName)) { // A replacement for an existing mesh const ExtMesh *oldMesh = extMeshCache.GetExtMesh(shapeName); // Replace old mesh direct references with new one and get the list // of scene objects referencing the old mesh boost::unordered_set<SceneObject *> modifiedObjsList; objDefs.UpdateMeshReferences(oldMesh, mesh, modifiedObjsList); // For each scene object BOOST_FOREACH(SceneObject *o, modifiedObjsList) { // Check if is a light source if (o->GetMaterial()->IsLightSource()) { const string objName = o->GetName(); // Delete all old triangle lights lightDefs.DeleteLightSourceStartWith(objName + TRIANGLE_LIGHT_POSTFIX); // Add all new triangle lights SDL_LOG("The " << objName << " object is a light sources with " << mesh->GetTotalTriangleCount() << " triangles"); for (u_int i = 0; i < mesh->GetTotalTriangleCount(); ++i) { TriangleLight *tl = new TriangleLight(); tl->lightMaterial = o->GetMaterial(); tl->mesh = mesh; tl->triangleIndex = i; tl->Preprocess(); lightDefs.DefineLightSource(objName + TRIANGLE_LIGHT_POSTFIX + ToString(i), tl); } editActions.AddActions(LIGHTS_EDIT | LIGHT_TYPES_EDIT); } } } extMeshCache.DefineExtMesh(shapeName, mesh); ++shapeCount; const double now = WallClockTime(); if (now - lastPrint > 2.0) { SDL_LOG("Shape count: " << shapeCount); lastPrint = now; } } SDL_LOG("Shape count: " << shapeCount); editActions.AddActions(GEOMETRY_EDIT); }