Skip to content

Commit cd159c2

Browse files
committed
Add new function in MeshManager to merge all submeshes of a mesh into one (#588)
--------- Signed-off-by: Ian Chen <[email protected]>
1 parent e213c2b commit cd159c2

File tree

4 files changed

+168
-5
lines changed

4 files changed

+168
-5
lines changed

graphics/include/gz/common/MeshManager.hh

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,11 +290,17 @@ namespace gz
290290
/// \param[in] _voxelResolution Voxel resolution to use. Higher value
291291
/// produces more accurate shapes.
292292
/// \return A vector of decomposed submeshes.
293-
public: std::vector<SubMesh> ConvexDecomposition(
293+
public: static std::vector<SubMesh> ConvexDecomposition(
294294
const common::SubMesh &_subMesh,
295295
std::size_t _maxConvexHulls = 16u,
296296
std::size_t _voxelResolution = 200000u);
297297

298+
/// \brief Merge all submeshes from one mesh into one single submesh.
299+
/// \param[in] _mesh Input mesh with submeshes to merge.
300+
/// \return A new mesh with the submeshes merged.
301+
public: static std::unique_ptr<Mesh> MergeSubMeshes(
302+
const common::Mesh &_mesh);
303+
298304
/// \brief Converts a vector of polylines into a table of vertices and
299305
/// a list of edges (each made of 2 points from the table of vertices.
300306
/// \param[in] _polys the polylines

graphics/src/ColladaLoader_TEST.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,6 @@ TEST_F(ColladaLoader, TexCoordSets)
242242
EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(0u, 0u));
243243
EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(1u, 0u));
244244
EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(2u, 0u));
245-
EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(1u, 0u));
246-
EXPECT_EQ(math::Vector2d(0, 1), subMeshB->TexCoordBySet(2u, 0u));
247245

248246
EXPECT_TRUE(subMeshB->HasTexCoordBySet(0u, 0u));
249247
EXPECT_TRUE(subMeshB->HasTexCoordBySet(1u, 0u));

graphics/src/MeshManager.cc

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <cctype>
2121
#include <cstdint>
22+
#include <memory>
2223
#include <mutex>
2324
#include <string>
2425
#include <unordered_map>
@@ -1760,3 +1761,72 @@ MeshManager::ConvexDecomposition(const SubMesh &_subMesh,
17601761

17611762
return decomposed;
17621763
}
1764+
1765+
//////////////////////////////////////////////////
1766+
std::unique_ptr<Mesh> MeshManager::MergeSubMeshes(const Mesh &_mesh)
1767+
{
1768+
SubMesh mergedSubMesh;
1769+
1770+
// The final merged submesh should contain all the texcoord sets
1771+
// in the original submeshes. Determine the max texcoord sets we need.
1772+
unsigned int maxTexCoordSet = 0u;
1773+
for (unsigned int i = 0u; i < _mesh.SubMeshCount(); ++i)
1774+
{
1775+
auto submesh = _mesh.SubMeshByIndex(i).lock();
1776+
maxTexCoordSet = (maxTexCoordSet > submesh->TexCoordSetCount()) ?
1777+
maxTexCoordSet : submesh->TexCoordSetCount();
1778+
}
1779+
1780+
unsigned int indexOffset = 0u;
1781+
for (unsigned int i = 0u; i < _mesh.SubMeshCount(); ++i)
1782+
{
1783+
auto submesh = _mesh.SubMeshByIndex(i).lock();
1784+
// vertices
1785+
for (unsigned int j = 0; j < submesh->VertexCount(); ++j)
1786+
{
1787+
mergedSubMesh.AddVertex(submesh->Vertex(j));
1788+
}
1789+
1790+
// normals
1791+
for (unsigned int j = 0; j < submesh->NormalCount(); ++j)
1792+
{
1793+
mergedSubMesh.AddNormal(submesh->Normal(j));
1794+
}
1795+
1796+
// indices - the index needs to start at an offset for each new submesh
1797+
for (unsigned int j = 0; j < submesh->IndexCount(); ++j)
1798+
{
1799+
mergedSubMesh.AddIndex(submesh->Index(j) + indexOffset);
1800+
}
1801+
indexOffset += submesh->VertexCount();
1802+
1803+
// texcoords
1804+
for (unsigned int j = 0; j < maxTexCoordSet; ++j)
1805+
{
1806+
if (j < submesh->TexCoordSetCount())
1807+
{
1808+
// Populate texcoords from input submesh
1809+
for (unsigned int k = 0; k < submesh->TexCoordCountBySet(j); ++k)
1810+
{
1811+
mergedSubMesh.AddTexCoordBySet(submesh->TexCoordBySet(k, j), j);
1812+
}
1813+
}
1814+
else
1815+
{
1816+
// Set texcoord to zero if the input submesh does not have that many
1817+
// texcoord sets. Note the texcoord count should be the same as vertex
1818+
// count.
1819+
for (unsigned int k = 0; k < submesh->VertexCount(); ++k)
1820+
{
1821+
mergedSubMesh.AddTexCoordBySet(math::Vector2d::Zero, j);
1822+
}
1823+
}
1824+
}
1825+
}
1826+
auto mesh = std::make_unique<Mesh>();
1827+
mesh->SetName(_mesh.Name() + "_merged");
1828+
mergedSubMesh.SetName(mesh->Name() + "_submesh");
1829+
mesh->AddSubMesh(mergedSubMesh);
1830+
1831+
return mesh;
1832+
}

graphics/src/MeshManager_TEST.cc

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@ TEST_F(MeshManager, ConvexDecomposition)
304304
std::size_t maxConvexHulls = 4;
305305
std::size_t resolution = 1000;
306306
auto submesh = boxMesh->SubMeshByIndex(0u).lock();
307-
auto decomposed = std::move(mgr->ConvexDecomposition(
307+
auto decomposed = std::move(common::MeshManager::ConvexDecomposition(
308308
*(submesh.get()), maxConvexHulls, resolution));
309309

310310
// Decomposing a box should just produce a box
@@ -321,7 +321,7 @@ TEST_F(MeshManager, ConvexDecomposition)
321321
ASSERT_NE(nullptr, drillMesh);
322322
EXPECT_EQ(1u, drillMesh->SubMeshCount());
323323
submesh = drillMesh->SubMeshByIndex(0u).lock();
324-
decomposed = std::move(mgr->ConvexDecomposition(
324+
decomposed = std::move(common::MeshManager::ConvexDecomposition(
325325
*(submesh.get()), maxConvexHulls, resolution));
326326

327327
// A drill should be decomposed into multiple submeshes
@@ -337,4 +337,93 @@ TEST_F(MeshManager, ConvexDecomposition)
337337
}
338338
}
339339

340+
/////////////////////////////////////////////////
341+
TEST_F(MeshManager, MergeSubMeshes)
342+
{
343+
auto mgr = common::MeshManager::Instance();
344+
const common::Mesh *mesh = mgr->Load(
345+
common::testing::TestFile("data",
346+
"multiple_texture_coordinates_triangle.dae"));
347+
ASSERT_NE(nullptr, mesh);
348+
EXPECT_EQ(2u, mesh->SubMeshCount());
349+
auto submesh = mesh->SubMeshByIndex(0u).lock();
350+
ASSERT_NE(nullptr, submesh);
351+
EXPECT_EQ(3u, submesh->VertexCount());
352+
EXPECT_EQ(3u, submesh->NormalCount());
353+
EXPECT_EQ(3u, submesh->IndexCount());
354+
EXPECT_EQ(2u, submesh->TexCoordSetCount());
355+
EXPECT_EQ(3u, submesh->TexCoordCountBySet(0));
356+
EXPECT_EQ(3u, submesh->TexCoordCountBySet(1));
357+
auto submeshB = mesh->SubMeshByIndex(1u).lock();
358+
ASSERT_NE(nullptr, submeshB);
359+
EXPECT_EQ(3u, submeshB->VertexCount());
360+
EXPECT_EQ(3u, submeshB->NormalCount());
361+
EXPECT_EQ(3u, submeshB->IndexCount());
362+
EXPECT_EQ(3u, submeshB->TexCoordSetCount());
363+
EXPECT_EQ(3u, submeshB->TexCoordCountBySet(0));
364+
EXPECT_EQ(3u, submeshB->TexCoordCountBySet(1));
365+
EXPECT_EQ(3u, submeshB->TexCoordCountBySet(2));
366+
367+
// merge all submeshes into one
368+
auto merged = common::MeshManager::MergeSubMeshes(*mesh);
369+
ASSERT_NE(nullptr, merged);
370+
EXPECT_FALSE(merged->Name().empty());
371+
EXPECT_EQ(1u, merged->SubMeshCount());
372+
auto mergedSubmesh = merged->SubMeshByIndex(0u).lock();
373+
ASSERT_NE(nullptr, mergedSubmesh);
374+
EXPECT_FALSE(mergedSubmesh->Name().empty());
375+
376+
// Verify vertice, normals, indice, and texcoord values in the
377+
// final merged submesh
378+
EXPECT_EQ(6u, mergedSubmesh->VertexCount());
379+
EXPECT_EQ(6u, mergedSubmesh->NormalCount());
380+
EXPECT_EQ(6u, mergedSubmesh->IndexCount());
381+
EXPECT_EQ(3u, mergedSubmesh->TexCoordSetCount());
382+
EXPECT_EQ(6u, mergedSubmesh->TexCoordCountBySet(0));
383+
EXPECT_EQ(6u, mergedSubmesh->TexCoordCountBySet(1));
384+
EXPECT_EQ(6u, mergedSubmesh->TexCoordCountBySet(2));
385+
386+
EXPECT_EQ(math::Vector3d(0, 0, 0), mergedSubmesh->Vertex(0u));
387+
EXPECT_EQ(math::Vector3d(10, 0, 0), mergedSubmesh->Vertex(1u));
388+
EXPECT_EQ(math::Vector3d(10, 10, 0), mergedSubmesh->Vertex(2u));
389+
EXPECT_EQ(math::Vector3d(10, 0, 0), mergedSubmesh->Vertex(3u));
390+
EXPECT_EQ(math::Vector3d(20, 0, 0), mergedSubmesh->Vertex(4u));
391+
EXPECT_EQ(math::Vector3d(20, 10, 0), mergedSubmesh->Vertex(5u));
392+
393+
EXPECT_EQ(math::Vector3d(0, 0, 1), mergedSubmesh->Normal(0u));
394+
EXPECT_EQ(math::Vector3d(0, 0, 1), mergedSubmesh->Normal(1u));
395+
EXPECT_EQ(math::Vector3d(0, 0, 1), mergedSubmesh->Normal(2u));
396+
EXPECT_EQ(math::Vector3d(0, 0, 1), mergedSubmesh->Normal(3u));
397+
EXPECT_EQ(math::Vector3d(0, 0, 1), mergedSubmesh->Normal(4u));
398+
EXPECT_EQ(math::Vector3d(0, 0, 1), mergedSubmesh->Normal(5u));
399+
400+
EXPECT_EQ(0u, mergedSubmesh->Index(0u));
401+
EXPECT_EQ(1u, mergedSubmesh->Index(1u));
402+
EXPECT_EQ(2u, mergedSubmesh->Index(2u));
403+
EXPECT_EQ(3u, mergedSubmesh->Index(3u));
404+
EXPECT_EQ(4u, mergedSubmesh->Index(4u));
405+
EXPECT_EQ(5u, mergedSubmesh->Index(5u));
406+
407+
EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(0u, 0u));
408+
EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(1u, 0u));
409+
EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(2u, 0u));
410+
EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(3u, 0u));
411+
EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(4u, 0u));
412+
EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(5u, 0u));
413+
414+
EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(0u, 1u));
415+
EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(1u, 1u));
416+
EXPECT_EQ(math::Vector2d(0, 1), mergedSubmesh->TexCoordBySet(2u, 1u));
417+
EXPECT_EQ(math::Vector2d(0, 0.5), mergedSubmesh->TexCoordBySet(3u, 1u));
418+
EXPECT_EQ(math::Vector2d(0, 0.4), mergedSubmesh->TexCoordBySet(4u, 1u));
419+
EXPECT_EQ(math::Vector2d(0, 0.3), mergedSubmesh->TexCoordBySet(5u, 1u));
420+
421+
EXPECT_EQ(math::Vector2d(0, 0), mergedSubmesh->TexCoordBySet(0u, 2u));
422+
EXPECT_EQ(math::Vector2d(0, 0), mergedSubmesh->TexCoordBySet(1u, 2u));
423+
EXPECT_EQ(math::Vector2d(0, 0), mergedSubmesh->TexCoordBySet(2u, 2u));
424+
EXPECT_EQ(math::Vector2d(0, 0.8), mergedSubmesh->TexCoordBySet(3u, 2u));
425+
EXPECT_EQ(math::Vector2d(0, 0.7), mergedSubmesh->TexCoordBySet(4u, 2u));
426+
EXPECT_EQ(math::Vector2d(0, 0.6), mergedSubmesh->TexCoordBySet(5u, 2u));
427+
}
428+
340429
#endif

0 commit comments

Comments
 (0)