From 86a9233a41db1f5e9fda02baed0865e1757ef424 Mon Sep 17 00:00:00 2001 From: Bart Siwek Date: Tue, 14 Aug 2018 13:59:37 +0200 Subject: [PATCH 1/5] MeshPrimitiveUtils now contains methods for serializing triangulated and segmented indices. --- Build/macOSPackageRoot/packages.config | 4 +- .../Source/MeshPrimitiveUtilsTests.cpp | 475 ++++++++++++++++++ GLTFSDK/CMakeLists.txt | 9 +- GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h | 18 +- GLTFSDK/Source/MeshPrimitiveUtils.cpp | 190 ++++++- 5 files changed, 687 insertions(+), 9 deletions(-) diff --git a/Build/macOSPackageRoot/packages.config b/Build/macOSPackageRoot/packages.config index 43bb3c1..2bae673 100644 --- a/Build/macOSPackageRoot/packages.config +++ b/Build/macOSPackageRoot/packages.config @@ -1,4 +1,4 @@  - - \ No newline at end of file + + diff --git a/GLTFSDK.Test/Source/MeshPrimitiveUtilsTests.cpp b/GLTFSDK.Test/Source/MeshPrimitiveUtilsTests.cpp index bc60b03..2bf5abe 100644 --- a/GLTFSDK.Test/Source/MeshPrimitiveUtilsTests.cpp +++ b/GLTFSDK.Test/Source/MeshPrimitiveUtilsTests.cpp @@ -1323,6 +1323,481 @@ namespace Microsoft Assert::AreEqual(outputIndices[262138], 131069U); Assert::AreEqual(outputIndices[262139], 0U); } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices16_Triangles) + { + auto readerWriter = std::make_shared(); + auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + + bufferBuilder.AddBuffer(); + bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + + // Serialize + MeshPrimitive meshPrimitive; + meshPrimitive.mode = MESH_TRIANGLES; + + std::vector triangulatedIndices = + { + 0, 3, 1, + 3, 2, 1, + 1, 2, 4, + 2, 5, 4 + }; + + meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeTriangulatedIndices16(triangulatedIndices, meshPrimitive.mode, bufferBuilder); + + // Read back & check + Document doc; + bufferBuilder.Output(doc); + + GLTFResourceReader reader(readerWriter); + + const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); + Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_SHORT, accessor.componentType); + + auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); + + AreEqual(triangulatedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices16_TriangleStrip) + { + auto readerWriter = std::make_shared(); + auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + + bufferBuilder.AddBuffer(); + bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + + // Serialize + MeshPrimitive meshPrimitive; + meshPrimitive.mode = MESH_TRIANGLE_STRIP; + + std::vector triangulatedIndices = + { + 0, 3, 1, + 3, 2, 1, + 1, 2, 4, + 2, 5, 4 + }; + + meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeTriangulatedIndices16(triangulatedIndices, meshPrimitive.mode, bufferBuilder); + + // Read back & check + Document doc; + bufferBuilder.Output(doc); + + GLTFResourceReader reader(readerWriter); + + const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); + Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_SHORT, accessor.componentType); + + auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); + + std::vector expectedIndices = + { + 0, 3, 1, 2, 4, 5 + }; + + AreEqual(expectedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices16_TriangleFan) + { + auto readerWriter = std::make_shared(); + auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + + bufferBuilder.AddBuffer(); + bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + + // Serialize + MeshPrimitive meshPrimitive; + meshPrimitive.mode = MESH_TRIANGLE_FAN; + + std::vector triangulatedIndices = + { + 5, 2, 0, + 5, 0, 1, + 5, 1, 4, + 5, 4, 3 + }; + + meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeTriangulatedIndices16(triangulatedIndices, meshPrimitive.mode, bufferBuilder); + + // Read back & check + Document doc; + bufferBuilder.Output(doc); + + GLTFResourceReader reader(readerWriter); + + const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); + Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_SHORT, accessor.componentType); + + auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); + + std::vector expectedIndices = + { + 5, 2, 0, 1, 4, 3 + }; + + AreEqual(expectedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices32_Triangles) + { + auto readerWriter = std::make_shared(); + auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + + bufferBuilder.AddBuffer(); + bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + + // Serialize + MeshPrimitive meshPrimitive; + meshPrimitive.mode = MESH_TRIANGLES; + + std::vector triangulatedIndices = + { + 0, 3, 1, + 3, 2, 1, + 1, 2, 4, + 2, 5, 4 + }; + + meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeTriangulatedIndices32(triangulatedIndices, meshPrimitive.mode, bufferBuilder); + + // Read back & check + Document doc; + bufferBuilder.Output(doc); + + GLTFResourceReader reader(readerWriter); + + const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); + Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_INT, accessor.componentType); + + auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); + + AreEqual(triangulatedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices32_TriangleStrip) + { + auto readerWriter = std::make_shared(); + auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + + bufferBuilder.AddBuffer(); + bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + + // Serialize + MeshPrimitive meshPrimitive; + meshPrimitive.mode = MESH_TRIANGLE_STRIP; + + std::vector triangulatedIndices = + { + 0, 3, 1, + 3, 2, 1, + 1, 2, 4, + 2, 5, 4 + }; + + meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeTriangulatedIndices32(triangulatedIndices, meshPrimitive.mode, bufferBuilder); + + // Read back & check + Document doc; + bufferBuilder.Output(doc); + + GLTFResourceReader reader(readerWriter); + + const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); + Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_INT, accessor.componentType); + + auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); + + std::vector expectedIndices = + { + 0, 3, 1, 2, 4, 5 + }; + + AreEqual(expectedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices32_TriangleFan) + { + auto readerWriter = std::make_shared(); + auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + + bufferBuilder.AddBuffer(); + bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + + // Serialize + MeshPrimitive meshPrimitive; + meshPrimitive.mode = MESH_TRIANGLE_FAN; + + std::vector triangulatedIndices = + { + 5, 2, 0, + 5, 0, 1, + 5, 1, 4, + 5, 4, 3 + }; + + meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeTriangulatedIndices32(triangulatedIndices, meshPrimitive.mode, bufferBuilder); + + // Read back & check + Document doc; + bufferBuilder.Output(doc); + + GLTFResourceReader reader(readerWriter); + + const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); + Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_INT, accessor.componentType); + + auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); + + std::vector expectedIndices = + { + 5, 2, 0, 1, 4, 3 + }; + + AreEqual(expectedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices16_Lines) + { + auto readerWriter = std::make_shared(); + auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + + bufferBuilder.AddBuffer(); + bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + + // Serialize + MeshPrimitive meshPrimitive; + meshPrimitive.mode = MESH_LINES; + + std::vector segmentedIndices = + { + 4, 2, + 2, 1, + 1, 3, + 3, 0 + }; + + meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeSegmentedIndices16(segmentedIndices, meshPrimitive.mode, bufferBuilder); + + // Read back & check + Document doc; + bufferBuilder.Output(doc); + + GLTFResourceReader reader(readerWriter); + + const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); + Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_SHORT, accessor.componentType); + + auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); + + AreEqual(segmentedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices16_LineStrip) + { + auto readerWriter = std::make_shared(); + auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + + bufferBuilder.AddBuffer(); + bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + + // Serialize + MeshPrimitive meshPrimitive; + meshPrimitive.mode = MESH_LINE_STRIP; + + std::vector segmentedIndices = + { + 4, 2, + 2, 1, + 1, 3, + 3, 0 + }; + + meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeSegmentedIndices16(segmentedIndices, meshPrimitive.mode, bufferBuilder); + + // Read back & check + Document doc; + bufferBuilder.Output(doc); + + GLTFResourceReader reader(readerWriter); + + const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); + Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_SHORT, accessor.componentType); + + auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); + + std::vector expectedIndices = + { + 4, 2, 1, 3, 0 + }; + + AreEqual(expectedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices16_LineLoop) + { + auto readerWriter = std::make_shared(); + auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + + bufferBuilder.AddBuffer(); + bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + + // Serialize + MeshPrimitive meshPrimitive; + meshPrimitive.mode = MESH_LINE_LOOP; + + std::vector segmentedIndices = + { + 4, 2, + 2, 1, + 1, 3, + 3, 0, + 0, 4 + }; + + meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeSegmentedIndices16(segmentedIndices, meshPrimitive.mode, bufferBuilder); + + // Read back & check + Document doc; + bufferBuilder.Output(doc); + + GLTFResourceReader reader(readerWriter); + + const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); + Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_SHORT, accessor.componentType); + + auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); + + std::vector expectedIndices = + { + 4, 2, 1, 3, 0 + }; + + AreEqual(expectedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices32_Lines) + { + auto readerWriter = std::make_shared(); + auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + + bufferBuilder.AddBuffer(); + bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + + // Serialize + MeshPrimitive meshPrimitive; + meshPrimitive.mode = MESH_LINES; + + std::vector segmentedIndices = + { + 4, 2, + 2, 1, + 1, 3, + 3, 0 + }; + + meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeSegmentedIndices32(segmentedIndices, meshPrimitive.mode, bufferBuilder); + + // Read back & check + Document doc; + bufferBuilder.Output(doc); + + GLTFResourceReader reader(readerWriter); + + const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); + Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_INT, accessor.componentType); + + auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); + + AreEqual(segmentedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices32_LineStrip) + { + auto readerWriter = std::make_shared(); + auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + + bufferBuilder.AddBuffer(); + bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + + // Serialize + MeshPrimitive meshPrimitive; + meshPrimitive.mode = MESH_LINE_STRIP; + + std::vector segmentedIndices = + { + 4, 2, + 2, 1, + 1, 3, + 3, 0 + }; + + meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeSegmentedIndices32(segmentedIndices, meshPrimitive.mode, bufferBuilder); + + // Read back & check + Document doc; + bufferBuilder.Output(doc); + + GLTFResourceReader reader(readerWriter); + + const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); + Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_INT, accessor.componentType); + + auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); + + std::vector expectedIndices = + { + 4, 2, 1, 3, 0 + }; + + AreEqual(expectedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices32_LineLoop) + { + auto readerWriter = std::make_shared(); + auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + + bufferBuilder.AddBuffer(); + bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + + // Serialize + MeshPrimitive meshPrimitive; + meshPrimitive.mode = MESH_LINE_LOOP; + + std::vector segmentedIndices = + { + 4, 2, + 2, 1, + 1, 3, + 3, 0, + 0, 4 + }; + + meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeSegmentedIndices32(segmentedIndices, meshPrimitive.mode, bufferBuilder); + + // Read back & check + Document doc; + bufferBuilder.Output(doc); + + GLTFResourceReader reader(readerWriter); + + const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); + Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_INT, accessor.componentType); + + auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); + + std::vector expectedIndices = + { + 4, 2, 1, 3, 0 + }; + + AreEqual(expectedIndices, outputIndices); + } + }; } } diff --git a/GLTFSDK/CMakeLists.txt b/GLTFSDK/CMakeLists.txt index e7df4d7..5f6492c 100644 --- a/GLTFSDK/CMakeLists.txt +++ b/GLTFSDK/CMakeLists.txt @@ -12,9 +12,16 @@ file(GLOB schema_deps "${CMAKE_CURRENT_LIST_DIR}/schema/*" ) +find_program(POWERSHELL + NAMES powershell pwsh) + +if(NOT POWERSHELL) + message(FATAL_ERROR "Powershell not found. Please make sure Powershell is installed and in PATH") +endif() + add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/GeneratedFiles/SchemaJson.h - COMMAND powershell -ExecutionPolicy Bypass "${CMAKE_CURRENT_LIST_DIR}/GenerateSchemaJsonHeader.ps1" -outPath "${CMAKE_BINARY_DIR}/GeneratedFiles" + COMMAND ${POWERSHELL} -ExecutionPolicy Bypass "${CMAKE_CURRENT_LIST_DIR}/GenerateSchemaJsonHeader.ps1" -outPath "${CMAKE_BINARY_DIR}/GeneratedFiles" WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} DEPENDS "${schema_deps}" ) diff --git a/GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h b/GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h index 15db670..05828a3 100644 --- a/GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h +++ b/GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h @@ -5,15 +5,15 @@ #include +#include + namespace Microsoft { namespace glTF { class Document; class GLTFResourceReader; - struct Accessor; - struct MeshPrimitive; - struct MorphTarget; + class BufferBuilder; namespace MeshPrimitiveUtils { @@ -57,6 +57,18 @@ namespace Microsoft std::vector GetJointWeights32(const Document& doc, const GLTFResourceReader& reader, const Accessor& accessor); std::vector GetJointWeights32_0(const Document& doc, const GLTFResourceReader& reader, const MeshPrimitive& meshPrimitive); + + std::string SerializeTriangulatedIndices16(const uint16_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder); + std::string SerializeTriangulatedIndices32(const uint32_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder); + + std::string SerializeTriangulatedIndices16(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder); + std::string SerializeTriangulatedIndices32(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder); + + std::string SerializeSegmentedIndices16(const uint16_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder); + std::string SerializeSegmentedIndices32(const uint32_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder); + + std::string SerializeSegmentedIndices16(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder); + std::string SerializeSegmentedIndices32(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder); }; } } diff --git a/GLTFSDK/Source/MeshPrimitiveUtils.cpp b/GLTFSDK/Source/MeshPrimitiveUtils.cpp index 85d45b4..1ed9163 100644 --- a/GLTFSDK/Source/MeshPrimitiveUtils.cpp +++ b/GLTFSDK/Source/MeshPrimitiveUtils.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -192,7 +193,7 @@ namespace { std::vector texcoordsFloat; texcoordsFloat.reserve(texcoords.size()); - for(size_t i = 0; i < texcoords.size(); i++) + for (size_t i = 0; i < texcoords.size(); i++) { texcoordsFloat.push_back(texcoords[i] / FLOAT_UINT8_MAX); } @@ -476,7 +477,7 @@ namespace if (doc.accessors.Has(meshPrimitive.indicesAccessorId)) { const auto& indicesAccessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - return Microsoft::glTF::MeshPrimitiveUtils::GetIndices16(doc, reader, indicesAccessor); + return MeshPrimitiveUtils::GetIndices16(doc, reader, indicesAccessor); } else { @@ -498,7 +499,7 @@ namespace if (doc.accessors.Has(meshPrimitive.indicesAccessorId)) { const auto& indicesAccessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - return Microsoft::glTF::MeshPrimitiveUtils::GetIndices32(doc, reader, indicesAccessor); + return MeshPrimitiveUtils::GetIndices32(doc, reader, indicesAccessor); } else { @@ -509,6 +510,149 @@ namespace return rawIndices; } } + + template + std::vector ReconstructTriangleStripIndexing(const T* indices, size_t indexCount) + { + if (indexCount % 3 != 0) + { + throw GLTFException("Input triangulated triangle strip has non-multiple-of-3 indices."); + } + + if (indexCount < 3) + { + throw GLTFException("Input triangulated triangle strip has fewer than 3 indices."); + } + + const size_t triangleCount = indexCount / 3; + const auto resultIndexCount = 2 + triangleCount; + std::vector result(resultIndexCount); + + result[0] = indices[0]; + result[1] = indices[1]; + result[2] = indices[2]; + + for (size_t i = 3; i < resultIndexCount; ++i) + { + if (i % 2 != 0) + { + result[i] = indices[3 * i - 5]; + } + else + { + result[i] = indices[3 * i - 4]; + } + } + + return result; + } + + template + std::vector ReconstructTriangleFanIndexing(const T* indices, size_t indexCount) + { + if (indexCount % 3 != 0) + { + throw GLTFException("Input triangulated triangle fan has non-multiple-of-3 indices."); + } + + if (indexCount < 3) + { + throw GLTFException("Input triangulated triangle fan has fewer than 3 indices."); + } + + const auto triangleCount = indexCount / 3; + const auto resultIndexCount = 2 + triangleCount; + std::vector result(resultIndexCount); + + result[0] = indices[0]; + result[1] = indices[1]; + result[2] = indices[2]; + + for (size_t i = 3; i < resultIndexCount; ++i) + { + result[i] = indices[3 * i - 4]; + } + + return result; + } + + template::value ? ComponentType::COMPONENT_UNSIGNED_SHORT : ComponentType::COMPONENT_UNSIGNED_INT> + std::string SerializeTriangulatedIndices(const T* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder) + { + static_assert(AccessorComponentType == ComponentType::COMPONENT_UNSIGNED_SHORT || AccessorComponentType == ComponentType::COMPONENT_UNSIGNED_INT, + "Unsupported value of AccessorComponentType used as a template argument for SerializeTriangulatedIndices"); + + bufferBuilder.AddBufferView(BufferViewTarget::ELEMENT_ARRAY_BUFFER); + + const auto accessorDesc = AccessorDesc(AccessorType::TYPE_SCALAR, AccessorComponentType); + + if (mode == MeshMode::MESH_TRIANGLE_STRIP) + { + auto reconstructedIndices = ReconstructTriangleStripIndexing(indices, indexCount); + return bufferBuilder.AddAccessor(reconstructedIndices.data(), reconstructedIndices.size(), accessorDesc).id; + } + else if (mode == MeshMode::MESH_TRIANGLE_FAN) + { + auto reconstructedIndices = ReconstructTriangleFanIndexing(indices, indexCount); + return bufferBuilder.AddAccessor(reconstructedIndices.data(), reconstructedIndices.size(), accessorDesc).id; + } + else + { + return bufferBuilder.AddAccessor(indices, indexCount, accessorDesc).id; + } + } + + template + std::vector ReconstructLineLoopIndexing(const T* indices, size_t indexCount) + { + if (indexCount % 2 != 0) + { + throw GLTFException("Input segmented line has non-multiple-of-2 indices."); + } + + const auto segmentCount = indexCount / 2; + std::vector result(segmentCount); + for (size_t i = 0; i < segmentCount; ++i) + { + result[i] = indices[2 * i]; + } + + return result; + } + + template + std::vector ReconstructLineStripIndexing(const T* indices, size_t indexCount) + { + auto result = ReconstructLineLoopIndexing(indices, indexCount); + result.push_back(indices[indexCount - 1]); + return result; + } + + template::value ? ComponentType::COMPONENT_UNSIGNED_SHORT : ComponentType::COMPONENT_UNSIGNED_INT> + std::string SerializeSegmentedIndices(const T* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder) + { + static_assert(AccessorComponentType == ComponentType::COMPONENT_UNSIGNED_SHORT || AccessorComponentType == ComponentType::COMPONENT_UNSIGNED_INT, + "Unsupported value of AccessorComponentType used as a template argument for SerializeSegmentedIndices"); + + bufferBuilder.AddBufferView(BufferViewTarget::ELEMENT_ARRAY_BUFFER); + + const auto accessorDesc = AccessorDesc(AccessorType::TYPE_SCALAR, AccessorComponentType); + + if (mode == MeshMode::MESH_LINE_STRIP) + { + auto reconstructedIndices = ReconstructLineStripIndexing(indices, indexCount); + return bufferBuilder.AddAccessor(reconstructedIndices.data(), reconstructedIndices.size(), accessorDesc).id; + } + else if (mode == MeshMode::MESH_LINE_LOOP) + { + auto reconstructedIndices = ReconstructLineLoopIndexing(indices, indexCount); + return bufferBuilder.AddAccessor(reconstructedIndices.data(), reconstructedIndices.size(), accessorDesc).id; + } + else + { + return bufferBuilder.AddAccessor(indices, indexCount, accessorDesc).id; + } + } } std::vector MeshPrimitiveUtils::GetIndices16(const Document& doc, const GLTFResourceReader& reader, const Accessor& accessor) @@ -828,3 +972,43 @@ std::vector MeshPrimitiveUtils::GetJointWeights32_0(const Document& do const auto& accessor = doc.accessors.Get(meshPrimitive.GetAttributeAccessorId(ACCESSOR_WEIGHTS_0)); return GetJointWeights32(doc, reader, accessor); } + +std::string MeshPrimitiveUtils::SerializeTriangulatedIndices16(const uint16_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder) +{ + return SerializeTriangulatedIndices(indices, indexCount, mode, bufferBuilder); +} + +std::string MeshPrimitiveUtils::SerializeTriangulatedIndices32(const uint32_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder) +{ + return SerializeTriangulatedIndices(indices, indexCount, mode, bufferBuilder); +} + +std::string MeshPrimitiveUtils::SerializeTriangulatedIndices16(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder) +{ + return SerializeTriangulatedIndices(indices.data(), indices.size(), mode, bufferBuilder); +} + +std::string MeshPrimitiveUtils::SerializeTriangulatedIndices32(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder) +{ + return SerializeTriangulatedIndices(indices.data(), indices.size(), mode, bufferBuilder); +} + +std::string MeshPrimitiveUtils::SerializeSegmentedIndices16(const uint16_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder) +{ + return SerializeSegmentedIndices(indices, indexCount, mode, bufferBuilder); +} + +std::string MeshPrimitiveUtils::SerializeSegmentedIndices32(const uint32_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder) +{ + return SerializeSegmentedIndices(indices, indexCount, mode, bufferBuilder); +} + +std::string MeshPrimitiveUtils::SerializeSegmentedIndices16(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder) +{ + return SerializeSegmentedIndices(indices.data(), indices.size(), mode, bufferBuilder); +} + +std::string MeshPrimitiveUtils::SerializeSegmentedIndices32(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder) +{ + return SerializeSegmentedIndices(indices.data(), indices.size(), mode, bufferBuilder); +} From 5b9d9949fd35d9b8b11d612ed5a98d91d66f1a04 Mon Sep 17 00:00:00 2001 From: Bart Siwek Date: Tue, 14 Aug 2018 14:16:14 +0200 Subject: [PATCH 2/5] Go back to using powershell directly. --- GLTFSDK/CMakeLists.txt | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/GLTFSDK/CMakeLists.txt b/GLTFSDK/CMakeLists.txt index 5f6492c..e7df4d7 100644 --- a/GLTFSDK/CMakeLists.txt +++ b/GLTFSDK/CMakeLists.txt @@ -12,16 +12,9 @@ file(GLOB schema_deps "${CMAKE_CURRENT_LIST_DIR}/schema/*" ) -find_program(POWERSHELL - NAMES powershell pwsh) - -if(NOT POWERSHELL) - message(FATAL_ERROR "Powershell not found. Please make sure Powershell is installed and in PATH") -endif() - add_custom_command( OUTPUT ${CMAKE_BINARY_DIR}/GeneratedFiles/SchemaJson.h - COMMAND ${POWERSHELL} -ExecutionPolicy Bypass "${CMAKE_CURRENT_LIST_DIR}/GenerateSchemaJsonHeader.ps1" -outPath "${CMAKE_BINARY_DIR}/GeneratedFiles" + COMMAND powershell -ExecutionPolicy Bypass "${CMAKE_CURRENT_LIST_DIR}/GenerateSchemaJsonHeader.ps1" -outPath "${CMAKE_BINARY_DIR}/GeneratedFiles" WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} DEPENDS "${schema_deps}" ) From a8ba8091fa2f975d7ac70713e8d1ffda0075882c Mon Sep 17 00:00:00 2001 From: Bart Siwek Date: Tue, 14 Aug 2018 14:19:50 +0200 Subject: [PATCH 3/5] Fix assert errors on windows --- .../Source/MeshPrimitiveUtilsTests.cpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/GLTFSDK.Test/Source/MeshPrimitiveUtilsTests.cpp b/GLTFSDK.Test/Source/MeshPrimitiveUtilsTests.cpp index 2bf5abe..1b02086 100644 --- a/GLTFSDK.Test/Source/MeshPrimitiveUtilsTests.cpp +++ b/GLTFSDK.Test/Source/MeshPrimitiveUtilsTests.cpp @@ -1353,7 +1353,7 @@ namespace Microsoft GLTFResourceReader reader(readerWriter); const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_SHORT, accessor.componentType); + Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_SHORT == accessor.componentType); auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); @@ -1389,7 +1389,7 @@ namespace Microsoft GLTFResourceReader reader(readerWriter); const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_SHORT, accessor.componentType); + Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_SHORT == accessor.componentType); auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); @@ -1430,7 +1430,7 @@ namespace Microsoft GLTFResourceReader reader(readerWriter); const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_SHORT, accessor.componentType); + Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_SHORT == accessor.componentType); auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); @@ -1471,7 +1471,7 @@ namespace Microsoft GLTFResourceReader reader(readerWriter); const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_INT, accessor.componentType); + Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_INT == accessor.componentType); auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); @@ -1507,7 +1507,7 @@ namespace Microsoft GLTFResourceReader reader(readerWriter); const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_INT, accessor.componentType); + Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_INT == accessor.componentType); auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); @@ -1548,7 +1548,7 @@ namespace Microsoft GLTFResourceReader reader(readerWriter); const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_INT, accessor.componentType); + Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_INT == accessor.componentType); auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); @@ -1589,7 +1589,7 @@ namespace Microsoft GLTFResourceReader reader(readerWriter); const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_SHORT, accessor.componentType); + Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_SHORT == accessor.componentType); auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); @@ -1625,7 +1625,7 @@ namespace Microsoft GLTFResourceReader reader(readerWriter); const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_SHORT, accessor.componentType); + Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_SHORT == accessor.componentType); auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); @@ -1667,7 +1667,7 @@ namespace Microsoft GLTFResourceReader reader(readerWriter); const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_SHORT, accessor.componentType); + Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_SHORT == accessor.componentType); auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); @@ -1708,7 +1708,7 @@ namespace Microsoft GLTFResourceReader reader(readerWriter); const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_INT, accessor.componentType); + Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_INT == accessor.componentType); auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); @@ -1744,7 +1744,7 @@ namespace Microsoft GLTFResourceReader reader(readerWriter); const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_INT, accessor.componentType); + Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_INT == accessor.componentType); auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); @@ -1786,7 +1786,7 @@ namespace Microsoft GLTFResourceReader reader(readerWriter); const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::AreEqual(ComponentType::COMPONENT_UNSIGNED_INT, accessor.componentType); + Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_INT == accessor.componentType); auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); From f094e775f2798804c737ec2530d3fcaa013a15a5 Mon Sep 17 00:00:00 2001 From: Bart Siwek Date: Wed, 15 Aug 2018 14:49:29 +0200 Subject: [PATCH 4/5] Requested changes --- .../Source/MeshPrimitiveUtilsTests.cpp | 457 +++++++----------- GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h | 16 +- GLTFSDK/Source/MeshPrimitiveUtils.cpp | 102 ++-- 3 files changed, 230 insertions(+), 345 deletions(-) diff --git a/GLTFSDK.Test/Source/MeshPrimitiveUtilsTests.cpp b/GLTFSDK.Test/Source/MeshPrimitiveUtilsTests.cpp index 1b02086..da1f724 100644 --- a/GLTFSDK.Test/Source/MeshPrimitiveUtilsTests.cpp +++ b/GLTFSDK.Test/Source/MeshPrimitiveUtilsTests.cpp @@ -1324,18 +1324,8 @@ namespace Microsoft Assert::AreEqual(outputIndices[262139], 0U); } - GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices16_Triangles) + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices16_TriangleStrip) { - auto readerWriter = std::make_shared(); - auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); - - bufferBuilder.AddBuffer(); - bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); - - // Serialize - MeshPrimitive meshPrimitive; - meshPrimitive.mode = MESH_TRIANGLES; - std::vector triangulatedIndices = { 0, 3, 1, @@ -1344,35 +1334,39 @@ namespace Microsoft 2, 5, 4 }; - meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeTriangulatedIndices16(triangulatedIndices, meshPrimitive.mode, bufferBuilder); + auto outputIndices = MeshPrimitiveUtils::ReverseTriangulateIndices16(triangulatedIndices, MESH_TRIANGLE_STRIP); - // Read back & check - Document doc; - bufferBuilder.Output(doc); - - GLTFResourceReader reader(readerWriter); - - const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_SHORT == accessor.componentType); - - auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); + std::vector expectedIndices = + { + 0, 3, 1, 2, 4, 5 + }; - AreEqual(triangulatedIndices, outputIndices); + AreEqual(expectedIndices, outputIndices); } - GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices16_TriangleStrip) + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices16_TriangleFan) { - auto readerWriter = std::make_shared(); - auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + std::vector triangulatedIndices = + { + 5, 2, 0, + 5, 0, 1, + 5, 1, 4, + 5, 4, 3 + }; - bufferBuilder.AddBuffer(); - bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + auto outputIndices = MeshPrimitiveUtils::ReverseTriangulateIndices16(triangulatedIndices, MESH_TRIANGLE_FAN); - // Serialize - MeshPrimitive meshPrimitive; - meshPrimitive.mode = MESH_TRIANGLE_STRIP; + std::vector expectedIndices = + { + 5, 2, 0, 1, 4, 3 + }; - std::vector triangulatedIndices = + AreEqual(expectedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices32_TriangleStrip) + { + std::vector triangulatedIndices = { 0, 3, 1, 3, 2, 1, @@ -1380,20 +1374,9 @@ namespace Microsoft 2, 5, 4 }; - meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeTriangulatedIndices16(triangulatedIndices, meshPrimitive.mode, bufferBuilder); - - // Read back & check - Document doc; - bufferBuilder.Output(doc); - - GLTFResourceReader reader(readerWriter); - - const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_SHORT == accessor.componentType); + auto outputIndices = MeshPrimitiveUtils::ReverseTriangulateIndices32(triangulatedIndices, MESH_TRIANGLE_STRIP); - auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); - - std::vector expectedIndices = + std::vector expectedIndices = { 0, 3, 1, 2, 4, 5 }; @@ -1401,19 +1384,9 @@ namespace Microsoft AreEqual(expectedIndices, outputIndices); } - GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices16_TriangleFan) + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices32_TriangleFan) { - auto readerWriter = std::make_shared(); - auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); - - bufferBuilder.AddBuffer(); - bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); - - // Serialize - MeshPrimitive meshPrimitive; - meshPrimitive.mode = MESH_TRIANGLE_FAN; - - std::vector triangulatedIndices = + std::vector triangulatedIndices = { 5, 2, 0, 5, 0, 1, @@ -1421,64 +1394,99 @@ namespace Microsoft 5, 4, 3 }; - meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeTriangulatedIndices16(triangulatedIndices, meshPrimitive.mode, bufferBuilder); + auto outputIndices = MeshPrimitiveUtils::ReverseTriangulateIndices32(triangulatedIndices, MESH_TRIANGLE_FAN); - // Read back & check - Document doc; - bufferBuilder.Output(doc); + std::vector expectedIndices = + { + 5, 2, 0, 1, 4, 3 + }; - GLTFResourceReader reader(readerWriter); + AreEqual(expectedIndices, outputIndices); + } - const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_SHORT == accessor.componentType); + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices16_LineStrip) + { + std::vector segmentedIndices = + { + 4, 2, + 2, 1, + 1, 3, + 3, 0 + }; - auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); + auto outputIndices = MeshPrimitiveUtils::ReverseSegmentIndices16(segmentedIndices, MESH_LINE_STRIP); std::vector expectedIndices = { - 5, 2, 0, 1, 4, 3 + 4, 2, 1, 3, 0 }; AreEqual(expectedIndices, outputIndices); } - GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices32_Triangles) + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices16_LineLoop) { - auto readerWriter = std::make_shared(); - auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); + std::vector segmentedIndices = + { + 4, 2, + 2, 1, + 1, 3, + 3, 0, + 0, 4 + }; - bufferBuilder.AddBuffer(); - bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); + auto outputIndices = MeshPrimitiveUtils::ReverseSegmentIndices16(segmentedIndices, MESH_LINE_LOOP); - // Serialize - MeshPrimitive meshPrimitive; - meshPrimitive.mode = MESH_TRIANGLES; + std::vector expectedIndices = + { + 4, 2, 1, 3, 0 + }; - std::vector triangulatedIndices = + AreEqual(expectedIndices, outputIndices); + } + + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices32_LineStrip) + { + std::vector segmentedIndices = { - 0, 3, 1, - 3, 2, 1, - 1, 2, 4, - 2, 5, 4 + 4, 2, + 2, 1, + 1, 3, + 3, 0 }; - meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeTriangulatedIndices32(triangulatedIndices, meshPrimitive.mode, bufferBuilder); + auto outputIndices = MeshPrimitiveUtils::ReverseSegmentIndices32(segmentedIndices, MESH_LINE_STRIP); - // Read back & check - Document doc; - bufferBuilder.Output(doc); + std::vector expectedIndices = + { + 4, 2, 1, 3, 0 + }; - GLTFResourceReader reader(readerWriter); + AreEqual(expectedIndices, outputIndices); + } - const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_INT == accessor.componentType); + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices32_LineLoop) + { + std::vector segmentedIndices = + { + 4, 2, + 2, 1, + 1, 3, + 3, 0, + 0, 4 + }; - auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); + auto outputIndices = MeshPrimitiveUtils::ReverseSegmentIndices32(segmentedIndices, MESH_LINE_LOOP); - AreEqual(triangulatedIndices, outputIndices); + std::vector expectedIndices = + { + 4, 2, 1, 3, 0 + }; + + AreEqual(expectedIndices, outputIndices); } - GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices32_TriangleStrip) + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_TriangulatedIndices16Roundtrip_TriangleStrip) { auto readerWriter = std::make_shared(); auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); @@ -1486,40 +1494,27 @@ namespace Microsoft bufferBuilder.AddBuffer(); bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); - // Serialize - MeshPrimitive meshPrimitive; - meshPrimitive.mode = MESH_TRIANGLE_STRIP; - - std::vector triangulatedIndices = - { - 0, 3, 1, - 3, 2, 1, - 1, 2, 4, - 2, 5, 4 + std::vector indices = { + 0U, 3U, 1U, 2U }; + auto indicesAccessor = bufferBuilder.AddAccessor(indices, { TYPE_SCALAR, COMPONENT_UNSIGNED_SHORT }); - meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeTriangulatedIndices32(triangulatedIndices, meshPrimitive.mode, bufferBuilder); - - // Read back & check Document doc; bufferBuilder.Output(doc); - GLTFResourceReader reader(readerWriter); - - const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_INT == accessor.componentType); + MeshPrimitive meshPrimitive; + meshPrimitive.indicesAccessorId = indicesAccessor.id; + meshPrimitive.mode = MESH_TRIANGLE_STRIP; - auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); + GLTFResourceReader reader(readerWriter); - std::vector expectedIndices = - { - 0, 3, 1, 2, 4, 5 - }; + auto triangulatedIndices = MeshPrimitiveUtils::GetTriangulatedIndices16(doc, reader, meshPrimitive); + auto outputIndices = MeshPrimitiveUtils::ReverseTriangulateIndices16(triangulatedIndices, meshPrimitive.mode); - AreEqual(expectedIndices, outputIndices); + AreEqual(outputIndices, indices); } - GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeTriangulatedIndices32_TriangleFan) + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_TriangulatedIndices16Roundtrip_TriangleFan) { auto readerWriter = std::make_shared(); auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); @@ -1527,40 +1522,27 @@ namespace Microsoft bufferBuilder.AddBuffer(); bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); - // Serialize - MeshPrimitive meshPrimitive; - meshPrimitive.mode = MESH_TRIANGLE_FAN; - - std::vector triangulatedIndices = - { - 5, 2, 0, - 5, 0, 1, - 5, 1, 4, - 5, 4, 3 + std::vector indices = { + 0U, 3U, 1U, 2U }; + auto indicesAccessor = bufferBuilder.AddAccessor(indices, { TYPE_SCALAR, COMPONENT_UNSIGNED_SHORT }); - meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeTriangulatedIndices32(triangulatedIndices, meshPrimitive.mode, bufferBuilder); - - // Read back & check Document doc; bufferBuilder.Output(doc); - GLTFResourceReader reader(readerWriter); - - const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_INT == accessor.componentType); + MeshPrimitive meshPrimitive; + meshPrimitive.indicesAccessorId = indicesAccessor.id; + meshPrimitive.mode = MESH_TRIANGLE_FAN; - auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); + GLTFResourceReader reader(readerWriter); - std::vector expectedIndices = - { - 5, 2, 0, 1, 4, 3 - }; + auto triangulatedIndices = MeshPrimitiveUtils::GetTriangulatedIndices16(doc, reader, meshPrimitive); + auto outputIndices = MeshPrimitiveUtils::ReverseTriangulateIndices16(triangulatedIndices, meshPrimitive.mode); - AreEqual(expectedIndices, outputIndices); + AreEqual(outputIndices, indices); } - GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices16_Lines) + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_TriangulatedIndices32Roundtrip_TriangleStrip) { auto readerWriter = std::make_shared(); auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); @@ -1568,35 +1550,27 @@ namespace Microsoft bufferBuilder.AddBuffer(); bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); - // Serialize - MeshPrimitive meshPrimitive; - meshPrimitive.mode = MESH_LINES; - - std::vector segmentedIndices = - { - 4, 2, - 2, 1, - 1, 3, - 3, 0 + std::vector indices = { + 0U, 3U, 1U, 2U }; + auto indicesAccessor = bufferBuilder.AddAccessor(indices, { TYPE_SCALAR, COMPONENT_UNSIGNED_INT }); - meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeSegmentedIndices16(segmentedIndices, meshPrimitive.mode, bufferBuilder); - - // Read back & check Document doc; bufferBuilder.Output(doc); - GLTFResourceReader reader(readerWriter); + MeshPrimitive meshPrimitive; + meshPrimitive.indicesAccessorId = indicesAccessor.id; + meshPrimitive.mode = MESH_TRIANGLE_STRIP; - const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_SHORT == accessor.componentType); + GLTFResourceReader reader(readerWriter); - auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); + auto triangulatedIndices = MeshPrimitiveUtils::GetTriangulatedIndices32(doc, reader, meshPrimitive); + auto outputIndices = MeshPrimitiveUtils::ReverseTriangulateIndices32(triangulatedIndices, meshPrimitive.mode); - AreEqual(segmentedIndices, outputIndices); + AreEqual(outputIndices, indices); } - GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices16_LineStrip) + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_TriangulatedIndices32Roundtrip_TriangleFan) { auto readerWriter = std::make_shared(); auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); @@ -1604,40 +1578,27 @@ namespace Microsoft bufferBuilder.AddBuffer(); bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); - // Serialize - MeshPrimitive meshPrimitive; - meshPrimitive.mode = MESH_LINE_STRIP; - - std::vector segmentedIndices = - { - 4, 2, - 2, 1, - 1, 3, - 3, 0 + std::vector indices = { + 0U, 3U, 1U, 2U }; + auto indicesAccessor = bufferBuilder.AddAccessor(indices, { TYPE_SCALAR, COMPONENT_UNSIGNED_INT }); - meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeSegmentedIndices16(segmentedIndices, meshPrimitive.mode, bufferBuilder); - - // Read back & check Document doc; bufferBuilder.Output(doc); - GLTFResourceReader reader(readerWriter); - - const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_SHORT == accessor.componentType); + MeshPrimitive meshPrimitive; + meshPrimitive.indicesAccessorId = indicesAccessor.id; + meshPrimitive.mode = MESH_TRIANGLE_FAN; - auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); + GLTFResourceReader reader(readerWriter); - std::vector expectedIndices = - { - 4, 2, 1, 3, 0 - }; + auto triangulatedIndices = MeshPrimitiveUtils::GetTriangulatedIndices32(doc, reader, meshPrimitive); + auto outputIndices = MeshPrimitiveUtils::ReverseTriangulateIndices32(triangulatedIndices, meshPrimitive.mode); - AreEqual(expectedIndices, outputIndices); + AreEqual(outputIndices, indices); } - GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices16_LineLoop) + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SegmentedIndices16Roundtrip_LineStrip) { auto readerWriter = std::make_shared(); auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); @@ -1645,41 +1606,27 @@ namespace Microsoft bufferBuilder.AddBuffer(); bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); - // Serialize - MeshPrimitive meshPrimitive; - meshPrimitive.mode = MESH_LINE_LOOP; - - std::vector segmentedIndices = - { - 4, 2, - 2, 1, - 1, 3, - 3, 0, - 0, 4 + std::vector indices = { + 0U, 3U, 1U, 2U }; + auto indicesAccessor = bufferBuilder.AddAccessor(indices, { TYPE_SCALAR, COMPONENT_UNSIGNED_SHORT }); - meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeSegmentedIndices16(segmentedIndices, meshPrimitive.mode, bufferBuilder); - - // Read back & check Document doc; bufferBuilder.Output(doc); - GLTFResourceReader reader(readerWriter); + MeshPrimitive meshPrimitive; + meshPrimitive.indicesAccessorId = indicesAccessor.id; + meshPrimitive.mode = MESH_LINE_STRIP; - const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_SHORT == accessor.componentType); + GLTFResourceReader reader(readerWriter); - auto outputIndices = MeshPrimitiveUtils::GetIndices16(doc, reader, meshPrimitive); + auto segmentedIndices = MeshPrimitiveUtils::GetSegmentedIndices16(doc, reader, meshPrimitive); + auto outputIndices = MeshPrimitiveUtils::ReverseSegmentIndices16(segmentedIndices, meshPrimitive.mode); - std::vector expectedIndices = - { - 4, 2, 1, 3, 0 - }; - - AreEqual(expectedIndices, outputIndices); + AreEqual(outputIndices, indices); } - GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices32_Lines) + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SegmentedIndices16Roundtrip_LineLoop) { auto readerWriter = std::make_shared(); auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); @@ -1687,35 +1634,27 @@ namespace Microsoft bufferBuilder.AddBuffer(); bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); - // Serialize - MeshPrimitive meshPrimitive; - meshPrimitive.mode = MESH_LINES; - - std::vector segmentedIndices = - { - 4, 2, - 2, 1, - 1, 3, - 3, 0 + std::vector indices = { + 0U, 3U, 1U, 2U }; + auto indicesAccessor = bufferBuilder.AddAccessor(indices, { TYPE_SCALAR, COMPONENT_UNSIGNED_SHORT }); - meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeSegmentedIndices32(segmentedIndices, meshPrimitive.mode, bufferBuilder); - - // Read back & check Document doc; bufferBuilder.Output(doc); - GLTFResourceReader reader(readerWriter); + MeshPrimitive meshPrimitive; + meshPrimitive.indicesAccessorId = indicesAccessor.id; + meshPrimitive.mode = MESH_LINE_LOOP; - const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_INT == accessor.componentType); + GLTFResourceReader reader(readerWriter); - auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); + auto segmentedIndices = MeshPrimitiveUtils::GetSegmentedIndices16(doc, reader, meshPrimitive); + auto outputIndices = MeshPrimitiveUtils::ReverseSegmentIndices16(segmentedIndices, meshPrimitive.mode); - AreEqual(segmentedIndices, outputIndices); + AreEqual(outputIndices, indices); } - GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices32_LineStrip) + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SegmentedIndices32Roundtrip_LineStrip) { auto readerWriter = std::make_shared(); auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); @@ -1723,40 +1662,27 @@ namespace Microsoft bufferBuilder.AddBuffer(); bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); - // Serialize - MeshPrimitive meshPrimitive; - meshPrimitive.mode = MESH_LINE_STRIP; - - std::vector segmentedIndices = - { - 4, 2, - 2, 1, - 1, 3, - 3, 0 + std::vector indices = { + 0U, 3U, 1U, 2U }; + auto indicesAccessor = bufferBuilder.AddAccessor(indices, { TYPE_SCALAR, COMPONENT_UNSIGNED_INT }); - meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeSegmentedIndices32(segmentedIndices, meshPrimitive.mode, bufferBuilder); - - // Read back & check Document doc; bufferBuilder.Output(doc); - GLTFResourceReader reader(readerWriter); + MeshPrimitive meshPrimitive; + meshPrimitive.indicesAccessorId = indicesAccessor.id; + meshPrimitive.mode = MESH_LINE_STRIP; - const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_INT == accessor.componentType); + GLTFResourceReader reader(readerWriter); - auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); + auto segmentedIndices = MeshPrimitiveUtils::GetSegmentedIndices32(doc, reader, meshPrimitive); + auto outputIndices = MeshPrimitiveUtils::ReverseSegmentIndices32(segmentedIndices, meshPrimitive.mode); - std::vector expectedIndices = - { - 4, 2, 1, 3, 0 - }; - - AreEqual(expectedIndices, outputIndices); + AreEqual(outputIndices, indices); } - GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SerializeSegmentedIndices32_LineLoop) + GLTFSDK_TEST_METHOD(MeshPrimitiveUtilsTests, MeshPrimitiveUtils_Test_SegmentedIndices32Roundtrip_LineLoop) { auto readerWriter = std::make_shared(); auto bufferBuilder = BufferBuilder(std::make_unique(readerWriter)); @@ -1764,40 +1690,25 @@ namespace Microsoft bufferBuilder.AddBuffer(); bufferBuilder.AddBufferView(BufferViewTarget::ARRAY_BUFFER); - // Serialize - MeshPrimitive meshPrimitive; - meshPrimitive.mode = MESH_LINE_LOOP; - - std::vector segmentedIndices = - { - 4, 2, - 2, 1, - 1, 3, - 3, 0, - 0, 4 + std::vector indices = { + 0U, 3U, 1U, 2U }; + auto indicesAccessor = bufferBuilder.AddAccessor(indices, { TYPE_SCALAR, COMPONENT_UNSIGNED_INT }); - meshPrimitive.indicesAccessorId = MeshPrimitiveUtils::SerializeSegmentedIndices32(segmentedIndices, meshPrimitive.mode, bufferBuilder); - - // Read back & check Document doc; bufferBuilder.Output(doc); - GLTFResourceReader reader(readerWriter); - - const auto& accessor = doc.accessors.Get(meshPrimitive.indicesAccessorId); - Assert::IsTrue(ComponentType::COMPONENT_UNSIGNED_INT == accessor.componentType); + MeshPrimitive meshPrimitive; + meshPrimitive.indicesAccessorId = indicesAccessor.id; + meshPrimitive.mode = MESH_LINE_LOOP; - auto outputIndices = MeshPrimitiveUtils::GetIndices32(doc, reader, meshPrimitive); + GLTFResourceReader reader(readerWriter); - std::vector expectedIndices = - { - 4, 2, 1, 3, 0 - }; + auto segmentedIndices = MeshPrimitiveUtils::GetSegmentedIndices32(doc, reader, meshPrimitive); + auto outputIndices = MeshPrimitiveUtils::ReverseSegmentIndices32(segmentedIndices, meshPrimitive.mode); - AreEqual(expectedIndices, outputIndices); + AreEqual(outputIndices, indices); } - }; } } diff --git a/GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h b/GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h index 05828a3..723dc69 100644 --- a/GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h +++ b/GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h @@ -58,17 +58,17 @@ namespace Microsoft std::vector GetJointWeights32(const Document& doc, const GLTFResourceReader& reader, const Accessor& accessor); std::vector GetJointWeights32_0(const Document& doc, const GLTFResourceReader& reader, const MeshPrimitive& meshPrimitive); - std::string SerializeTriangulatedIndices16(const uint16_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder); - std::string SerializeTriangulatedIndices32(const uint32_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder); + std::vector ReverseTriangulateIndices16(const uint16_t* indices, size_t indexCount, MeshMode mode); + std::vector ReverseTriangulateIndices32(const uint32_t* indices, size_t indexCount, MeshMode mode); - std::string SerializeTriangulatedIndices16(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder); - std::string SerializeTriangulatedIndices32(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder); + std::vector ReverseTriangulateIndices16(const std::vector& indices, MeshMode mode); + std::vector ReverseTriangulateIndices32(const std::vector& indices, MeshMode mode); - std::string SerializeSegmentedIndices16(const uint16_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder); - std::string SerializeSegmentedIndices32(const uint32_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder); + std::vector ReverseSegmentIndices16(const uint16_t* indices, size_t indexCount, MeshMode mode); + std::vector ReverseSegmentIndices32(const uint32_t* indices, size_t indexCount, MeshMode mode); - std::string SerializeSegmentedIndices16(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder); - std::string SerializeSegmentedIndices32(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder); + std::vector ReverseSegmentIndices16(const std::vector& indices, MeshMode mode); + std::vector ReverseSegmentIndices32(const std::vector& indices, MeshMode mode); }; } } diff --git a/GLTFSDK/Source/MeshPrimitiveUtils.cpp b/GLTFSDK/Source/MeshPrimitiveUtils.cpp index 1ed9163..c45e288 100644 --- a/GLTFSDK/Source/MeshPrimitiveUtils.cpp +++ b/GLTFSDK/Source/MeshPrimitiveUtils.cpp @@ -524,23 +524,19 @@ namespace throw GLTFException("Input triangulated triangle strip has fewer than 3 indices."); } - const size_t triangleCount = indexCount / 3; - const auto resultIndexCount = 2 + triangleCount; - std::vector result(resultIndexCount); + std::vector result; + result.push_back(indices[0]); + result.push_back(indices[1]); - result[0] = indices[0]; - result[1] = indices[1]; - result[2] = indices[2]; - - for (size_t i = 3; i < resultIndexCount; ++i) + for (size_t i = 2; i < indexCount; i += 3) { - if (i % 2 != 0) + if (i % 2 == 0) { - result[i] = indices[3 * i - 5]; + result.push_back(indices[i]); } else { - result[i] = indices[3 * i - 4]; + result.push_back(indices[i - 1]); } } @@ -560,45 +556,32 @@ namespace throw GLTFException("Input triangulated triangle fan has fewer than 3 indices."); } - const auto triangleCount = indexCount / 3; - const auto resultIndexCount = 2 + triangleCount; - std::vector result(resultIndexCount); - - result[0] = indices[0]; - result[1] = indices[1]; - result[2] = indices[2]; + std::vector result; + result.push_back(indices[0]); + result.push_back(indices[1]); - for (size_t i = 3; i < resultIndexCount; ++i) + for (size_t i = 2; i < indexCount; i += 3) { - result[i] = indices[3 * i - 4]; + result.push_back(indices[i]); } return result; } - template::value ? ComponentType::COMPONENT_UNSIGNED_SHORT : ComponentType::COMPONENT_UNSIGNED_INT> - std::string SerializeTriangulatedIndices(const T* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder) + template + std::vector ReverseTriangulateIndices(const T* indices, size_t indexCount, MeshMode mode) { - static_assert(AccessorComponentType == ComponentType::COMPONENT_UNSIGNED_SHORT || AccessorComponentType == ComponentType::COMPONENT_UNSIGNED_INT, - "Unsupported value of AccessorComponentType used as a template argument for SerializeTriangulatedIndices"); - - bufferBuilder.AddBufferView(BufferViewTarget::ELEMENT_ARRAY_BUFFER); - - const auto accessorDesc = AccessorDesc(AccessorType::TYPE_SCALAR, AccessorComponentType); - if (mode == MeshMode::MESH_TRIANGLE_STRIP) { - auto reconstructedIndices = ReconstructTriangleStripIndexing(indices, indexCount); - return bufferBuilder.AddAccessor(reconstructedIndices.data(), reconstructedIndices.size(), accessorDesc).id; + return ReconstructTriangleStripIndexing(indices, indexCount); } else if (mode == MeshMode::MESH_TRIANGLE_FAN) { - auto reconstructedIndices = ReconstructTriangleFanIndexing(indices, indexCount); - return bufferBuilder.AddAccessor(reconstructedIndices.data(), reconstructedIndices.size(), accessorDesc).id; + return ReconstructTriangleFanIndexing(indices, indexCount); } else { - return bufferBuilder.AddAccessor(indices, indexCount, accessorDesc).id; + throw GLTFException("Non-triangulated mesh mode specificed."); } } @@ -628,29 +611,20 @@ namespace return result; } - template::value ? ComponentType::COMPONENT_UNSIGNED_SHORT : ComponentType::COMPONENT_UNSIGNED_INT> - std::string SerializeSegmentedIndices(const T* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder) + template + std::vector ReverseSegmentIndices(const T* indices, size_t indexCount, MeshMode mode) { - static_assert(AccessorComponentType == ComponentType::COMPONENT_UNSIGNED_SHORT || AccessorComponentType == ComponentType::COMPONENT_UNSIGNED_INT, - "Unsupported value of AccessorComponentType used as a template argument for SerializeSegmentedIndices"); - - bufferBuilder.AddBufferView(BufferViewTarget::ELEMENT_ARRAY_BUFFER); - - const auto accessorDesc = AccessorDesc(AccessorType::TYPE_SCALAR, AccessorComponentType); - if (mode == MeshMode::MESH_LINE_STRIP) { - auto reconstructedIndices = ReconstructLineStripIndexing(indices, indexCount); - return bufferBuilder.AddAccessor(reconstructedIndices.data(), reconstructedIndices.size(), accessorDesc).id; + return ReconstructLineStripIndexing(indices, indexCount); } else if (mode == MeshMode::MESH_LINE_LOOP) { - auto reconstructedIndices = ReconstructLineLoopIndexing(indices, indexCount); - return bufferBuilder.AddAccessor(reconstructedIndices.data(), reconstructedIndices.size(), accessorDesc).id; + return ReconstructLineLoopIndexing(indices, indexCount); } else { - return bufferBuilder.AddAccessor(indices, indexCount, accessorDesc).id; + throw GLTFException("Non-segmented mesh mode specificed."); } } } @@ -973,42 +947,42 @@ std::vector MeshPrimitiveUtils::GetJointWeights32_0(const Document& do return GetJointWeights32(doc, reader, accessor); } -std::string MeshPrimitiveUtils::SerializeTriangulatedIndices16(const uint16_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder) +std::vector MeshPrimitiveUtils::ReverseTriangulateIndices16(const uint16_t* indices, size_t indexCount, MeshMode mode) { - return SerializeTriangulatedIndices(indices, indexCount, mode, bufferBuilder); + return ReverseTriangulateIndices(indices, indexCount, mode); } -std::string MeshPrimitiveUtils::SerializeTriangulatedIndices32(const uint32_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder) +std::vector MeshPrimitiveUtils::ReverseTriangulateIndices32(const uint32_t* indices, size_t indexCount, MeshMode mode) { - return SerializeTriangulatedIndices(indices, indexCount, mode, bufferBuilder); + return ReverseTriangulateIndices(indices, indexCount, mode); } -std::string MeshPrimitiveUtils::SerializeTriangulatedIndices16(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder) +std::vector MeshPrimitiveUtils::ReverseTriangulateIndices16(const std::vector& indices, MeshMode mode) { - return SerializeTriangulatedIndices(indices.data(), indices.size(), mode, bufferBuilder); + return ReverseTriangulateIndices(indices.data(), indices.size(), mode); } -std::string MeshPrimitiveUtils::SerializeTriangulatedIndices32(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder) +std::vector MeshPrimitiveUtils::ReverseTriangulateIndices32(const std::vector& indices, MeshMode mode) { - return SerializeTriangulatedIndices(indices.data(), indices.size(), mode, bufferBuilder); + return ReverseTriangulateIndices(indices.data(), indices.size(), mode); } -std::string MeshPrimitiveUtils::SerializeSegmentedIndices16(const uint16_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder) +std::vector MeshPrimitiveUtils::ReverseSegmentIndices16(const uint16_t* indices, size_t indexCount, MeshMode mode) { - return SerializeSegmentedIndices(indices, indexCount, mode, bufferBuilder); + return ReverseSegmentIndices(indices, indexCount, mode); } -std::string MeshPrimitiveUtils::SerializeSegmentedIndices32(const uint32_t* indices, size_t indexCount, MeshMode mode, BufferBuilder& bufferBuilder) +std::vector MeshPrimitiveUtils::ReverseSegmentIndices32(const uint32_t* indices, size_t indexCount, MeshMode mode) { - return SerializeSegmentedIndices(indices, indexCount, mode, bufferBuilder); + return ReverseSegmentIndices(indices, indexCount, mode); } -std::string MeshPrimitiveUtils::SerializeSegmentedIndices16(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder) +std::vector MeshPrimitiveUtils::ReverseSegmentIndices16(const std::vector& indices, MeshMode mode) { - return SerializeSegmentedIndices(indices.data(), indices.size(), mode, bufferBuilder); + return ReverseSegmentIndices(indices.data(), indices.size(), mode); } -std::string MeshPrimitiveUtils::SerializeSegmentedIndices32(const std::vector& indices, MeshMode mode, BufferBuilder& bufferBuilder) +std::vector MeshPrimitiveUtils::ReverseSegmentIndices32(const std::vector& indices, MeshMode mode) { - return SerializeSegmentedIndices(indices.data(), indices.size(), mode, bufferBuilder); + return ReverseSegmentIndices(indices.data(), indices.size(), mode); } From abc483fa7f6251f7f7ad81179ac73f29711f0d2d Mon Sep 17 00:00:00 2001 From: Bart Siwek Date: Thu, 16 Aug 2018 13:34:55 +0200 Subject: [PATCH 5/5] More requested changes. --- GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h | 1 - GLTFSDK/Source/MeshPrimitiveUtils.cpp | 13 +++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h b/GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h index 723dc69..7b518b8 100644 --- a/GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h +++ b/GLTFSDK/Inc/GLTFSDK/MeshPrimitiveUtils.h @@ -13,7 +13,6 @@ namespace Microsoft { class Document; class GLTFResourceReader; - class BufferBuilder; namespace MeshPrimitiveUtils { diff --git a/GLTFSDK/Source/MeshPrimitiveUtils.cpp b/GLTFSDK/Source/MeshPrimitiveUtils.cpp index c45e288..fb40d24 100644 --- a/GLTFSDK/Source/MeshPrimitiveUtils.cpp +++ b/GLTFSDK/Source/MeshPrimitiveUtils.cpp @@ -525,6 +525,8 @@ namespace } std::vector result; + result.reserve(2 + indexCount / 3); + result.push_back(indices[0]); result.push_back(indices[1]); @@ -557,6 +559,8 @@ namespace } std::vector result; + result.reserve(2 + indexCount / 3); + result.push_back(indices[0]); result.push_back(indices[1]); @@ -593,11 +597,12 @@ namespace throw GLTFException("Input segmented line has non-multiple-of-2 indices."); } - const auto segmentCount = indexCount / 2; - std::vector result(segmentCount); - for (size_t i = 0; i < segmentCount; ++i) + std::vector result; + result.reserve(indexCount / 2); + + for (size_t i = 0; i < indexCount; i += 2) { - result[i] = indices[2 * i]; + result.push_back(indices[i]); } return result;