From 7e0d57b4fed29f73b43898d14661319ca5c85857 Mon Sep 17 00:00:00 2001 From: JosiahWI Date: Wed, 17 May 2023 09:09:06 -0500 Subject: [PATCH] Reorganize CGLTFMeshFileLoader help functions I moved them all into static methods and changed the ordering in the source file so that createMesh() would be close to the top of the file. I also corrected formatting in some of the function declarations since I had to change them anyway. --- source/Irrlicht/CGLTFMeshFileLoader.cpp | 376 ++++++++++++------------ source/Irrlicht/CGLTFMeshFileLoader.h | 72 ++++- src/CMakeLists.txt | 2 +- 3 files changed, 258 insertions(+), 192 deletions(-) diff --git a/source/Irrlicht/CGLTFMeshFileLoader.cpp b/source/Irrlicht/CGLTFMeshFileLoader.cpp index 5edb1ef7..bba35226 100644 --- a/source/Irrlicht/CGLTFMeshFileLoader.cpp +++ b/source/Irrlicht/CGLTFMeshFileLoader.cpp @@ -21,201 +21,43 @@ #include #include -template -struct Span -{ - T* buffer = nullptr; - std::size_t size = 0; -}; - -class BufferOffset -{ -public: - BufferOffset(const std::vector& buf, - const std::size_t offset) - : m_buf(buf) - , m_offset(offset) - { - } - - BufferOffset(const BufferOffset& other, const std::size_t fromOffset) - : m_buf(other.m_buf) - , m_offset(other.m_offset + fromOffset) - { - } - - unsigned char at(const std::size_t fromOffset) const - { - return m_buf.at(m_offset + fromOffset); - } - -private: - const std::vector& m_buf; - std::size_t m_offset; -}; - // A helper function to disable tinygltf embedded image loading -bool dummyImageLoader(tinygltf::Image *a, const int b, std::string *c, - std::string *d, int e, int f, const unsigned char * g, - int h, void *user_pointer) +static bool dummyImageLoader(tinygltf::Image *a, + const int b, std::string *c, + std::string *d, + int e, + int f, + const unsigned char * g, + int h, + void *user_pointer) { return false; }; -namespace irr +namespace irr { + +namespace scene { + +CGLTFMeshFileLoader::BufferOffset::BufferOffset( + const std::vector& buf, + const std::size_t offset) + : m_buf(buf) + , m_offset(offset) { - -namespace scene -{ - -static bool tryParseGLTF(io::IReadFile* file, tinygltf::Model& model) -{ - tinygltf::TinyGLTF loader {}; - - // Stop embedded textures from making model fail to load - loader.SetImageLoader(dummyImageLoader, nullptr); - - std::string err {}; - std::string warn {}; - - auto buf = std::make_unique(file->getSize()); - file->read(buf.get(), file->getSize()); - - if (err != "") { - return false; - } - - return loader.LoadASCIIFromString(&model, &err, &warn, buf.get(), - file->getSize(), "", 1); } -template -static T readPrimitive(const BufferOffset& readFrom) +CGLTFMeshFileLoader::BufferOffset::BufferOffset( + const CGLTFMeshFileLoader::BufferOffset& other, + const std::size_t fromOffset) + : m_buf(other.m_buf) + , m_offset(other.m_offset + fromOffset) { - unsigned char d[sizeof(T)]{}; - for (std::size_t i = 0; i < sizeof(T); ++i) { - d[i] = readFrom.at(i); - } - T dest; - std::memcpy(&dest, d, sizeof(dest)); - return dest; } -static core::vector2df readVec2DF(const BufferOffset& readFrom) +unsigned char CGLTFMeshFileLoader::BufferOffset::at( + const std::size_t fromOffset) const { - return core::vector2df(readPrimitive(readFrom), - readPrimitive(BufferOffset( readFrom, sizeof(float)))); - -} - -static core::vector3df readVec3DF(const BufferOffset& readFrom, - const float scale = 1.0f) -{ - // glTF's coordinate system is right-handed, Irrlicht's is left-handed - // glTF's +Z axis corresponds to Irrlicht's -Z axis - return core::vector3df( - scale * readPrimitive(readFrom), - scale * readPrimitive(BufferOffset(readFrom, sizeof(float))), - -scale * readPrimitive(BufferOffset(readFrom, 2 * - sizeof(float)))); -} - -float getScale(const tinygltf::Model& model) -{ - if (model.nodes[0].scale.size() > 0) { - return static_cast(model.nodes[0].scale[0]); - } - return 1.0f; -} - -static void copyPositions(const tinygltf::Model& model, - const Span vertices, const std::size_t accessorId) -{ - - const auto& view = model.bufferViews[ - model.accessors[accessorId].bufferView]; - const auto& buffer = model.buffers[view.buffer]; - const auto count = model.accessors[accessorId].count; - - float scale = getScale(model); - - for (std::size_t i = 0; i < count; i++) { - const auto v = readVec3DF(BufferOffset( - buffer.data, view.byteOffset + (3 * sizeof(float) * i)),scale); - vertices.buffer[i].Pos = v; - } -} - -static void copyNormals(const tinygltf::Model& model, -const Span vertices,const std::size_t accessorId) -{ - const auto& view = model.bufferViews[ - model.accessors[accessorId].bufferView]; - const auto& buffer = model.buffers[view.buffer]; - const auto count = model.accessors[accessorId].count; - - for (std::size_t i = 0; i < count; i++) { - const auto n = readVec3DF(BufferOffset( buffer.data, - view.byteOffset + 3 * sizeof(float) * i )); - vertices.buffer[i].Normal = n; - } -} - -static void copyTCoords(const tinygltf::Model& model, - const Span vertices, const std::size_t accessorId) -{ - const auto& view = model.bufferViews[ - model.accessors[accessorId].bufferView]; - const auto& buffer = model.buffers[view.buffer]; - const auto count = model.accessors[accessorId].count; - - for (std::size_t i = 0; i < count; ++i) { - const auto t = readVec2DF(BufferOffset( - buffer.data, view.byteOffset + 2 * sizeof(float) * i)); - vertices.buffer[i].TCoords = t; - } -} - -static void getIndices(const tinygltf::Model& model, - const std::size_t accessorId, std::vector& indicesBuffer) -{ - const auto& view = model.bufferViews[ - model.accessors[accessorId].bufferView]; - const auto& modelIndices = model.buffers[view.buffer]; - - auto buffOffset = BufferOffset(modelIndices.data, view.byteOffset); - auto count = model.accessors[accessorId].count; - - for (std::size_t i = 0; i < count; i++) { - indicesBuffer[i] = readPrimitive(BufferOffset( - buffOffset, i * sizeof(u16))); - } -} - -//Returns a tuple of the current counts (current_vertex_index, -// current_normals_index, current_tcoords_index) -static void getVertices -( const tinygltf::Model& model, const std::size_t accessorId, - Span& verticesBuffer, - std::size_t mesh_index, std::size_t primitive_index ) -{ - copyPositions(model, verticesBuffer, accessorId); - - const auto normalsField = model.meshes[mesh_index] - .primitives[primitive_index].attributes.find("NORMAL"); - - if (normalsField != model.meshes[mesh_index] - .primitives[primitive_index].attributes.end()) { - copyNormals(model, verticesBuffer, normalsField->second); - } - - const auto tCoordsField = model.meshes[mesh_index] - .primitives[primitive_index].attributes.find("TEXCOORD_0"); - - if (tCoordsField != model.meshes[mesh_index] - .primitives[primitive_index].attributes.end()) { - copyTCoords(model, verticesBuffer, tCoordsField->second); - } + return m_buf.at(m_offset + fromOffset); } CGLTFMeshFileLoader::CGLTFMeshFileLoader() noexcept @@ -223,7 +65,7 @@ CGLTFMeshFileLoader::CGLTFMeshFileLoader() noexcept } bool CGLTFMeshFileLoader::isALoadableFileExtension( - const io::path& filename) const + const io::path& filename) const { return core::hasFileExtension(filename, "gltf"); } @@ -254,7 +96,7 @@ IAnimatedMesh* CGLTFMeshFileLoader::createMesh(io::IReadFile* file) // Creates counts for preallocation std::size_t vertices_count = model.accessors[positionAccessorId].count; - // We must count to create containers for the data + // We must count to create containers for the data // Create new buffer for vertices, positions, and normals auto* vertexBuffer = new video::S3DVertex[vertices_count](); // This is used to copy data into the vertexBuffer @@ -270,13 +112,13 @@ IAnimatedMesh* CGLTFMeshFileLoader::createMesh(io::IReadFile* file) // Inverse the order of indices due to the axis of the model being // inverted when going from left handed to right handed coordinates - std::reverse(indicesBuffer.begin(),indicesBuffer.end()); + std::reverse(indicesBuffer.begin(),indicesBuffer.end()); // Create the mesh buffer SMeshBuffer* meshbuf { new SMeshBuffer {} }; meshbuf->append(vertexBuffer, vertices_count, indicesBuffer.data(), indicesBuffer.size()); - + mesh->addMeshBuffer(meshbuf); } @@ -284,11 +126,169 @@ IAnimatedMesh* CGLTFMeshFileLoader::createMesh(io::IReadFile* file) // Create the mesh animations SAnimatedMesh* animatedMesh { new SAnimatedMesh {} }; - animatedMesh->addMesh(mesh); + animatedMesh->addMesh(mesh); return animatedMesh; } +template +T CGLTFMeshFileLoader::readPrimitive(const BufferOffset& readFrom) +{ + unsigned char d[sizeof(T)]{}; + for (std::size_t i = 0; i < sizeof(T); ++i) { + d[i] = readFrom.at(i); + } + T dest; + std::memcpy(&dest, d, sizeof(dest)); + return dest; +} + +core::vector2df CGLTFMeshFileLoader::readVec2DF( + const CGLTFMeshFileLoader::BufferOffset& readFrom) +{ + return core::vector2df(readPrimitive(readFrom), + readPrimitive(BufferOffset(readFrom, sizeof(float)))); + +} + +core::vector3df CGLTFMeshFileLoader::readVec3DF( + const CGLTFMeshFileLoader::BufferOffset& readFrom, + const float scale = 1.0f) +{ + // glTF's coordinate system is right-handed, Irrlicht's is left-handed + // glTF's +Z axis corresponds to Irrlicht's -Z axis + return core::vector3df( + scale * readPrimitive(readFrom), + scale * readPrimitive(BufferOffset(readFrom, sizeof(float))), + -scale * readPrimitive(BufferOffset(readFrom, 2 * + sizeof(float)))); +} + +void CGLTFMeshFileLoader::copyPositions(const tinygltf::Model& model, + const Span vertices, + const std::size_t accessorId) +{ + + const auto& view = model.bufferViews[ + model.accessors[accessorId].bufferView]; + const auto& buffer = model.buffers[view.buffer]; + const auto count = model.accessors[accessorId].count; + + float scale = getScale(model); + + for (std::size_t i = 0; i < count; i++) { + const auto v = readVec3DF(BufferOffset( + buffer.data, view.byteOffset + (3 * sizeof(float) * i)),scale); + vertices.buffer[i].Pos = v; + } +} + +void CGLTFMeshFileLoader::copyNormals(const tinygltf::Model& model, + const Span vertices, + const std::size_t accessorId) +{ + const auto& view = model.bufferViews[ + model.accessors[accessorId].bufferView]; + const auto& buffer = model.buffers[view.buffer]; + const auto count = model.accessors[accessorId].count; + + for (std::size_t i = 0; i < count; i++) { + const auto n = readVec3DF(BufferOffset( buffer.data, + view.byteOffset + 3 * sizeof(float) * i )); + vertices.buffer[i].Normal = n; + } +} + +void CGLTFMeshFileLoader::copyTCoords(const tinygltf::Model& model, + const Span vertices, + const std::size_t accessorId) +{ + const auto& view = model.bufferViews[ + model.accessors[accessorId].bufferView]; + const auto& buffer = model.buffers[view.buffer]; + const auto count = model.accessors[accessorId].count; + + for (std::size_t i = 0; i < count; ++i) { + const auto t = readVec2DF(BufferOffset( + buffer.data, view.byteOffset + 2 * sizeof(float) * i)); + vertices.buffer[i].TCoords = t; + } +} + +void CGLTFMeshFileLoader::getIndices(const tinygltf::Model& model, + const std::size_t accessorId, + std::vector& indicesBuffer) +{ + const auto& view = model.bufferViews[ + model.accessors[accessorId].bufferView]; + const auto& modelIndices = model.buffers[view.buffer]; + + auto buffOffset = BufferOffset(modelIndices.data, view.byteOffset); + auto count = model.accessors[accessorId].count; + + for (std::size_t i = 0; i < count; i++) { + indicesBuffer[i] = readPrimitive(BufferOffset( + buffOffset, i * sizeof(u16))); + } +} + +//Returns a tuple of the current counts (current_vertex_index, +// current_normals_index, current_tcoords_index) +void CGLTFMeshFileLoader::getVertices(const tinygltf::Model& model, + const std::size_t accessorId, + Span& verticesBuffer, + std::size_t mesh_index, + std::size_t primitive_index) +{ + copyPositions(model, verticesBuffer, accessorId); + + const auto normalsField = model.meshes[mesh_index] + .primitives[primitive_index].attributes.find("NORMAL"); + + if (normalsField != model.meshes[mesh_index] + .primitives[primitive_index].attributes.end()) { + copyNormals(model, verticesBuffer, normalsField->second); + } + + const auto tCoordsField = model.meshes[mesh_index] + .primitives[primitive_index].attributes.find("TEXCOORD_0"); + + if (tCoordsField != model.meshes[mesh_index] + .primitives[primitive_index].attributes.end()) { + copyTCoords(model, verticesBuffer, tCoordsField->second); + } +} + +bool CGLTFMeshFileLoader::tryParseGLTF(io::IReadFile* file, + tinygltf::Model& model) +{ + tinygltf::TinyGLTF loader {}; + + // Stop embedded textures from making model fail to load + loader.SetImageLoader(dummyImageLoader, nullptr); + + std::string err {}; + std::string warn {}; + + auto buf = std::make_unique(file->getSize()); + file->read(buf.get(), file->getSize()); + + if (err != "") { + return false; + } + + return loader.LoadASCIIFromString(&model, &err, &warn, buf.get(), + file->getSize(), "", 1); +} + +float CGLTFMeshFileLoader::getScale(const tinygltf::Model& model) +{ + if (model.nodes[0].scale.size() > 0) { + return static_cast(model.nodes[0].scale[0]); + } + return 1.0f; +} + } // namespace scene } // namespace irr diff --git a/source/Irrlicht/CGLTFMeshFileLoader.h b/source/Irrlicht/CGLTFMeshFileLoader.h index a082c29a..d6ba8f67 100644 --- a/source/Irrlicht/CGLTFMeshFileLoader.h +++ b/source/Irrlicht/CGLTFMeshFileLoader.h @@ -1,4 +1,3 @@ -<<<<<<< HEAD #ifndef __C_GLTF_MESH_FILE_LOADER_INCLUDED__ #define __C_GLTF_MESH_FILE_LOADER_INCLUDED__ @@ -6,6 +5,14 @@ #include "IMeshLoader.h" #include "IReadFile.h" #include "path.h" +#include "S3DVertex.h" +#include "vector2d.h" +#include "vector3d.h" + +#include + +#include +#include namespace irr { @@ -16,14 +23,72 @@ namespace scene class CGLTFMeshFileLoader : public IMeshLoader { public: - CGLTFMeshFileLoader(); + CGLTFMeshFileLoader() noexcept; bool isALoadableFileExtension(const io::path& filename) const override; IAnimatedMesh* createMesh(io::IReadFile* file) override; private: - bool tryParseGLTF(io::IReadFile* file) const; + template + struct Span + { + T* buffer = nullptr; + std::size_t size = 0; + }; + + class BufferOffset + { + public: + BufferOffset(const std::vector& buf, + const std::size_t offset); + + BufferOffset(const BufferOffset& other, + const std::size_t fromOffset); + + unsigned char at(const std::size_t fromOffset) const; + private: + const std::vector& m_buf; + std::size_t m_offset; + int m_filesize; + }; + + template + static T readPrimitive(const BufferOffset& readFrom); + + static core::vector2df readVec2DF( + const BufferOffset& readFrom); + + static core::vector3df readVec3DF( + const BufferOffset& readFrom, + const float scale); + + static void copyPositions(const tinygltf::Model& model, + const Span vertices, + const std::size_t accessorId); + + static void copyNormals(const tinygltf::Model& model, + const Span vertices, + const std::size_t accessorId); + + static void copyTCoords(const tinygltf::Model& model, + const Span vertices, + const std::size_t accessorId); + + static void getIndices(const tinygltf::Model& model, + const std::size_t accessorId, + std::vector& indicesBuffer); + + static void getVertices(const tinygltf::Model& model, + const std::size_t accessorId, + Span& outVertices, + std::size_t meshIndex, + std::size_t primitiveIndex); + + static bool tryParseGLTF(io::IReadFile* file, + tinygltf::Model& model); + + static float getScale(const tinygltf::Model& model); }; } // namespace scene @@ -31,3 +96,4 @@ private: } // namespace irr #endif // __C_GLTF_MESH_FILE_LOADER_INCLUDED__ + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 73c8cd81..d82f8a67 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -369,7 +369,7 @@ get_property(tinygltf_COMPILE_DEFS PROPERTY INTERFACE_COMPILE_DEFINITIONS ) -target_include_directories(IRRMESHOBJ PRIVATE ${tinygltf_INCLUDE_DIRS}) +target_include_directories(IRRMESHOBJ PUBLIC ${tinygltf_INCLUDE_DIRS}) target_compile_definitions(IRRMESHOBJ PUBLIC ${tinygltf_COMPILE_DEFS}) add_library(IRROBJ OBJECT