From 8900a07166c5e0dba6907bba453ef7a3c059219d Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Tue, 26 Mar 2024 02:59:27 +0000 Subject: [PATCH 1/2] add function to merge submeshes Signed-off-by: Ian Chen --- graphics/include/gz/common/MeshManager.hh | 8 +- graphics/src/ColladaLoader_TEST.cc | 2 - graphics/src/MeshManager.cc | 69 +++++++++++++++++ graphics/src/MeshManager_TEST.cc | 93 ++++++++++++++++++++++- 4 files changed, 167 insertions(+), 5 deletions(-) diff --git a/graphics/include/gz/common/MeshManager.hh b/graphics/include/gz/common/MeshManager.hh index 61b19f3e..4b7873f8 100644 --- a/graphics/include/gz/common/MeshManager.hh +++ b/graphics/include/gz/common/MeshManager.hh @@ -290,11 +290,17 @@ namespace gz /// \param[in] _voxelResolution Voxel resolution to use. Higher value /// produces more accurate shapes. /// \return A vector of decomposed submeshes. - public: std::vector ConvexDecomposition( + public: static std::vector ConvexDecomposition( const common::SubMesh &_subMesh, std::size_t _maxConvexHulls = 16u, std::size_t _voxelResolution = 200000u); + /// \brief Merge all submeshes from one mesh into one single submesh. + /// \param[in] _mesh Input mesh with submeshes to merge. + /// \return A new mesh with the submeshes merged. + public: static std::unique_ptr MergeSubMeshes( + const common::Mesh &_mesh); + /// \brief Converts a vector of polylines into a table of vertices and /// a list of edges (each made of 2 points from the table of vertices. /// \param[in] _polys the polylines diff --git a/graphics/src/ColladaLoader_TEST.cc b/graphics/src/ColladaLoader_TEST.cc index 87540999..754f913d 100644 --- a/graphics/src/ColladaLoader_TEST.cc +++ b/graphics/src/ColladaLoader_TEST.cc @@ -242,8 +242,6 @@ TEST_F(ColladaLoader, TexCoordSets) EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(0u, 0u)); EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(1u, 0u)); EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(2u, 0u)); - EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(1u, 0u)); - EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(2u, 0u)); EXPECT_TRUE(subMeshB->HasTexCoordBySet(0u, 0u)); EXPECT_TRUE(subMeshB->HasTexCoordBySet(1u, 0u)); diff --git a/graphics/src/MeshManager.cc b/graphics/src/MeshManager.cc index c35c5dae..cfba26e7 100644 --- a/graphics/src/MeshManager.cc +++ b/graphics/src/MeshManager.cc @@ -1759,3 +1759,72 @@ MeshManager::ConvexDecomposition(const SubMesh &_subMesh, return decomposed; } + +////////////////////////////////////////////////// +std::unique_ptr MeshManager::MergeSubMeshes(const Mesh &_mesh) +{ + SubMesh mergedSubMesh; + + // The final merged submesh should contain all the texcoord sets + // in the original submeshes. Determine the max texcoord sets we need. + unsigned int maxTexCoordSet = 0u; + for (unsigned int i = 0u; i < _mesh.SubMeshCount(); ++i) + { + auto submesh = _mesh.SubMeshByIndex(i).lock(); + maxTexCoordSet = (maxTexCoordSet > submesh->TexCoordSetCount()) ? + maxTexCoordSet : submesh->TexCoordSetCount(); + } + + unsigned int indexOffset = 0u; + for (unsigned int i = 0u; i < _mesh.SubMeshCount(); ++i) + { + auto submesh = _mesh.SubMeshByIndex(i).lock(); + // vertices + for (unsigned int j = 0; j < submesh->VertexCount(); ++j) + { + mergedSubMesh.AddVertex(submesh->Vertex(j)); + } + + // normals + for (unsigned int j = 0; j < submesh->NormalCount(); ++j) + { + mergedSubMesh.AddNormal(submesh->Normal(j)); + } + + // indices - the index needs to start at an offset for each new submesh + for (unsigned int j = 0; j < submesh->IndexCount(); ++j) + { + mergedSubMesh.AddIndex(submesh->Index(j) + indexOffset); + } + indexOffset += submesh->VertexCount(); + + // texcoords + for (unsigned int j = 0; j < maxTexCoordSet; ++j) + { + if (j < submesh->TexCoordSetCount()) + { + // Populate texcoords from input submesh + for (unsigned int k = 0; k < submesh->TexCoordCountBySet(j); ++k) + { + mergedSubMesh.AddTexCoordBySet(submesh->TexCoordBySet(k, j), j); + } + } + else + { + // Set texcoord to zero if it the input submesh does not have that many + // texcoord sets. Note the texcoord count should be the same as vertex + // count. + for (unsigned int k = 0; k < submesh->VertexCount(); ++k) + { + mergedSubMesh.AddTexCoordBySet(math::Vector2d::Zero, j); + } + } + } + } + auto mesh = std::make_unique(); + mesh->SetName(_mesh.Name() + "_merged"); + mergedSubMesh.SetName(mesh->Name() + "_submesh"); + mesh->AddSubMesh(mergedSubMesh); + + return mesh; +} diff --git a/graphics/src/MeshManager_TEST.cc b/graphics/src/MeshManager_TEST.cc index 568e0661..dd7f8acb 100644 --- a/graphics/src/MeshManager_TEST.cc +++ b/graphics/src/MeshManager_TEST.cc @@ -304,7 +304,7 @@ TEST_F(MeshManager, ConvexDecomposition) std::size_t maxConvexHulls = 4; std::size_t resolution = 1000; auto submesh = boxMesh->SubMeshByIndex(0u).lock(); - auto decomposed = std::move(mgr->ConvexDecomposition( + auto decomposed = std::move(common::MeshManager::ConvexDecomposition( *(submesh.get()), maxConvexHulls, resolution)); // Decomposing a box should just produce a box @@ -321,7 +321,7 @@ TEST_F(MeshManager, ConvexDecomposition) ASSERT_NE(nullptr, drillMesh); EXPECT_EQ(1u, drillMesh->SubMeshCount()); submesh = drillMesh->SubMeshByIndex(0u).lock(); - decomposed = std::move(mgr->ConvexDecomposition( + decomposed = std::move(common::MeshManager::ConvexDecomposition( *(submesh.get()), maxConvexHulls, resolution)); // A drill should be decomposed into multiple submeshes @@ -337,4 +337,93 @@ TEST_F(MeshManager, ConvexDecomposition) } } +///////////////////////////////////////////////// +TEST_F(MeshManager, MergeSubMeshes) +{ + auto mgr = common::MeshManager::Instance(); + const common::Mesh *mesh = mgr->Load( + common::testing::TestFile("data", + "multiple_texture_coordinates_triangle.dae")); + ASSERT_NE(nullptr, mesh); + EXPECT_EQ(2u, mesh->SubMeshCount()); + auto submesh = mesh->SubMeshByIndex(0u).lock(); + ASSERT_NE(nullptr, submesh); + EXPECT_EQ(3u, submesh->VertexCount()); + EXPECT_EQ(3u, submesh->NormalCount()); + EXPECT_EQ(3u, submesh->IndexCount()); + EXPECT_EQ(2u, submesh->TexCoordSetCount()); + EXPECT_EQ(3u, submesh->TexCoordCountBySet(0)); + EXPECT_EQ(3u, submesh->TexCoordCountBySet(1)); + auto submeshB = mesh->SubMeshByIndex(1u).lock(); + ASSERT_NE(nullptr, submeshB); + EXPECT_EQ(3u, submeshB->VertexCount()); + EXPECT_EQ(3u, submeshB->NormalCount()); + EXPECT_EQ(3u, submeshB->IndexCount()); + EXPECT_EQ(3u, submeshB->TexCoordSetCount()); + EXPECT_EQ(3u, submeshB->TexCoordCountBySet(0)); + EXPECT_EQ(3u, submeshB->TexCoordCountBySet(1)); + EXPECT_EQ(3u, submeshB->TexCoordCountBySet(2)); + + // merge all submeshes into one + auto merged = common::MeshManager::MergeSubMeshes(*mesh); + ASSERT_NE(nullptr, merged); + EXPECT_FALSE(merged->Name().empty()); + EXPECT_EQ(1u, merged->SubMeshCount()); + auto mergedSubmesh = merged->SubMeshByIndex(0u).lock(); + ASSERT_NE(nullptr, mergedSubmesh); + EXPECT_FALSE(mergedSubmesh->Name().empty()); + + // Verify vertice, normals, indice, and texcoord values in the + // final merged submesh + EXPECT_EQ(6u, mergedSubmesh->VertexCount()); + EXPECT_EQ(6u, mergedSubmesh->NormalCount()); + EXPECT_EQ(6u, mergedSubmesh->IndexCount()); + EXPECT_EQ(3u, mergedSubmesh->TexCoordSetCount()); + EXPECT_EQ(6u, mergedSubmesh->TexCoordCountBySet(0)); + EXPECT_EQ(6u, mergedSubmesh->TexCoordCountBySet(1)); + EXPECT_EQ(6u, mergedSubmesh->TexCoordCountBySet(2)); + + EXPECT_EQ(math::Vector3d(0, 0, 0), mergedSubmesh->Vertex(0u)); + EXPECT_EQ(math::Vector3d(10, 0, 0), mergedSubmesh->Vertex(1u)); + EXPECT_EQ(math::Vector3d(10, 10, 0), mergedSubmesh->Vertex(2u)); + EXPECT_EQ(math::Vector3d(10, 0, 0), mergedSubmesh->Vertex(3u)); + EXPECT_EQ(math::Vector3d(20, 0, 0), mergedSubmesh->Vertex(4u)); + EXPECT_EQ(math::Vector3d(20, 10, 0), mergedSubmesh->Vertex(5u)); + + EXPECT_EQ(math::Vector3d(0, 0, 1), mergedSubmesh->Normal(0u)); + EXPECT_EQ(math::Vector3d(0, 0, 1), mergedSubmesh->Normal(1u)); + EXPECT_EQ(math::Vector3d(0, 0, 1), mergedSubmesh->Normal(2u)); + EXPECT_EQ(math::Vector3d(0, 0, 1), mergedSubmesh->Normal(3u)); + EXPECT_EQ(math::Vector3d(0, 0, 1), mergedSubmesh->Normal(4u)); + EXPECT_EQ(math::Vector3d(0, 0, 1), mergedSubmesh->Normal(5u)); + + EXPECT_EQ(0u, mergedSubmesh->Index(0u)); + EXPECT_EQ(1u, mergedSubmesh->Index(1u)); + EXPECT_EQ(2u, mergedSubmesh->Index(2u)); + EXPECT_EQ(3u, mergedSubmesh->Index(3u)); + EXPECT_EQ(4u, mergedSubmesh->Index(4u)); + EXPECT_EQ(5u, mergedSubmesh->Index(5u)); + + EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(0u, 0u)); + EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(1u, 0u)); + EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(2u, 0u)); + EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(3u, 0u)); + EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(4u, 0u)); + EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(5u, 0u)); + + EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(0u, 1u)); + EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(1u, 1u)); + EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(2u, 1u)); + EXPECT_EQ(math::Vector2d(0, 0.5), mergedSubmesh->TexCoordBySet(3u, 1u)); + EXPECT_EQ(math::Vector2d(0, 0.4), mergedSubmesh->TexCoordBySet(4u, 1u)); + EXPECT_EQ(math::Vector2d(0, 0.3), mergedSubmesh->TexCoordBySet(5u, 1u)); + + EXPECT_EQ(math::Vector2d(0, 0), mergedSubmesh->TexCoordBySet(0u, 2u)); + EXPECT_EQ(math::Vector2d(0, 0), mergedSubmesh->TexCoordBySet(1u, 2u)); + EXPECT_EQ(math::Vector2d(0, 0), mergedSubmesh->TexCoordBySet(2u, 2u)); + EXPECT_EQ(math::Vector2d(0, 0.8), mergedSubmesh->TexCoordBySet(3u, 2u)); + EXPECT_EQ(math::Vector2d(0, 0.7), mergedSubmesh->TexCoordBySet(4u, 2u)); + EXPECT_EQ(math::Vector2d(0, 0.6), mergedSubmesh->TexCoordBySet(5u, 2u)); +} + #endif From 943ecb2f69ba16c5e5619a1469a40ca7dc70a5cb Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Tue, 26 Mar 2024 17:09:51 +0000 Subject: [PATCH 2/2] add include Signed-off-by: Ian Chen --- graphics/src/MeshManager.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graphics/src/MeshManager.cc b/graphics/src/MeshManager.cc index cfba26e7..bb6173e4 100644 --- a/graphics/src/MeshManager.cc +++ b/graphics/src/MeshManager.cc @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -1811,7 +1812,7 @@ std::unique_ptr MeshManager::MergeSubMeshes(const Mesh &_mesh) } else { - // Set texcoord to zero if it the input submesh does not have that many + // Set texcoord to zero if the input submesh does not have that many // texcoord sets. Note the texcoord count should be the same as vertex // count. for (unsigned int k = 0; k < submesh->VertexCount(); ++k)