Exemple #1
0
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);
}