-
Notifications
You must be signed in to change notification settings - Fork 6
feat(object): obj loader #72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
f0986b8
feat(object): add the declaration of the Vertex structure to represen…
MasterLaplace 0e8a84f
feat(object): add the declaration of the Mesh structure to represent …
MasterLaplace cda8f50
feat(object): implement OBJLoader for loading .obj files and managing…
MasterLaplace b372439
feat(object): add inclusions for OBJLoader, Vertex, and Mesh in Objec…
MasterLaplace d50f517
feat(object): add validation for model loading path in OBJLoader
MasterLaplace 6b6612f
feat(object): reorder includes in Object.hpp and add unit tests for O…
MasterLaplace 054a214
style: apply linter
github-actions[bot] eed6e74
feat(tests): add .obj files for model loading tests
MasterLaplace edbba8a
fix(object): move TINYOBJLOADER_IMPLEMENTATION to OBJLoader.cpp and u…
MasterLaplace da879eb
fix(tests): update OBJLoader tests to use a defined file path for assets
MasterLaplace 5a04226
style: apply linter
github-actions[bot] d0f16f1
fix(object): refactor OBJLoader to include Logger and change target k…
MasterLaplace e22afdd
fix(tests): update OBJLoader tests to use a new asset path and adjust…
MasterLaplace b3c22c4
fix(build): update asset handling in xmake.lua for improved build pro…
MasterLaplace 727892a
fix(tests): remove obsolete loadModel_fail test and associated asset
MasterLaplace de8e13a
fix(build): remove obsolete test target configuration from xmake.lua
MasterLaplace 0e6d7ca
fix(tests): add assertions to verify vertices and indices are not emp…
MasterLaplace d85e575
refactor(mesh): update MeshLoader to use a functor for loading meshes
MasterLaplace f26bf0c
test(mesh): add unit test for loading mesh from entt resource cache
MasterLaplace 36b6fb0
test(vertex): add unit tests for the Vertex structure
MasterLaplace 8ba35a6
style: apply linter
github-actions[bot] d711469
refactor(vertex): simplify equality operator and add unit test for fa…
MasterLaplace ae32655
refactor(tests): rename test files and update test case names for con…
MasterLaplace 41de6fd
refactor(xmake): restructure build and clean functions for asset mana…
MasterLaplace 4e64c62
fix: update dependency management and change build hook to after_build
MasterLaplace b225040
refactor(OBJLoader): replace push_back with emplace_back for performa…
MasterLaplace 00bd96b
test(OBJLoader): update test case to use non-OBJ file and add corresp…
MasterLaplace f1392ff
Merge branch 'main' into 40-obj-loader
ripel2 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| /************************************************************************** | ||
| * EngineSquared v0.0.0 | ||
| * | ||
| * EngineSquared is a software package, part of the Engine². | ||
| * | ||
| * This file is part of the EngineSquared project that is under GPL-3.0 License. | ||
| * Copyright © 2024 by @EngineSquared, All rights reserved. | ||
| * | ||
| * EngineSquared is a free software: you can redistribute it and/or modify | ||
| * it under the terms of the GPL-3.0 License as published by the | ||
| * Free Software Foundation. See the GPL-3.0 License for more details. | ||
| * | ||
| * @file Mesh.hpp | ||
| * @brief Mesh struct declaration. | ||
| * | ||
| * This struct is used to represent a mesh. | ||
| * | ||
| * @author @MasterLaplace | ||
| * @version 0.0.0 | ||
| * @date 2024-12-06 | ||
| **************************************************************************/ | ||
|
|
||
| #ifndef MESH_HPP_ | ||
| #define MESH_HPP_ | ||
|
|
||
| #include "OBJLoader.hpp" | ||
|
|
||
| #include <entt/resource/loader.hpp> | ||
|
|
||
| namespace ES::Plugin::Object::Component { | ||
|
|
||
| /** | ||
| * @brief Mesh structure. | ||
| * | ||
| * This structure is used to represent a mesh. | ||
| * It contains the vertices and indices of the mesh. | ||
| */ | ||
| struct Mesh { | ||
| std::vector<Component::Vertex> vertices; | ||
| std::vector<uint32_t> indices; | ||
|
|
||
| explicit Mesh(const std::string &file) { Resource::OBJLoader::loadModel(file, vertices, indices); } | ||
| }; | ||
|
|
||
| /** | ||
| * @brief MeshLoader structure. | ||
| * | ||
| * This structure is used to load a mesh from a file. | ||
| * @note This structure is used by the entt resource cache. | ||
| */ | ||
| struct MeshLoader final { | ||
| using result_type = std::shared_ptr<Mesh>; | ||
|
|
||
| result_type operator()(const std::string &file) const { return std::make_shared<Mesh>(file); } | ||
| }; | ||
|
|
||
| } // namespace ES::Plugin::Object::Component | ||
|
|
||
| #endif /* !MESH_HPP_ */ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| /************************************************************************** | ||
| * EngineSquared v0.0.0 | ||
| * | ||
| * EngineSquared is a software package, part of the Engine². | ||
| * | ||
| * This file is part of the EngineSquared project that is under GPL-3.0 License. | ||
| * Copyright © 2024 by @EngineSquared, All rights reserved. | ||
| * | ||
| * EngineSquared is a free software: you can redistribute it and/or modify | ||
| * it under the terms of the GPL-3.0 License as published by the | ||
| * Free Software Foundation. See the GPL-3.0 License for more details. | ||
| * | ||
| * @file Vertex.hpp | ||
| * @brief Vertex struct declaration. | ||
| * | ||
| * This struct is used to represent a vertex in a mesh. | ||
| * | ||
| * @author @MasterLaplace | ||
| * @version 0.0.0 | ||
| * @date 2024-12-06 | ||
| **************************************************************************/ | ||
|
|
||
| #ifndef VERTEX_HPP_ | ||
| #define VERTEX_HPP_ | ||
|
|
||
| #include <glm/glm.hpp> | ||
|
|
||
| #define GLM_ENABLE_EXPERIMENTAL | ||
| #include <glm/gtx/hash.hpp> | ||
|
|
||
| namespace ES::Plugin::Object::Component { | ||
|
|
||
| /** | ||
| * @brief Vertex structure. | ||
| * | ||
| * This structure is used to represent a vertex in a mesh. | ||
| * It contains the position, color, and texture coordinates of the vertex. | ||
| */ | ||
| struct Vertex { | ||
| glm::vec3 pos; | ||
| glm::vec3 color; | ||
| glm::vec2 texCoord; | ||
|
|
||
| bool operator==(const Vertex &other) const = default; | ||
| }; | ||
|
|
||
| } // namespace ES::Plugin::Object::Component | ||
|
|
||
| namespace std { | ||
|
|
||
| /** | ||
| * @brief Hash function for the Vertex structure. | ||
| */ | ||
| template <> struct hash<ES::Plugin::Object::Component::Vertex> { | ||
| /** | ||
| * @brief Hash function for the Vertex structure. | ||
| * | ||
| * @param vertex Vertex to hash. | ||
| * @return std::size_t Hash value. | ||
| */ | ||
| size_t operator()(ES::Plugin::Object::Component::Vertex const &vertex) const | ||
| { | ||
| return ((hash<glm::vec3>()(vertex.pos) ^ (hash<glm::vec3>()(vertex.color) << 1)) >> 1) ^ | ||
| (hash<glm::vec2>()(vertex.texCoord) << 1); | ||
| } | ||
| }; | ||
|
|
||
| } // namespace std | ||
|
|
||
| #endif /* !VERTEX_HPP_ */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| #include "OBJLoader.hpp" | ||
|
|
||
| #define TINYOBJLOADER_IMPLEMENTATION | ||
| #include "tiny_obj_loader.h" | ||
|
|
||
| #include "Logger.hpp" | ||
|
|
||
| namespace ES::Plugin::Object::Resource { | ||
|
|
||
| bool OBJLoader::loadModel(const std::string &path, std::vector<Component::Vertex> &vertices, | ||
| std::vector<uint32_t> &indices) | ||
| { | ||
| tinyobj::attrib_t attrib; | ||
| std::vector<tinyobj::shape_t> shapes; | ||
| std::vector<tinyobj::material_t> materials; | ||
| std::string warn; | ||
| std::string err; | ||
|
|
||
| if (path.empty()) | ||
| { | ||
| ES::Utils::Log::Warn("The path is empty."); | ||
| return false; | ||
| } | ||
|
|
||
| else if (path.ends_with(".obj") == false) | ||
| { | ||
| ES::Utils::Log::Warn("The file is not a .obj file."); | ||
| return false; | ||
| } | ||
|
|
||
| else if (!tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, path.c_str())) | ||
| { | ||
| ES::Utils::Log::Warn(warn + err); | ||
| return false; | ||
| } | ||
|
|
||
| vertices.reserve(attrib.vertices.size() / 3); | ||
| indices.reserve(attrib.vertices.size()); | ||
|
|
||
| std::unordered_map<Component::Vertex, uint32_t> uniqueVertices{}; | ||
|
|
||
| for (const auto &shape : shapes) | ||
| { | ||
| for (const auto &index : shape.mesh.indices) | ||
| { | ||
| Component::Vertex vertex{}; | ||
|
|
||
| vertex.pos = {attrib.vertices[3 * index.vertex_index + 0], attrib.vertices[3 * index.vertex_index + 1], | ||
| attrib.vertices[3 * index.vertex_index + 2]}; | ||
|
|
||
| vertex.texCoord = {attrib.texcoords[2 * index.texcoord_index + 0], | ||
| 1.0f - attrib.texcoords[2 * index.texcoord_index + 1]}; | ||
|
|
||
| vertex.color = {1.0f, 1.0f, 1.0f}; | ||
|
|
||
| if (uniqueVertices.count(vertex) == 0) | ||
| { | ||
| uniqueVertices[vertex] = static_cast<uint32_t>(vertices.size()); | ||
| vertices.emplace_back(vertex); | ||
| } | ||
|
|
||
| indices.emplace_back(uniqueVertices[vertex]); | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| } // namespace ES::Plugin::Object::Resource |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| /************************************************************************** | ||
| * EngineSquared v0.0.0 | ||
| * | ||
| * EngineSquared is a software package, part of the Engine². | ||
| * | ||
| * This file is part of the EngineSquared project that is under GPL-3.0 License. | ||
| * Copyright © 2024 by @EngineSquared, All rights reserved. | ||
| * | ||
| * EngineSquared is a free software: you can redistribute it and/or modify | ||
| * it under the terms of the GPL-3.0 License as published by the | ||
| * Free Software Foundation. See the GPL-3.0 License for more details. | ||
| * | ||
| * @file OBJLoader.hpp | ||
| * @brief OBJLoader class declaration. | ||
| * | ||
| * This class is used to load .obj files and create a model from them. | ||
| * | ||
| * @author @MasterLaplace | ||
| * @version 0.0.0 | ||
| * @date 2024-12-06 | ||
| **************************************************************************/ | ||
|
|
||
| #ifndef OBJLOADER_HPP_ | ||
| #define OBJLOADER_HPP_ | ||
|
|
||
| #include <memory> | ||
| #include <stdexcept> | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| #include "Vertex.hpp" | ||
|
|
||
| namespace ES::Plugin::Object::Resource { | ||
|
|
||
| /** | ||
| * @brief OBJLoader class. | ||
| * | ||
| * This class is used to load .obj files. | ||
| */ | ||
| class OBJLoader { | ||
| public: | ||
| /** | ||
| * Load a model from a .obj file. | ||
| * | ||
| * @param path path to the .obj file | ||
| * @param vertices vector to store the vertices | ||
| * @param indices vector to store the indices | ||
| * @return true if the model was loaded successfully, false otherwise | ||
| */ | ||
| static bool loadModel(const std::string &path, std::vector<Component::Vertex> &vertices, | ||
| std::vector<uint32_t> &indices); | ||
|
ripel2 marked this conversation as resolved.
|
||
| }; | ||
|
|
||
| } // namespace ES::Plugin::Object::Resource | ||
|
|
||
| #endif /* !OBJLOADER_HPP_ */ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| #include <gtest/gtest.h> | ||
|
|
||
| #include "Mesh.hpp" | ||
|
|
||
| #include <entt/core/hashed_string.hpp> | ||
| #include <entt/resource/cache.hpp> | ||
|
|
||
| #include "export.h" | ||
|
|
||
| #define OBJ_FILE_PATH PROJECT_SOURCE_DIR "assets/" | ||
|
|
||
| using namespace ES::Plugin::Object; | ||
|
|
||
| /** | ||
| * @brief Load a mesh from a file using the entt resource cache. | ||
| * The mesh is loaded from a file and stored in the cache. | ||
| * The mesh is then retrieved from the cache and its vertices are checked. | ||
| */ | ||
| TEST(MeshTest, component_mesh_entt_cache_loader) | ||
| { | ||
| entt::resource_cache<Component::Mesh, Component::MeshLoader> cache{}; | ||
|
|
||
| std::string something_else("mesh_id"); | ||
| auto ret = cache.load(entt::hashed_string{something_else.c_str()}, std::string(OBJ_FILE_PATH "cube.obj")); | ||
|
|
||
| EXPECT_EQ(ret.second, true); | ||
|
|
||
| entt::resource<Component::Mesh> res = ret.first->second; | ||
|
|
||
| EXPECT_EQ(res->vertices.empty(), false); | ||
| EXPECT_EQ(res->indices.empty(), false); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| #include <gtest/gtest.h> | ||
|
|
||
| #include "OBJLoader.hpp" | ||
|
|
||
| #include "export.h" | ||
|
|
||
| #define OBJ_FILE_PATH PROJECT_SOURCE_DIR "assets/" | ||
|
|
||
| using namespace ES::Plugin::Object; | ||
|
|
||
| TEST(OBJLoaderTest, loadModel) | ||
| { | ||
| std::vector<Component::Vertex> vertices; | ||
| std::vector<uint32_t> indices; | ||
|
|
||
| EXPECT_EQ(Resource::OBJLoader::loadModel(OBJ_FILE_PATH "cube.obj", vertices, indices), true); | ||
|
|
||
| EXPECT_EQ(vertices.empty(), false); | ||
| EXPECT_EQ(indices.empty(), false); | ||
| } | ||
|
|
||
| TEST(OBJLoaderTest, loadModel_empty_path) | ||
| { | ||
| std::vector<Component::Vertex> vertices; | ||
| std::vector<uint32_t> indices; | ||
|
|
||
| EXPECT_EQ(Resource::OBJLoader::loadModel("", vertices, indices), false); | ||
| } | ||
|
|
||
| TEST(OBJLoaderTest, loadModel_not_obj_file) | ||
| { | ||
| std::vector<Component::Vertex> vertices; | ||
| std::vector<uint32_t> indices; | ||
|
|
||
| EXPECT_EQ(Resource::OBJLoader::loadModel(OBJ_FILE_PATH "not_obj.txt", vertices, indices), false); | ||
| } | ||
|
|
||
| TEST(OBJLoaderTest, loadModel_wrong_path) | ||
| { | ||
| std::vector<Component::Vertex> vertices; | ||
| std::vector<uint32_t> indices; | ||
|
|
||
| EXPECT_EQ(Resource::OBJLoader::loadModel("wrong_path", vertices, indices), false); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.