Skip to content

Commit

Permalink
Add new function in MeshManager to merge all submeshes of a mesh into…
Browse files Browse the repository at this point in the history
… one (#588)



---------

Signed-off-by: Ian Chen <[email protected]>
  • Loading branch information
iche033 committed Apr 8, 2024
1 parent e213c2b commit cd159c2
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 5 deletions.
8 changes: 7 additions & 1 deletion graphics/include/gz/common/MeshManager.hh
Original file line number Diff line number Diff line change
Expand Up @@ -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<SubMesh> ConvexDecomposition(
public: static std::vector<SubMesh> 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<Mesh> 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
Expand Down
2 changes: 0 additions & 2 deletions graphics/src/ColladaLoader_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
70 changes: 70 additions & 0 deletions graphics/src/MeshManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <cctype>
#include <cstdint>
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>
Expand Down Expand Up @@ -1760,3 +1761,72 @@ MeshManager::ConvexDecomposition(const SubMesh &_subMesh,

return decomposed;
}

//////////////////////////////////////////////////
std::unique_ptr<Mesh> 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 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>();
mesh->SetName(_mesh.Name() + "_merged");
mergedSubMesh.SetName(mesh->Name() + "_submesh");
mesh->AddSubMesh(mergedSubMesh);

return mesh;
}
93 changes: 91 additions & 2 deletions graphics/src/MeshManager_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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

0 comments on commit cd159c2

Please sign in to comment.