void ParseLine( const char* line ) { m_line = line; SkipSpace(); switch(*(m_line++)) { case 'f': if (isspace(*(m_line++))) { ParseFace(); } break; case 'v': { char ch = *(m_line++); switch (ch) { case 'n': { ParseVec3(m_normals); return; } case 't': { ParseVec2(m_uvs); return; } default: if (isspace(ch)) { ParseVec3(m_positions); } return; } } } }
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); } }
ObjModel::ObjModel(const std::string& filePath) { // standardise dir seperators std::string filePathStd = std::string(filePath); std::replace(filePathStd.begin(), filePathStd.end(), '\\', '/'); // asd/asd/asd/asd/asd/asd/file.obj auto tokens = SplitString(filePathStd, '/'); std::string fileName = tokens[tokens.size() - 1]; std::string workingDir = filePathStd.substr(0, filePathStd.size() - fileName.size()); std::ifstream file; file.open((workingDir + "/" + fileName).c_str()); int curMaterialIndex = 0; std::string line; if (file.is_open()) { while (file.good()) { getline(file, line); unsigned int lineLength = line.length(); if (lineLength < 2) continue; const char* lineCStr = line.c_str(); switch (lineCStr[0]) { case 'v': // "v?" => vertex { switch (lineCStr[1]) { case 't': // ? == 't' => vertex texture / uv coords { #define TEMP_SSCANF // ~5.5 secs //#define TEMP_SPLIT // ~10 secs //#define TEMP_STREAM // ~7.5 secs #ifdef TEMP_SSCANF glm::vec2 vt; sscanf_s(lineCStr, "vt %f %f", &vt.x, &vt.y); textures.push_back(vt); #endif // SSCANF #ifdef TEMP_SPLIT textures.push_back(ParseVec2(line)); #endif // TEMP_SPLIT #ifdef TEMP_STREAM std::istringstream issvt(line.substr(2)); glm::vec2 vt; issvt >> vt.x; issvt >> vt.y; textures.push_back(vt); #endif // TEMP_STREAM break; } case 'n': // ? == 'n' => vertex normal { #ifdef TEMP_SSCANF glm::vec3 vn; sscanf_s(lineCStr, "vn %f %f %f", &vn.x, &vn.y, &vn.z); normals.push_back(vn); #endif // SSCANF #ifdef TEMP_SPLIT normals.push_back(ParseVec3(line)); #endif // TEMP_SPLIT #ifdef TEMP_STREAM std::istringstream issvt(line.substr(2)); glm::vec3 vn; issvt >> vn.x; issvt >> vn.y; issvt >> vn.z; normals.push_back(vn); #endif // TEMP_STREAM break; } case '\t': // ? == ' ' => vertex case ' ': { #ifdef TEMP_SSCANF glm::vec3 v; sscanf_s(lineCStr, "v %f %f %f", &v.x, &v.y, &v.z); positions.push_back(v); #endif // SSCANF #ifdef TEMP_SPLIT positions.push_back(ParseVec3(line)); #endif // TEMP_SPLIT #ifdef TEMP_STREAM std::istringstream issvt(line.substr(2)); glm::vec3 v; issvt >> v.x; issvt >> v.y; issvt >> v.z; positions.push_back(v); #endif // TEMP_STREAM break; } } break; } case 'f': // 'f' => face { CreateFace(curMaterialIndex, line); break; } case 'm': // 'm' => material template lib { if (lineCStr[1] != 't') break; char buffer[BUFSIZ]; sscanf_s(lineCStr, "mtllib %s", &buffer); std::string mtlFileName = std::string(buffer); //std::string mtlFileName = SplitString(line, ' ')[1]; std::vector<Material*> mats = LoadMaterials(workingDir, mtlFileName); materials.insert(std::end(materials), std::begin(mats), std::end(mats)); break; } case 'u': // 'u' => usemtl { if (lineCStr[1] != 's') break; std::string mtlName = SplitString(line, ' ')[1]; for (int i = 0; i < materials.size(); i++) { if (materials[i]->name == mtlName) { curMaterialIndex = i; break; } } break; } }; } } else {