Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new function in MeshManager to merge all submeshes of a mesh into one #588

Merged
merged 2 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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));
mjcarroll marked this conversation as resolved.
Show resolved Hide resolved

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 @@ -1759,3 +1760,72 @@ MeshManager::ConvexDecomposition(const SubMesh &_subMesh,

return decomposed;
}

//////////////////////////////////////////////////
std::unique_ptr<Mesh> MeshManager::MergeSubMeshes(const Mesh &_mesh)
iche033 marked this conversation as resolved.
Show resolved Hide resolved
{
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
Loading