.. _program_listing_file_Utilities_OBJLoader.h: Program Listing for File OBJLoader.h ==================================== |exhale_lsh| :ref:`Return to documentation for file ` (``Utilities/OBJLoader.h``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp #ifndef __OBJLoader_h__ #define __OBJLoader_h__ #include #include "Logger.h" #include "StringTools.h" #include namespace Utilities { struct MeshFaceIndices { std::array posIndices; std::array texIndices; std::array normalIndices; }; class OBJLoader { public: using Vec3f = std::array; using Vec2f = std::array; static void loadObj(const std::string &filename, std::vector *x, std::vector *faces, std::vector *normals, std::vector *texcoords, const Vec3f &scale) { LOG_INFO << "Loading " << filename; std::ifstream filestream; filestream.open(filename.c_str()); if (filestream.fail()) { LOG_ERR << "Failed to open file: " << filename; return; } std::string line_stream; bool vt = false; bool vn = false; std::vector pos_buffer; std::vector f_buffer; while (getline(filestream, line_stream)) { std::stringstream str_stream(line_stream); std::string type_str; str_stream >> type_str; if (type_str == "v") { Vec3f pos; pos_buffer.clear(); std::string parse_str = line_stream.substr(line_stream.find("v") + 1); StringTools::tokenize(parse_str, pos_buffer); for (unsigned int i = 0; i < 3; i++) pos[i] = stof(pos_buffer[i]) * scale[i]; x->push_back(pos); } else if (type_str == "vt") { if (texcoords != nullptr) { Vec2f tex; pos_buffer.clear(); std::string parse_str = line_stream.substr(line_stream.find("vt") + 2); StringTools::tokenize(parse_str, pos_buffer); for (unsigned int i = 0; i < 2; i++) tex[i] = stof(pos_buffer[i]); texcoords->push_back(tex); vt = true; } } else if (type_str == "vn") { if (normals != nullptr) { Vec3f nor; pos_buffer.clear(); std::string parse_str = line_stream.substr(line_stream.find("vn") + 2); StringTools::tokenize(parse_str, pos_buffer); for (unsigned int i = 0; i < 3; i++) nor[i] = stof(pos_buffer[i]); normals->push_back(nor); vn = true; } } else if (type_str == "f") { MeshFaceIndices faceIndex; if (vn && vt) { f_buffer.clear(); std::string parse_str = line_stream.substr(line_stream.find("f") + 1); StringTools::tokenize(parse_str, f_buffer); for (int i = 0; i < 3; ++i) { pos_buffer.clear(); StringTools::tokenize(f_buffer[i], pos_buffer, "/"); faceIndex.posIndices[i] = stoi(pos_buffer[0]) - 1; faceIndex.texIndices[i] = stoi(pos_buffer[1]) - 1; faceIndex.normalIndices[i] = stoi(pos_buffer[2]) - 1; } } else if (vn) { f_buffer.clear(); std::string parse_str = line_stream.substr(line_stream.find("f") + 1); StringTools::tokenize(parse_str, f_buffer); for (int i = 0; i < 3; ++i) { pos_buffer.clear(); StringTools::tokenize(f_buffer[i], pos_buffer, "/"); faceIndex.posIndices[i] = stoi(pos_buffer[0]) - 1; faceIndex.normalIndices[i] = stoi(pos_buffer[1]) - 1; } } else if (vt) { f_buffer.clear(); std::string parse_str = line_stream.substr(line_stream.find("f") + 1); StringTools::tokenize(parse_str, f_buffer); for (int i = 0; i < 3; ++i) { pos_buffer.clear(); StringTools::tokenize(f_buffer[i], pos_buffer, "/"); faceIndex.posIndices[i] = stoi(pos_buffer[0]) - 1; faceIndex.texIndices[i] = stoi(pos_buffer[1]) - 1; } } else { f_buffer.clear(); std::string parse_str = line_stream.substr(line_stream.find("f") + 1); StringTools::tokenize(parse_str, f_buffer); for (int i = 0; i < 3; ++i) { faceIndex.posIndices[i] = stoi(f_buffer[i]) - 1; } } faces->push_back(faceIndex); } } filestream.close(); } }; } #endif