LightManager::LightManager() : m_sunTimer(Framework::Timer::TT_LOOP, 30.0f) , m_ambientInterpolator() { m_lightTimers.reserve(NUMBER_OF_POINT_LIGHTS); m_lightPos.reserve(NUMBER_OF_POINT_LIGHTS); m_lightPos.push_back(LightInterpolator()); m_lightPos.push_back(LightInterpolator()); m_lightPos.push_back(LightInterpolator()); m_lightIntensity.resize(NUMBER_OF_POINT_LIGHTS, glm::vec4(0.2f, 0.2f, 0.2f, 1.0f)); std::vector<glm::vec3> posValues; posValues.reserve(60); posValues.push_back(glm::vec3(-50.0f, 30.0f, 70.0f)); posValues.push_back(glm::vec3(-70.0f, 30.0f, 50.0f)); posValues.push_back(glm::vec3(-70.0f, 30.0f, -50.0f)); posValues.push_back(glm::vec3(-50.0f, 30.0f, -70.0f)); posValues.push_back(glm::vec3(50.0f, 30.0f, -70.0f)); posValues.push_back(glm::vec3(70.0f, 30.0f, -50.0f)); posValues.push_back(glm::vec3(70.0f, 30.0f, 50.0f)); posValues.push_back(glm::vec3(50.0f, 30.0f, 70.0f)); m_lightPos[0].SetValues(posValues); m_lightTimers.push_back(Framework::Timer(Framework::Timer::TT_LOOP, 15.0f)); //Right-side light. posValues.clear(); posValues.push_back(glm::vec3(100.0f, 6.0f, 75.0f)); posValues.push_back(glm::vec3(90.0f, 8.0f, 90.0f)); posValues.push_back(glm::vec3(75.0f, 10.0f, 100.0f)); posValues.push_back(glm::vec3(60.0f, 12.0f, 90.0f)); posValues.push_back(glm::vec3(50.0f, 14.0f, 75.0f)); posValues.push_back(glm::vec3(60.0f, 16.0f, 60.0f)); posValues.push_back(glm::vec3(75.0f, 18.0f, 50.0f)); posValues.push_back(glm::vec3(90.0f, 20.0f, 60.0f)); posValues.push_back(glm::vec3(100.0f, 22.0f, 75.0f)); posValues.push_back(glm::vec3(90.0f, 24.0f, 90.0f)); posValues.push_back(glm::vec3(75.0f, 26.0f, 100.0f)); posValues.push_back(glm::vec3(60.0f, 28.0f, 90.0f)); posValues.push_back(glm::vec3(50.0f, 30.0f, 75.0f)); posValues.push_back(glm::vec3(105.0f, 9.0f, -70.0f)); posValues.push_back(glm::vec3(105.0f, 10.0f, -90.0f)); posValues.push_back(glm::vec3(72.0f, 20.0f, -90.0f)); posValues.push_back(glm::vec3(72.0f, 22.0f, -70.0f)); posValues.push_back(glm::vec3(105.0f, 32.0f, -70.0f)); posValues.push_back(glm::vec3(105.0f, 34.0f, -90.0f)); posValues.push_back(glm::vec3(72.0f, 44.0f, -90.0f)); m_lightPos[1].SetValues(posValues); m_lightTimers.push_back(Framework::Timer(Framework::Timer::TT_LOOP, 25.0f)); //Left-side light. posValues.clear(); posValues.push_back(glm::vec3(-7.0f, 35.0f, 1.0f)); posValues.push_back(glm::vec3(8.0f, 40.0f, -14.0f)); posValues.push_back(glm::vec3(-7.0f, 45.0f, -29.0f)); posValues.push_back(glm::vec3(-22.0f, 50.0f, -14.0f)); posValues.push_back(glm::vec3(-7.0f, 55.0f, 1.0f)); posValues.push_back(glm::vec3(8.0f, 60.0f, -14.0f)); posValues.push_back(glm::vec3(-7.0f, 65.0f, -29.0f)); posValues.push_back(glm::vec3(-83.0f, 30.0f, -92.0f)); posValues.push_back(glm::vec3(-98.0f, 27.0f, -77.0f)); posValues.push_back(glm::vec3(-83.0f, 24.0f, -62.0f)); posValues.push_back(glm::vec3(-68.0f, 21.0f, -77.0f)); posValues.push_back(glm::vec3(-83.0f, 18.0f, -92.0f)); posValues.push_back(glm::vec3(-98.0f, 15.0f, -77.0f)); posValues.push_back(glm::vec3(-50.0f, 8.0f, 25.0f)); posValues.push_back(glm::vec3(-59.5f, 4.0f, 65.0f)); posValues.push_back(glm::vec3(-59.5f, 4.0f, 78.0f)); posValues.push_back(glm::vec3(-45.0f, 4.0f, 82.0f)); posValues.push_back(glm::vec3(-40.0f, 4.0f, 50.0f)); posValues.push_back(glm::vec3(-70.0f, 20.0f, 40.0f)); posValues.push_back(glm::vec3(-60.0f, 20.0f, 90.0f)); posValues.push_back(glm::vec3(-40.0f, 25.0f, 90.0f)); m_lightPos[2].SetValues(posValues); m_lightTimers.push_back(Framework::Timer(Framework::Timer::TT_LOOP, 15.0f)); }
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); } }