From 9c21e2ec1b751d9aa17218b957638ab527329ce9 Mon Sep 17 00:00:00 2001 From: JosiahWI Date: Wed, 29 Nov 2023 19:57:58 -0600 Subject: [PATCH] Handle byte stride on vertex buffers Vertex buffers (and only vertex buffers) may have a byte stride specified. --- source/Irrlicht/CGLTFMeshFileLoader.cpp | 11 ++- source/Irrlicht/CGLTFMeshFileLoader.h | 2 + .../assets/triangle_with_vertex_stride.gltf | 71 +++++++++++++++++++ .../tests/testCGLTFMeshFileLoader.cpp | 12 +++- 4 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 source/Irrlicht/tests/assets/triangle_with_vertex_stride.gltf diff --git a/source/Irrlicht/CGLTFMeshFileLoader.cpp b/source/Irrlicht/CGLTFMeshFileLoader.cpp index 59ce3209b..8bec5de26 100644 --- a/source/Irrlicht/CGLTFMeshFileLoader.cpp +++ b/source/Irrlicht/CGLTFMeshFileLoader.cpp @@ -224,10 +224,11 @@ void CGLTFMeshFileLoader::MeshExtractor::copyPositions( const auto& buffer = getBuffer(accessorIdx); const auto count = getElemCount(accessorIdx); + const auto byteStride = getByteStride(accessorIdx); for (std::size_t i = 0; i < count; i++) { const auto v = readVec3DF(BufferOffset(buffer, - 3 * sizeof(float) * i), getScale()); + (byteStride * i)), getScale()); vertices[i].Pos = v; } } @@ -275,6 +276,14 @@ std::size_t CGLTFMeshFileLoader::MeshExtractor::getElemCount( return m_model.accessors[accessorIdx].count; } +std::size_t CGLTFMeshFileLoader::MeshExtractor::getByteStride( + const std::size_t accessorIdx) const +{ + const auto& accessor = m_model.accessors[accessorIdx]; + const auto& view = m_model.bufferViews[accessor.bufferView]; + return accessor.ByteStride(view); +} + CGLTFMeshFileLoader::BufferOffset CGLTFMeshFileLoader::MeshExtractor::getBuffer( const std::size_t accessorIdx) const { diff --git a/source/Irrlicht/CGLTFMeshFileLoader.h b/source/Irrlicht/CGLTFMeshFileLoader.h index 18f0cc598..2f1411681 100644 --- a/source/Irrlicht/CGLTFMeshFileLoader.h +++ b/source/Irrlicht/CGLTFMeshFileLoader.h @@ -104,6 +104,8 @@ private: std::size_t getElemCount(const std::size_t accessorIdx) const; + std::size_t getByteStride(const std::size_t accessorIdx) const; + BufferOffset getBuffer(const std::size_t accessorIdx) const; std::size_t getIndicesAccessorIdx(const std::size_t meshIdx, diff --git a/source/Irrlicht/tests/assets/triangle_with_vertex_stride.gltf b/source/Irrlicht/tests/assets/triangle_with_vertex_stride.gltf new file mode 100644 index 000000000..fce122c8a --- /dev/null +++ b/source/Irrlicht/tests/assets/triangle_with_vertex_stride.gltf @@ -0,0 +1,71 @@ +{ + "scene": 0, + "scenes" : [ + { + "nodes" : [ 0 ] + } + ], + + "nodes" : [ + { + "mesh" : 0 + } + ], + + "meshes" : [ + { + "primitives" : [ { + "attributes" : { + "POSITION" : 1 + }, + "indices" : 0 + } ] + } + ], + + "buffers" : [ + { + "uri" : "data:application/octet-stream;base64,AAABAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAAAA=", + "byteLength" : 80 + } + ], + "bufferViews" : [ + { + "buffer" : 0, + "byteOffset" : 0, + "byteLength" : 6, + "target" : 34963 + }, + { + "buffer" : 0, + "byteOffset" : 8, + "byteLength" : 36, + "byteStride" : 24, + "target" : 34962 + } + ], + "accessors" : [ + { + "bufferView" : 0, + "byteOffset" : 0, + "componentType" : 5123, + "count" : 3, + "type" : "SCALAR", + "max" : [ 2 ], + "min" : [ 0 ] + }, + { + "bufferView" : 1, + "byteOffset" : 0, + "componentType" : 5126, + "count" : 3, + "type" : "VEC3", + "max" : [ 1.0, 1.0, 0.0 ], + "min" : [ 0.0, 0.0, 0.0 ] + } + ], + + "asset" : { + "version" : "2.0" + } +} diff --git a/source/Irrlicht/tests/testCGLTFMeshFileLoader.cpp b/source/Irrlicht/tests/testCGLTFMeshFileLoader.cpp index 86d7ff09d..ea75c738c 100644 --- a/source/Irrlicht/tests/testCGLTFMeshFileLoader.cpp +++ b/source/Irrlicht/tests/testCGLTFMeshFileLoader.cpp @@ -1,8 +1,12 @@ #include "CReadFile.h" +#include + +// Catch needs to be included after Irrlicht so that it sees operator<< +// declarations. #define CATCH_CONFIG_MAIN #include -#include + #include using namespace std; @@ -49,7 +53,11 @@ TEST_CASE("load empty gltf file") { } TEST_CASE("minimal triangle") { - ScopedMesh sm("source/Irrlicht/tests/assets/minimal_triangle.gltf"); + auto path = GENERATE( + "source/Irrlicht/tests/assets/minimal_triangle.gltf", + "source/Irrlicht/tests/assets/triangle_with_vertex_stride.gltf"); + INFO(path); + ScopedMesh sm(path); REQUIRE(sm.getMesh() != nullptr); REQUIRE(sm.getMesh()->getMeshBufferCount() == 1);