Exemplo n.º 1
0
LightEnv::LightEnv( const std::string& envFilename )
	: m_fLightAttenuation(40.0f)
{
	std::ifstream fileStream(envFilename.c_str());
	if(!fileStream.is_open())
		throw std::runtime_error("Could not find the mesh file.");

	TiXmlDocument theDoc;

	fileStream >> theDoc;
	fileStream.close();

	if(theDoc.Error())
		throw std::runtime_error(theDoc.ErrorDesc());

	TiXmlHandle docHandle(&theDoc);

	const TiXmlElement *pRootNode = docHandle.FirstChild("lightenv").ToElement();

	if(!pRootNode)
		throw std::runtime_error("The root node must be a 'lightenv' element.");

	pRootNode->QueryFloatAttribute("atten", &m_fLightAttenuation);
	m_fLightAttenuation = 1.0f / (m_fLightAttenuation * m_fLightAttenuation);

	const TiXmlElement *pSunNode = docHandle.FirstChild("lightenv").FirstChild("sun").ToElement();

	if(!pSunNode)
		throw std::runtime_error("There must be a 'lightenv' element that has a 'sun' element as a child.");

	float timerTime = 0;
	if(pSunNode->QueryFloatAttribute("time", &timerTime) != TIXML_SUCCESS)
		throw std::runtime_error("'sun' elements must have a 'time' attribute that is a float.");

	m_sunTimer = Framework::Timer(Framework::Timer::TT_LOOP, timerTime);

	LightVector ambient;
	LightVector light;
	LightVector background;
	MaxIntensityVector maxIntensity;

	for(const TiXmlElement *pKeyElem = pSunNode->FirstChildElement("key");
		pKeyElem;
		pKeyElem = pKeyElem->NextSiblingElement("key"))
	{
		float keyTime = 0;
		if(pKeyElem->QueryFloatAttribute("time", &keyTime) != TIXML_SUCCESS)
			throw std::runtime_error("'key' elements must have a 'time' attribute that is a float.");
		//Convert from hours to normalized time.
		keyTime = keyTime / 24.0f;

		std::string strVec4;
		if(pKeyElem->QueryStringAttribute("ambient", &strVec4) != TIXML_SUCCESS)
			throw std::runtime_error("'key' elements must have an 'ambient' attribute.");
		ambient.push_back(LightData(ParseVec4(strVec4), keyTime));

		if(pKeyElem->QueryStringAttribute("intensity", &strVec4) != TIXML_SUCCESS)
			throw std::runtime_error("'key' elements must have a 'intensity' attribute.");
		light.push_back(LightData(ParseVec4(strVec4), keyTime));

		if(pKeyElem->QueryStringAttribute("background", &strVec4) != TIXML_SUCCESS)
			throw std::runtime_error("'key' elements must have a 'background' attribute.");
		background.push_back(LightData(ParseVec4(strVec4), keyTime));

		maxIntensity.push_back(MaxIntensityData(0.0f, keyTime));
		if(pKeyElem->QueryFloatAttribute("max-intensity", &maxIntensity.back().first) != TIXML_SUCCESS)
			throw std::runtime_error("'key' elements must have a 'max-intensity' attribute that is a float.");
	}

	if(ambient.empty())
		throw std::runtime_error("'sun' element must have at least one 'key' element child.");

	m_ambientInterpolator.SetValues(ambient);
	m_sunlightInterpolator.SetValues(light);
	m_backgroundInterpolator.SetValues(background);
	m_maxIntensityInterpolator.SetValues(maxIntensity);

	const TiXmlElement *pLightNode = docHandle.FirstChild("lightenv").FirstChild("light").ToElement();
	for(; pLightNode; pLightNode = pLightNode->NextSiblingElement("light"))
	{
		if(m_lightPos.size() + 1 == MAX_NUMBER_OF_LIGHTS)
			throw std::runtime_error("Too many lights specified.");

		float lightTime = 0;
		if(pLightNode->QueryFloatAttribute("time", &lightTime) != TIXML_SUCCESS)
			throw std::runtime_error("'light' elements must have a 'time' attribute that is a float.");

		m_lightTimers.push_back(Framework::Timer(Framework::Timer::TT_LOOP, lightTime));

		std::string strVec4;
		if(pLightNode->QueryStringAttribute("intensity", &strVec4) != TIXML_SUCCESS)
			throw std::runtime_error("'light' elements must have an 'intensity' attribute.");
		m_lightIntensity.push_back(ParseVec4(strVec4));

		std::vector<glm::vec3> posValues;
		for(const TiXmlElement *pKeyElem = pLightNode->FirstChildElement("key");
			pKeyElem;
			pKeyElem = pKeyElem->NextSiblingElement("key"))
		{
			posValues.push_back(ParseVec3(pKeyElem->GetText()));
		}

		if(posValues.empty())
			throw std::runtime_error("'light' elements must have at least one 'key' element child.");

		m_lightPos.push_back(LightInterpolator());
		m_lightPos.back().SetValues(posValues);
	}
}
Exemplo n.º 2
0
LightEnv::LightEnv( const std::string& envFilename )
	: m_fLightAttenuation(40.0f)
{
	std::ifstream fileStream(envFilename.c_str());
	if(!fileStream.is_open())
		throw std::runtime_error("Could not find the mesh file.");

	std::vector<char> fileData;
	fileData.reserve(2000);
	fileData.insert(fileData.end(), std::istreambuf_iterator<char>(fileStream),
		std::istreambuf_iterator<char>());
	fileData.push_back('\0');

	xml_document<> doc;

	try
	{
		doc.parse<0>(&fileData[0]);
	}
	catch(rapidxml::parse_error &e)
	{
		std::cout << envFilename << ": Parse error in light environment file." << std::endl;
		std::cout << e.what() << std::endl << e.where<char>() << std::endl;
		throw;
	}

	xml_node<> *pRootNode = doc.first_node("lightenv");
	PARSE_THROW(pRootNode, ("lightenv node not found in light environment file: " + envFilename));

	m_fLightAttenuation = rapidxml::get_attrib_float(*pRootNode, "atten", m_fLightAttenuation);
	m_fLightAttenuation = 1.0f / (m_fLightAttenuation * m_fLightAttenuation);

	xml_node<> *pSunNode = pRootNode->first_node("sun");
	PARSE_THROW(pSunNode, "lightenv node must have a first child that is called `sun`.");

	m_sunTimer = Framework::Timer(Framework::Timer::TT_LOOP,
		rapidxml::get_attrib_float(*pSunNode, "time", ThrowAttrib));

	LightVector ambient;
	LightVector light;
	LightVector background;
	MaxIntensityVector maxIntensity;

	for(const xml_node<> *pKeyNode = pSunNode->first_node("key");
		pKeyNode;
		pKeyNode = pKeyNode->next_sibling("key"))
	{
		float keyTime = rapidxml::get_attrib_float(*pKeyNode, "time", ThrowAttrib);
		//Convert from hours to normalized time.
		keyTime = keyTime / 24.0f;

		ambient.push_back(LightData(
			rapidxml::get_attrib_vec4(*pKeyNode, "ambient", ThrowAttrib), keyTime));

		light.push_back(LightData(
			rapidxml::get_attrib_vec4(*pKeyNode, "intensity", ThrowAttrib), keyTime));

		background.push_back(LightData(
			rapidxml::get_attrib_vec4(*pKeyNode, "background", ThrowAttrib), keyTime));

		maxIntensity.push_back(MaxIntensityData(
			rapidxml::get_attrib_float(*pKeyNode, "max-intensity", ThrowAttrib), keyTime));
	}

	if(ambient.empty())
		throw std::runtime_error("'sun' element must have at least one 'key' element child.");

	m_ambientInterpolator.SetValues(ambient);
	m_sunlightInterpolator.SetValues(light);
	m_backgroundInterpolator.SetValues(background);
	m_maxIntensityInterpolator.SetValues(maxIntensity);

	for(xml_node<> *pLightNode = pRootNode->first_node("light");
		pLightNode;
		pLightNode = pLightNode->next_sibling("light"))
	{
		if(m_lightPos.size() + 1 == MAX_NUMBER_OF_LIGHTS)
			throw std::runtime_error("Too many lights specified.");

		m_lightTimers.push_back(Framework::Timer(
			Framework::Timer::TT_LOOP,
			rapidxml::get_attrib_float(*pLightNode, "time", ThrowAttrib)));

		m_lightIntensity.push_back(rapidxml::get_attrib_vec4(
			*pLightNode, "intensity", ThrowAttrib));

		std::vector<glm::vec3> posValues;
		for(xml_node<> *pKeyNode = pLightNode->first_node("key");
			pKeyNode;
			pKeyNode = pKeyNode->next_sibling("key"))
		{
			posValues.push_back(ParseVec3(make_string(*pKeyNode)));
		}

		if(posValues.empty())
			throw std::runtime_error("'light' elements must have at least one 'key' element child.");

		m_lightPos.push_back(LightInterpolator());
		m_lightPos.back().SetValues(posValues);
	}
}