From 2a72a30aa2c42fec0106fbd8c642386602a22227 Mon Sep 17 00:00:00 2001 From: SeanOMik Date: Fri, 16 Sep 2022 17:39:24 -0400 Subject: [PATCH] Readadd obj loading --- examples/dev_testing/src/main.cpp | 10 ++- include/simpleengine/gfx/model.h | 7 ++ src/gfx/model.cpp | 107 +++++++++++++++++++++++++++++- 3 files changed, 121 insertions(+), 3 deletions(-) diff --git a/examples/dev_testing/src/main.cpp b/examples/dev_testing/src/main.cpp index 9c163e8..2084785 100644 --- a/examples/dev_testing/src/main.cpp +++ b/examples/dev_testing/src/main.cpp @@ -171,9 +171,15 @@ int main(int argc, char *argv[]) { se::gfx::Material material(white_texture, 1.f, 0.f, 0.f, 0.f, 0.f); // Create the entity and add the model component to it. - auto entity = std::make_shared(); + /* auto entity = std::make_shared(); entity->add_component(cube_vertices, cube_indicies, material, true); - entity->translate(3.5f, 0.f, 0.f); + entity->translate(3.5f, 0.f, 0.f); */ + + //auto entity = std::make_shared(game.get_window(), core_shader, white_texture, "examples/dev_testing/resources/dragon.obj"); + auto entity = std::make_shared(); + se::gfx::Model model(material, "examples/dev_testing/resources/dragon.obj"); + entity->add_component(model); + entity->translate(5.f, 0.f, 0.f); // Create a renderer and submit the entity into it. auto renderer = std::make_shared(game.get_window(), core_shader); diff --git a/include/simpleengine/gfx/model.h b/include/simpleengine/gfx/model.h index fddf29b..ac7bcdd 100644 --- a/include/simpleengine/gfx/model.h +++ b/include/simpleengine/gfx/model.h @@ -30,6 +30,8 @@ namespace simpleengine::gfx { Model(std::vector vertices, std::vector indicies, Material material); Model(std::vector vertices, std::vector indicies = std::vector(), std::optional material = std::nullopt); + Model(Material material, std::string filename); + Model(Material material, std::ifstream file_stream); virtual void destroy() override; @@ -44,5 +46,10 @@ namespace simpleengine::gfx { * */ void calculate_normals(); + + private: + void process_vertex(const std::vector& vertex_data, const std::vector& in_textures, + const std::vector& in_normals, std::vector& out_indicies, + std::vector& out_textures, std::vector& out_normals); }; } \ No newline at end of file diff --git a/src/gfx/model.cpp b/src/gfx/model.cpp index 38539e5..0f35527 100644 --- a/src/gfx/model.cpp +++ b/src/gfx/model.cpp @@ -4,7 +4,7 @@ namespace simpleengine::gfx { Model::Model(std::vector vertices, std::vector indicies, Material material) : material(std::make_optional(material)), vertices(vertices), indicies(indicies), - vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)), + vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)), vao(gfx::VAO::init()) { } @@ -16,6 +16,111 @@ namespace simpleengine::gfx { } + Model::Model(Material material,std::string filename) : + Model(material, std::ifstream(filename, std::ios::in | std::ios::binary)) { + + } + + std::vector split_string(std::string str, const char delim) { + std::istringstream ss(str); + + std::vector tokens; + size_t pos = 0; + std::string token; + while ((pos = str.find(delim)) != std::string::npos) { + token = str.substr(0, pos); + tokens.push_back(token); + str.erase(0, pos + 1); + } + tokens.push_back(str); + + return tokens; + } + + Model::Model(Material material, std::ifstream file_stream) : + vbo(gfx::VBO::init(GL_ARRAY_BUFFER, false)), ebo(gfx::VBO::init(GL_ELEMENT_ARRAY_BUFFER, false)), + vao(gfx::VAO::init()), material(material) { + + if (!file_stream.is_open()) { + std::cerr << "File stream that was given to ObjModel::ObjModel is not open!" << std::endl; + throw std::runtime_error("Failed to open ObjModel model file"); + } + + // The vertices, texture coords, and normals that were read from the obj file + // these are not in a particular order. + std::vector obj_vertices; + std::vector obj_textures; + std::vector obj_normals; + + // The texture coords and normals that have been sorted. + std::vector textures; + std::vector normals; + + // Read the vertices, texture coords, and normals. Break when run into indices + std::string line; + while (std::getline(file_stream, line)) { + std::vector line_tokens = split_string(line, ' '); + + if (line_tokens.front() == "v") { + //glm::vec3 vertex(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3])); + obj_vertices.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3])); + } else if (line_tokens.front() == "vt") { + obj_textures.emplace_back(stof(line_tokens[1]), stof(line_tokens[2])); + } else if (line_tokens.front() == "vn") { + obj_normals.emplace_back(stof(line_tokens[1]), stof(line_tokens[2]), stof(line_tokens[3])); + } else if (line_tokens.front() == "f") { + auto size = obj_vertices.size(); + textures.resize(size); + normals.resize(size); + break; + } + } + + // Process the indicies. This will sort everything for storing inside of the Vertex list. + do { + if (!line.starts_with("f")) { + continue; + } + std::vector line_tokens = split_string(line, ' '); + std::vector vertex1 = split_string(line_tokens[1], '/'); + std::vector vertex2 = split_string(line_tokens[2], '/'); + std::vector vertex3 = split_string(line_tokens[3], '/'); + + process_vertex(vertex1, obj_textures, obj_normals, indicies, textures, normals); + process_vertex(vertex2, obj_textures, obj_normals, indicies, textures, normals); + process_vertex(vertex3, obj_textures, obj_normals, indicies, textures, normals); + } while (std::getline(file_stream, line)); + + file_stream.close(); + + const int texture_id = 0; + + std::cout << "Texture ID: " << texture_id << std::endl; + + // Insert everything into lit_vertices. + for (int i = 0; i < obj_vertices.size(); i++) { + vertices.emplace_back(simpleengine::Vectorf(obj_vertices.at(i)), glm::vec3(1.f), textures.at(i), normals.at(i), texture_id); + } + } + + void Model::process_vertex(const std::vector& vertex_data, const std::vector& in_textures, + const std::vector& in_normals, std::vector& out_indicies, + std::vector& out_textures, std::vector& out_normals) { + + // Get the index the current vertex and put it in indicies + int currentVertexIndex = stoi(vertex_data[0]) - 1; + out_indicies.push_back(currentVertexIndex); + + // Read texture coords + glm::vec2 current_tex = in_textures.at(stoi(vertex_data[1]) - 1); + current_tex.y = 1 - current_tex.y; + out_textures.at(currentVertexIndex) = current_tex; + + // Read normals + glm::vec3 current_norm = in_normals.at(stoi(vertex_data[2]) - 1); + out_normals.at(currentVertexIndex) = current_norm; + } + void Model::destroy() { this->ebo.destroy(); this->vbo.destroy();