From 37a2ab300634d3489cd167f71b47065c190ad3a5 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 7 Mar 2024 23:27:27 +0000 Subject: [PATCH 1/2] Add mesh simplification attribute Signed-off-by: Ian Chen --- include/sdf/Mesh.hh | 9 +++++++++ sdf/1.11/mesh_shape.sdf | 7 +++++++ src/Mesh.cc | 26 ++++++++++++++++++++++++++ src/Mesh_TEST.cc | 17 +++++++++++++++++ test/integration/geometry_dom.cc | 2 ++ test/sdf/shapes.sdf | 2 +- 6 files changed, 62 insertions(+), 1 deletion(-) diff --git a/include/sdf/Mesh.hh b/include/sdf/Mesh.hh index f19d98818..0d530ef6d 100644 --- a/include/sdf/Mesh.hh +++ b/include/sdf/Mesh.hh @@ -61,6 +61,15 @@ namespace sdf /// an error code and message. An empty vector indicates no error. public: Errors Load(sdf::ElementPtr _sdf, const ParserConfig &_config); + /// \brief Get the mesh's simplifcation method + /// \return The mesh simplification method. + /// Empty string if no mesh simplificaton is done. + public: std::string Simplification() const; + + /// \brief Set the mesh simplification method. + /// \param[in] _simplifcation The mesh simplification method. + public: void SetSimplification(const std::string &_simplifcation); + /// \brief Get the mesh's URI. /// \return The URI of the mesh data. public: std::string Uri() const; diff --git a/sdf/1.11/mesh_shape.sdf b/sdf/1.11/mesh_shape.sdf index 61bce76dd..96eaf930b 100644 --- a/sdf/1.11/mesh_shape.sdf +++ b/sdf/1.11/mesh_shape.sdf @@ -1,5 +1,12 @@ Mesh shape + + + + Set whether to simplify the mesh using one of the specified methods. Values include: "convex_hull", "convex_decomposition". Default value is an empty string which means no mesh simplification. + + + Mesh uri diff --git a/src/Mesh.cc b/src/Mesh.cc index 9dfddcf2b..7ae9e92c7 100644 --- a/src/Mesh.cc +++ b/src/Mesh.cc @@ -30,6 +30,9 @@ using namespace sdf; // Private data class class sdf::Mesh::Implementation { + /// \brief Mesh simplification method + public: std::string simplification; + /// \brief The mesh's URI. public: std::string uri = ""; @@ -87,6 +90,13 @@ Errors Mesh::Load(ElementPtr _sdf, const ParserConfig &_config) return errors; } + // Simplify + if (_sdf->HasAttribute("simplification")) + { + this->dataPtr->simplification = _sdf->Get("simplification", + this->dataPtr->simplification).first; + } + if (_sdf->HasElement("uri")) { std::unordered_set paths; @@ -140,6 +150,18 @@ sdf::ElementPtr Mesh::Element() const return this->dataPtr->sdf; } +////////////////////////////////////////////////// +std::string Mesh::Simplification() const +{ + return this->dataPtr->simplification; +} + +////////////////////////////////////////////////// +void Mesh::SetSimplification(const std::string &_simplification) +{ + this->dataPtr->simplification = _simplification; +} + ////////////////////////////////////////////////// std::string Mesh::Uri() const { @@ -244,6 +266,10 @@ sdf::ElementPtr Mesh::ToElement(sdf::Errors &_errors) const sdf::ElementPtr elem(new sdf::Element); sdf::initFile("mesh_shape.sdf", elem); + // Simplification + elem->GetAttribute("simplification")->Set( + this->dataPtr->simplification); + // Uri sdf::ElementPtr uriElem = elem->GetElement("uri", _errors); uriElem->Set(_errors, this->Uri()); diff --git a/src/Mesh_TEST.cc b/src/Mesh_TEST.cc index 51c1751f4..eb7d08e2f 100644 --- a/src/Mesh_TEST.cc +++ b/src/Mesh_TEST.cc @@ -34,6 +34,7 @@ TEST(DOMMesh, Construction) sdf::Mesh mesh; EXPECT_EQ(nullptr, mesh.Element()); + EXPECT_EQ(std::string(), mesh.Simplification()); EXPECT_EQ(std::string(), mesh.FilePath()); EXPECT_EQ(std::string(), mesh.Uri()); EXPECT_EQ(std::string(), mesh.Submesh()); @@ -45,6 +46,7 @@ TEST(DOMMesh, Construction) TEST(DOMMesh, MoveConstructor) { sdf::Mesh mesh; + mesh.SetSimplification("convex_hull"); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); @@ -52,6 +54,7 @@ TEST(DOMMesh, MoveConstructor) mesh.SetFilePath("/pear"); sdf::Mesh mesh2(std::move(mesh)); + EXPECT_EQ("convex_hull", mesh2.Simplification()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -63,6 +66,7 @@ TEST(DOMMesh, MoveConstructor) TEST(DOMMesh, CopyConstructor) { sdf::Mesh mesh; + mesh.SetSimplification("convex_hull"); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); @@ -70,6 +74,7 @@ TEST(DOMMesh, CopyConstructor) mesh.SetFilePath("/pear"); sdf::Mesh mesh2(mesh); + EXPECT_EQ("convex_hull", mesh2.Simplification()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -81,6 +86,7 @@ TEST(DOMMesh, CopyConstructor) TEST(DOMMesh, CopyAssignmentOperator) { sdf::Mesh mesh; + mesh.SetSimplification("convex_hull"); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); @@ -89,6 +95,7 @@ TEST(DOMMesh, CopyAssignmentOperator) sdf::Mesh mesh2; mesh2 = mesh; + EXPECT_EQ("convex_hull", mesh2.Simplification()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -100,6 +107,7 @@ TEST(DOMMesh, CopyAssignmentOperator) TEST(DOMMesh, MoveAssignmentOperator) { sdf::Mesh mesh; + mesh.SetSimplification("convex_hull"); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); @@ -108,6 +116,7 @@ TEST(DOMMesh, MoveAssignmentOperator) sdf::Mesh mesh2; mesh2 = std::move(mesh); + EXPECT_EQ("convex_hull", mesh2.Simplification()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -140,6 +149,10 @@ TEST(DOMMesh, Set) sdf::Mesh mesh; EXPECT_EQ(nullptr, mesh.Element()); + EXPECT_EQ(std::string(), mesh.Simplification()); + mesh.SetSimplification("convex_hull"); + EXPECT_EQ("convex_hull", mesh.Simplification()); + EXPECT_EQ(std::string(), mesh.Uri()); mesh.SetUri("http://myuri.com"); EXPECT_EQ("http://myuri.com", mesh.Uri()); @@ -296,6 +309,7 @@ TEST(DOMMesh, ToElement) { sdf::Mesh mesh; + mesh.SetSimplification("convex_hull"); mesh.SetUri("mesh-uri"); mesh.SetScale(gz::math::Vector3d(1, 2, 3)); mesh.SetSubmesh("submesh"); @@ -307,6 +321,7 @@ TEST(DOMMesh, ToElement) sdf::Mesh mesh2; mesh2.Load(elem); + EXPECT_EQ(mesh.Simplification(), mesh2.Simplification()); EXPECT_EQ(mesh.Uri(), mesh2.Uri()); EXPECT_EQ(mesh.Scale(), mesh2.Scale()); EXPECT_EQ(mesh.Submesh(), mesh2.Submesh()); @@ -332,6 +347,7 @@ TEST(DOMMesh, ToElementErrorOutput) sdf::Mesh mesh; sdf::Errors errors; + mesh.SetSimplification("convex_hull"); mesh.SetUri("mesh-uri"); mesh.SetScale(gz::math::Vector3d(1, 2, 3)); mesh.SetSubmesh("submesh"); @@ -345,6 +361,7 @@ TEST(DOMMesh, ToElementErrorOutput) errors = mesh2.Load(elem); EXPECT_TRUE(errors.empty()); + EXPECT_EQ(mesh.Simplification(), mesh2.Simplification()); EXPECT_EQ(mesh.Uri(), mesh2.Uri()); EXPECT_EQ(mesh.Scale(), mesh2.Scale()); EXPECT_EQ(mesh.Submesh(), mesh2.Submesh()); diff --git a/test/integration/geometry_dom.cc b/test/integration/geometry_dom.cc index 07d50d570..fb54d3a8e 100644 --- a/test/integration/geometry_dom.cc +++ b/test/integration/geometry_dom.cc @@ -179,6 +179,8 @@ TEST(DOMGeometry, Shapes) EXPECT_EQ(sdf::GeometryType::MESH, meshCol->Geom()->Type()); const sdf::Mesh *meshColGeom = meshCol->Geom()->MeshShape(); ASSERT_NE(nullptr, meshColGeom); + EXPECT_EQ("convex_hull", meshColGeom->Simplification()); + EXPECT_EQ("https://fuel.gazebosim.org/1.0/an_org/models/a_model/mesh/" "mesh.dae", meshColGeom->Uri()); EXPECT_TRUE(gz::math::Vector3d(0.1, 0.2, 0.3) == diff --git a/test/sdf/shapes.sdf b/test/sdf/shapes.sdf index 1f5f4fa27..bfa50c934 100644 --- a/test/sdf/shapes.sdf +++ b/test/sdf/shapes.sdf @@ -120,7 +120,7 @@ - + https://fuel.gazebosim.org/1.0/an_org/models/a_model/mesh/mesh.dae my_submesh From 64d7c97607c953202b8a771a7c7b3a2e67873774 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 14 Mar 2024 00:27:38 +0000 Subject: [PATCH 2/2] add enum, expand sdf doc Signed-off-by: Ian Chen --- include/sdf/Mesh.hh | 27 ++++++++++++++++++-- sdf/1.11/mesh_shape.sdf | 2 +- src/Mesh.cc | 44 +++++++++++++++++++++++++++----- src/Mesh_TEST.cc | 26 ++++++++++++++----- test/integration/geometry_dom.cc | 4 ++- 5 files changed, 86 insertions(+), 17 deletions(-) diff --git a/include/sdf/Mesh.hh b/include/sdf/Mesh.hh index 0d530ef6d..5270f90e0 100644 --- a/include/sdf/Mesh.hh +++ b/include/sdf/Mesh.hh @@ -37,6 +37,17 @@ namespace sdf // Forward declarations. class ParserConfig; + /// \brief Mesh simplification method + enum class MeshSimplification + { + /// \brief No mesh simplification + NONE, + /// \brief Convex hull + CONVEX_HULL, + /// \brief Convex decomposition + CONVEX_DECOMPOSITION + }; + /// \brief Mesh represents a mesh shape, and is usually accessed through a /// Geometry. class SDFORMAT_VISIBLE Mesh @@ -61,14 +72,26 @@ namespace sdf /// an error code and message. An empty vector indicates no error. public: Errors Load(sdf::ElementPtr _sdf, const ParserConfig &_config); + /// \brief Get the mesh's simplifcation method + /// \return The mesh simplification method. + /// MeshSimplification::NONE if no mesh simplificaton is done. + public: MeshSimplification Simplification() const; + /// \brief Get the mesh's simplifcation method /// \return The mesh simplification method. /// Empty string if no mesh simplificaton is done. - public: std::string Simplification() const; + public: std::string SimplificationStr() const; + + /// \brief Set the mesh simplification method. + /// \param[in] _simplifcation The mesh simplification method. + public: void SetSimplification(MeshSimplification _simplifcation); /// \brief Set the mesh simplification method. /// \param[in] _simplifcation The mesh simplification method. - public: void SetSimplification(const std::string &_simplifcation); + /// \return True if the _simplificationStr parameter matched a known + /// mesh simplification method. False if the mesh simplification method + /// could not be set. + public: bool SetSimplification(const std::string &_simplifcationStr); /// \brief Get the mesh's URI. /// \return The URI of the mesh data. diff --git a/sdf/1.11/mesh_shape.sdf b/sdf/1.11/mesh_shape.sdf index 96eaf930b..347414eca 100644 --- a/sdf/1.11/mesh_shape.sdf +++ b/sdf/1.11/mesh_shape.sdf @@ -3,7 +3,7 @@ - Set whether to simplify the mesh using one of the specified methods. Values include: "convex_hull", "convex_decomposition". Default value is an empty string which means no mesh simplification. + Set whether to simplify the mesh using one of the specified methods. Values include: "convex_hull" - a single convex hull that encapsulates the mesh, "convex_decomposition" - decompose the mesh into multiple convex hull meshes. Default value is an empty string which means no mesh simplification. diff --git a/src/Mesh.cc b/src/Mesh.cc index 7ae9e92c7..d97a98cd4 100644 --- a/src/Mesh.cc +++ b/src/Mesh.cc @@ -27,11 +27,21 @@ using namespace sdf; +/// Mesh Simplification method strings. These should match the data in +/// `enum class MeshSimplification` located in Mesh.hh, and the size +/// template parameter should match the number of elements as well. +constexpr std::array kMeshSimplificationStrs = +{ + "", + "convex_hull", + "convex_decomposition" +}; + // Private data class class sdf::Mesh::Implementation { /// \brief Mesh simplification method - public: std::string simplification; + public: MeshSimplification simplification = MeshSimplification::NONE; /// \brief The mesh's URI. public: std::string uri = ""; @@ -93,8 +103,7 @@ Errors Mesh::Load(ElementPtr _sdf, const ParserConfig &_config) // Simplify if (_sdf->HasAttribute("simplification")) { - this->dataPtr->simplification = _sdf->Get("simplification", - this->dataPtr->simplification).first; + this->SetSimplification(_sdf->Get("simplification", "").first); } if (_sdf->HasElement("uri")) @@ -151,13 +160,36 @@ sdf::ElementPtr Mesh::Element() const } ////////////////////////////////////////////////// -std::string Mesh::Simplification() const +MeshSimplification Mesh::Simplification() const { return this->dataPtr->simplification; } ////////////////////////////////////////////////// -void Mesh::SetSimplification(const std::string &_simplification) +std::string Mesh::SimplificationStr() const +{ + size_t index = static_cast(this->dataPtr->simplification); + if (index < kMeshSimplificationStrs.size()) + return std::string(kMeshSimplificationStrs[index]); + return ""; +} + +////////////////////////////////////////////////// +bool Mesh::SetSimplification(const std::string &_simplificationStr) +{ + for (size_t i = 0; i < kMeshSimplificationStrs.size(); ++i) + { + if (_simplificationStr == kMeshSimplificationStrs[i]) + { + this->dataPtr->simplification = static_cast(i); + return true; + } + } + return false; +} + +////////////////////////////////////////////////// +void Mesh::SetSimplification(MeshSimplification _simplification) { this->dataPtr->simplification = _simplification; } @@ -268,7 +300,7 @@ sdf::ElementPtr Mesh::ToElement(sdf::Errors &_errors) const // Simplification elem->GetAttribute("simplification")->Set( - this->dataPtr->simplification); + this->SimplificationStr()); // Uri sdf::ElementPtr uriElem = elem->GetElement("uri", _errors); diff --git a/src/Mesh_TEST.cc b/src/Mesh_TEST.cc index eb7d08e2f..8f79451c8 100644 --- a/src/Mesh_TEST.cc +++ b/src/Mesh_TEST.cc @@ -34,7 +34,8 @@ TEST(DOMMesh, Construction) sdf::Mesh mesh; EXPECT_EQ(nullptr, mesh.Element()); - EXPECT_EQ(std::string(), mesh.Simplification()); + EXPECT_EQ(std::string(), mesh.SimplificationStr()); + EXPECT_EQ(sdf::MeshSimplification::NONE, mesh.Simplification()); EXPECT_EQ(std::string(), mesh.FilePath()); EXPECT_EQ(std::string(), mesh.Uri()); EXPECT_EQ(std::string(), mesh.Submesh()); @@ -54,7 +55,8 @@ TEST(DOMMesh, MoveConstructor) mesh.SetFilePath("/pear"); sdf::Mesh mesh2(std::move(mesh)); - EXPECT_EQ("convex_hull", mesh2.Simplification()); + EXPECT_EQ("convex_hull", mesh2.SimplificationStr()); + EXPECT_EQ(sdf::MeshSimplification::CONVEX_HULL, mesh2.Simplification()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -74,7 +76,8 @@ TEST(DOMMesh, CopyConstructor) mesh.SetFilePath("/pear"); sdf::Mesh mesh2(mesh); - EXPECT_EQ("convex_hull", mesh2.Simplification()); + EXPECT_EQ("convex_hull", mesh2.SimplificationStr()); + EXPECT_EQ(sdf::MeshSimplification::CONVEX_HULL, mesh2.Simplification()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -95,7 +98,8 @@ TEST(DOMMesh, CopyAssignmentOperator) sdf::Mesh mesh2; mesh2 = mesh; - EXPECT_EQ("convex_hull", mesh2.Simplification()); + EXPECT_EQ("convex_hull", mesh2.SimplificationStr()); + EXPECT_EQ(sdf::MeshSimplification::CONVEX_HULL, mesh2.Simplification()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -116,7 +120,8 @@ TEST(DOMMesh, MoveAssignmentOperator) sdf::Mesh mesh2; mesh2 = std::move(mesh); - EXPECT_EQ("convex_hull", mesh2.Simplification()); + EXPECT_EQ("convex_hull", mesh2.SimplificationStr()); + EXPECT_EQ(sdf::MeshSimplification::CONVEX_HULL, mesh2.Simplification()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -149,9 +154,14 @@ TEST(DOMMesh, Set) sdf::Mesh mesh; EXPECT_EQ(nullptr, mesh.Element()); - EXPECT_EQ(std::string(), mesh.Simplification()); + EXPECT_EQ(std::string(), mesh.SimplificationStr()); mesh.SetSimplification("convex_hull"); - EXPECT_EQ("convex_hull", mesh.Simplification()); + EXPECT_EQ("convex_hull", mesh.SimplificationStr()); + EXPECT_EQ(sdf::MeshSimplification::CONVEX_HULL, mesh.Simplification()); + mesh.SetSimplification(sdf::MeshSimplification::CONVEX_DECOMPOSITION); + EXPECT_EQ("convex_decomposition", mesh.SimplificationStr()); + EXPECT_EQ(sdf::MeshSimplification::CONVEX_DECOMPOSITION, + mesh.Simplification()); EXPECT_EQ(std::string(), mesh.Uri()); mesh.SetUri("http://myuri.com"); @@ -321,6 +331,7 @@ TEST(DOMMesh, ToElement) sdf::Mesh mesh2; mesh2.Load(elem); + EXPECT_EQ(mesh.SimplificationStr(), mesh2.SimplificationStr()); EXPECT_EQ(mesh.Simplification(), mesh2.Simplification()); EXPECT_EQ(mesh.Uri(), mesh2.Uri()); EXPECT_EQ(mesh.Scale(), mesh2.Scale()); @@ -361,6 +372,7 @@ TEST(DOMMesh, ToElementErrorOutput) errors = mesh2.Load(elem); EXPECT_TRUE(errors.empty()); + EXPECT_EQ(mesh.SimplificationStr(), mesh2.SimplificationStr()); EXPECT_EQ(mesh.Simplification(), mesh2.Simplification()); EXPECT_EQ(mesh.Uri(), mesh2.Uri()); EXPECT_EQ(mesh.Scale(), mesh2.Scale()); diff --git a/test/integration/geometry_dom.cc b/test/integration/geometry_dom.cc index fb54d3a8e..ceef3fa15 100644 --- a/test/integration/geometry_dom.cc +++ b/test/integration/geometry_dom.cc @@ -179,7 +179,9 @@ TEST(DOMGeometry, Shapes) EXPECT_EQ(sdf::GeometryType::MESH, meshCol->Geom()->Type()); const sdf::Mesh *meshColGeom = meshCol->Geom()->MeshShape(); ASSERT_NE(nullptr, meshColGeom); - EXPECT_EQ("convex_hull", meshColGeom->Simplification()); + EXPECT_EQ("convex_hull", meshColGeom->SimplificationStr()); + EXPECT_EQ(sdf::MeshSimplification::CONVEX_HULL, + meshColGeom->Simplification()); EXPECT_EQ("https://fuel.gazebosim.org/1.0/an_org/models/a_model/mesh/" "mesh.dae", meshColGeom->Uri());