From a2e441e40ac34ad94ec08bffe4ab04882d80a09a Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 7 Mar 2024 23:27:27 +0000 Subject: [PATCH 1/7] 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 aa7cee81c77eb6f2e7190e7b1af26ed5da464b16 Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 14 Mar 2024 00:27:38 +0000 Subject: [PATCH 2/7] 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 | 46 +++++++++++++++++++++++++++----- src/Mesh_TEST.cc | 26 +++++++++++++----- test/integration/geometry_dom.cc | 4 ++- 5 files changed, 88 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..2758a85c6 100644 --- a/src/Mesh.cc +++ b/src/Mesh.cc @@ -14,8 +14,10 @@ * limitations under the License. * */ +#include #include #include +#include #include #include "sdf/CustomInertiaCalcProperties.hh" @@ -27,11 +29,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 +105,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 +162,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 +302,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()); From 89b46c043c0c94b6c83f92371c302ec7b2d2977a Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Thu, 14 Mar 2024 01:49:45 +0000 Subject: [PATCH 3/7] update sdf 1.12 Signed-off-by: Ian Chen --- sdf/1.12/mesh_shape.sdf | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sdf/1.12/mesh_shape.sdf b/sdf/1.12/mesh_shape.sdf index 61bce76dd..347414eca 100644 --- a/sdf/1.12/mesh_shape.sdf +++ b/sdf/1.12/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" - 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. + + + Mesh uri From 75ca10e995baa59371cc51c4793fc918b337d65b Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Fri, 15 Mar 2024 21:25:22 +0000 Subject: [PATCH 4/7] Simplification -> Optimization Signed-off-by: Ian Chen --- include/sdf/Mesh.hh | 36 ++++++++++---------- src/Mesh.cc | 44 ++++++++++++------------- src/Mesh_TEST.cc | 56 ++++++++++++++++---------------- test/integration/geometry_dom.cc | 6 ++-- 4 files changed, 71 insertions(+), 71 deletions(-) diff --git a/include/sdf/Mesh.hh b/include/sdf/Mesh.hh index 5270f90e0..a354141dd 100644 --- a/include/sdf/Mesh.hh +++ b/include/sdf/Mesh.hh @@ -37,10 +37,10 @@ namespace sdf // Forward declarations. class ParserConfig; - /// \brief Mesh simplification method - enum class MeshSimplification + /// \brief Mesh optimization method + enum class MeshOptimization { - /// \brief No mesh simplification + /// \brief No mesh optimization NONE, /// \brief Convex hull CONVEX_HULL, @@ -72,26 +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 optimization method + /// \return The mesh optimization method. + /// MeshOptimization::NONE if no mesh simplificaton is done. + public: MeshOptimization Optimization() const; - /// \brief Get the mesh's simplifcation method - /// \return The mesh simplification method. + /// \brief Get the mesh's optimization method + /// \return The mesh optimization method. /// Empty string if no mesh simplificaton is done. - public: std::string SimplificationStr() const; + public: std::string OptimizationStr() const; - /// \brief Set the mesh simplification method. - /// \param[in] _simplifcation The mesh simplification method. - public: void SetSimplification(MeshSimplification _simplifcation); + /// \brief Set the mesh optimization method. + /// \param[in] _optimization The mesh optimization method. + public: void SetOptimization(MeshOptimization _optimization); - /// \brief Set the mesh simplification method. - /// \param[in] _simplifcation The mesh simplification method. - /// \return True if the _simplificationStr parameter matched a known - /// mesh simplification method. False if the mesh simplification method + /// \brief Set the mesh optimization method. + /// \param[in] _optimization The mesh optimization method. + /// \return True if the _optimizationStr parameter matched a known + /// mesh optimization method. False if the mesh optimization method /// could not be set. - public: bool SetSimplification(const std::string &_simplifcationStr); + public: bool SetOptimization(const std::string &_optimizationStr); /// \brief Get the mesh's URI. /// \return The URI of the mesh data. diff --git a/src/Mesh.cc b/src/Mesh.cc index 2758a85c6..1c1be1416 100644 --- a/src/Mesh.cc +++ b/src/Mesh.cc @@ -29,10 +29,10 @@ using namespace sdf; -/// Mesh Simplification method strings. These should match the data in -/// `enum class MeshSimplification` located in Mesh.hh, and the size +/// Mesh Optimization method strings. These should match the data in +/// `enum class MeshOptimization` located in Mesh.hh, and the size /// template parameter should match the number of elements as well. -constexpr std::array kMeshSimplificationStrs = +constexpr std::array kMeshOptimizationStrs = { "", "convex_hull", @@ -42,8 +42,8 @@ constexpr std::array kMeshSimplificationStrs = // Private data class class sdf::Mesh::Implementation { - /// \brief Mesh simplification method - public: MeshSimplification simplification = MeshSimplification::NONE; + /// \brief Mesh optimization method + public: MeshOptimization optimization = MeshOptimization::NONE; /// \brief The mesh's URI. public: std::string uri = ""; @@ -103,9 +103,9 @@ Errors Mesh::Load(ElementPtr _sdf, const ParserConfig &_config) } // Simplify - if (_sdf->HasAttribute("simplification")) + if (_sdf->HasAttribute("optimization")) { - this->SetSimplification(_sdf->Get("simplification", "").first); + this->SetOptimization(_sdf->Get("optimization", "").first); } if (_sdf->HasElement("uri")) @@ -162,28 +162,28 @@ sdf::ElementPtr Mesh::Element() const } ////////////////////////////////////////////////// -MeshSimplification Mesh::Simplification() const +MeshOptimization Mesh::Optimization() const { - return this->dataPtr->simplification; + return this->dataPtr->optimization; } ////////////////////////////////////////////////// -std::string Mesh::SimplificationStr() const +std::string Mesh::OptimizationStr() const { - size_t index = static_cast(this->dataPtr->simplification); - if (index < kMeshSimplificationStrs.size()) - return std::string(kMeshSimplificationStrs[index]); + size_t index = static_cast(this->dataPtr->optimization); + if (index < kMeshOptimizationStrs.size()) + return std::string(kMeshOptimizationStrs[index]); return ""; } ////////////////////////////////////////////////// -bool Mesh::SetSimplification(const std::string &_simplificationStr) +bool Mesh::SetOptimization(const std::string &_optimizationStr) { - for (size_t i = 0; i < kMeshSimplificationStrs.size(); ++i) + for (size_t i = 0; i < kMeshOptimizationStrs.size(); ++i) { - if (_simplificationStr == kMeshSimplificationStrs[i]) + if (_optimizationStr == kMeshOptimizationStrs[i]) { - this->dataPtr->simplification = static_cast(i); + this->dataPtr->optimization = static_cast(i); return true; } } @@ -191,9 +191,9 @@ bool Mesh::SetSimplification(const std::string &_simplificationStr) } ////////////////////////////////////////////////// -void Mesh::SetSimplification(MeshSimplification _simplification) +void Mesh::SetOptimization(MeshOptimization _optimization) { - this->dataPtr->simplification = _simplification; + this->dataPtr->optimization = _optimization; } ////////////////////////////////////////////////// @@ -300,9 +300,9 @@ 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->SimplificationStr()); + // Optimization + elem->GetAttribute("optimization")->Set( + this->OptimizationStr()); // Uri sdf::ElementPtr uriElem = elem->GetElement("uri", _errors); diff --git a/src/Mesh_TEST.cc b/src/Mesh_TEST.cc index 8f79451c8..512f09e1f 100644 --- a/src/Mesh_TEST.cc +++ b/src/Mesh_TEST.cc @@ -34,8 +34,8 @@ TEST(DOMMesh, Construction) sdf::Mesh mesh; EXPECT_EQ(nullptr, mesh.Element()); - EXPECT_EQ(std::string(), mesh.SimplificationStr()); - EXPECT_EQ(sdf::MeshSimplification::NONE, mesh.Simplification()); + EXPECT_EQ(std::string(), mesh.OptimizationStr()); + EXPECT_EQ(sdf::MeshOptimization::NONE, mesh.Optimization()); EXPECT_EQ(std::string(), mesh.FilePath()); EXPECT_EQ(std::string(), mesh.Uri()); EXPECT_EQ(std::string(), mesh.Submesh()); @@ -47,7 +47,7 @@ TEST(DOMMesh, Construction) TEST(DOMMesh, MoveConstructor) { sdf::Mesh mesh; - mesh.SetSimplification("convex_hull"); + mesh.SetOptimization("convex_hull"); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); @@ -55,8 +55,8 @@ TEST(DOMMesh, MoveConstructor) mesh.SetFilePath("/pear"); sdf::Mesh mesh2(std::move(mesh)); - EXPECT_EQ("convex_hull", mesh2.SimplificationStr()); - EXPECT_EQ(sdf::MeshSimplification::CONVEX_HULL, mesh2.Simplification()); + EXPECT_EQ("convex_hull", mesh2.OptimizationStr()); + EXPECT_EQ(sdf::MeshOptimization::CONVEX_HULL, mesh2.Optimization()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -68,7 +68,7 @@ TEST(DOMMesh, MoveConstructor) TEST(DOMMesh, CopyConstructor) { sdf::Mesh mesh; - mesh.SetSimplification("convex_hull"); + mesh.SetOptimization("convex_hull"); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); @@ -76,8 +76,8 @@ TEST(DOMMesh, CopyConstructor) mesh.SetFilePath("/pear"); sdf::Mesh mesh2(mesh); - EXPECT_EQ("convex_hull", mesh2.SimplificationStr()); - EXPECT_EQ(sdf::MeshSimplification::CONVEX_HULL, mesh2.Simplification()); + EXPECT_EQ("convex_hull", mesh2.OptimizationStr()); + EXPECT_EQ(sdf::MeshOptimization::CONVEX_HULL, mesh2.Optimization()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -89,7 +89,7 @@ TEST(DOMMesh, CopyConstructor) TEST(DOMMesh, CopyAssignmentOperator) { sdf::Mesh mesh; - mesh.SetSimplification("convex_hull"); + mesh.SetOptimization("convex_hull"); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); @@ -98,8 +98,8 @@ TEST(DOMMesh, CopyAssignmentOperator) sdf::Mesh mesh2; mesh2 = mesh; - EXPECT_EQ("convex_hull", mesh2.SimplificationStr()); - EXPECT_EQ(sdf::MeshSimplification::CONVEX_HULL, mesh2.Simplification()); + EXPECT_EQ("convex_hull", mesh2.OptimizationStr()); + EXPECT_EQ(sdf::MeshOptimization::CONVEX_HULL, mesh2.Optimization()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -111,7 +111,7 @@ TEST(DOMMesh, CopyAssignmentOperator) TEST(DOMMesh, MoveAssignmentOperator) { sdf::Mesh mesh; - mesh.SetSimplification("convex_hull"); + mesh.SetOptimization("convex_hull"); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); @@ -120,8 +120,8 @@ TEST(DOMMesh, MoveAssignmentOperator) sdf::Mesh mesh2; mesh2 = std::move(mesh); - EXPECT_EQ("convex_hull", mesh2.SimplificationStr()); - EXPECT_EQ(sdf::MeshSimplification::CONVEX_HULL, mesh2.Simplification()); + EXPECT_EQ("convex_hull", mesh2.OptimizationStr()); + EXPECT_EQ(sdf::MeshOptimization::CONVEX_HULL, mesh2.Optimization()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -154,14 +154,14 @@ TEST(DOMMesh, Set) sdf::Mesh mesh; EXPECT_EQ(nullptr, mesh.Element()); - EXPECT_EQ(std::string(), mesh.SimplificationStr()); - mesh.SetSimplification("convex_hull"); - 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.OptimizationStr()); + mesh.SetOptimization("convex_hull"); + EXPECT_EQ("convex_hull", mesh.OptimizationStr()); + EXPECT_EQ(sdf::MeshOptimization::CONVEX_HULL, mesh.Optimization()); + mesh.SetOptimization(sdf::MeshOptimization::CONVEX_DECOMPOSITION); + EXPECT_EQ("convex_decomposition", mesh.OptimizationStr()); + EXPECT_EQ(sdf::MeshOptimization::CONVEX_DECOMPOSITION, + mesh.Optimization()); EXPECT_EQ(std::string(), mesh.Uri()); mesh.SetUri("http://myuri.com"); @@ -319,7 +319,7 @@ TEST(DOMMesh, ToElement) { sdf::Mesh mesh; - mesh.SetSimplification("convex_hull"); + mesh.SetOptimization("convex_hull"); mesh.SetUri("mesh-uri"); mesh.SetScale(gz::math::Vector3d(1, 2, 3)); mesh.SetSubmesh("submesh"); @@ -331,8 +331,8 @@ TEST(DOMMesh, ToElement) sdf::Mesh mesh2; mesh2.Load(elem); - EXPECT_EQ(mesh.SimplificationStr(), mesh2.SimplificationStr()); - EXPECT_EQ(mesh.Simplification(), mesh2.Simplification()); + EXPECT_EQ(mesh.OptimizationStr(), mesh2.OptimizationStr()); + EXPECT_EQ(mesh.Optimization(), mesh2.Optimization()); EXPECT_EQ(mesh.Uri(), mesh2.Uri()); EXPECT_EQ(mesh.Scale(), mesh2.Scale()); EXPECT_EQ(mesh.Submesh(), mesh2.Submesh()); @@ -358,7 +358,7 @@ TEST(DOMMesh, ToElementErrorOutput) sdf::Mesh mesh; sdf::Errors errors; - mesh.SetSimplification("convex_hull"); + mesh.SetOptimization("convex_hull"); mesh.SetUri("mesh-uri"); mesh.SetScale(gz::math::Vector3d(1, 2, 3)); mesh.SetSubmesh("submesh"); @@ -372,8 +372,8 @@ 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.OptimizationStr(), mesh2.OptimizationStr()); + EXPECT_EQ(mesh.Optimization(), mesh2.Optimization()); 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 ceef3fa15..30bcb1f7b 100644 --- a/test/integration/geometry_dom.cc +++ b/test/integration/geometry_dom.cc @@ -179,9 +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->SimplificationStr()); - EXPECT_EQ(sdf::MeshSimplification::CONVEX_HULL, - meshColGeom->Simplification()); + EXPECT_EQ("convex_hull", meshColGeom->OptimizationStr()); + EXPECT_EQ(sdf::MeshOptimization::CONVEX_HULL, + meshColGeom->Optimization()); EXPECT_EQ("https://fuel.gazebosim.org/1.0/an_org/models/a_model/mesh/" "mesh.dae", meshColGeom->Uri()); From b399bcda15b64b90f170d04904e16c5a3f59457c Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Fri, 15 Mar 2024 22:47:37 +0000 Subject: [PATCH 5/7] simplification -> optimization, add convex decomposition max convex hulls property Signed-off-by: Ian Chen --- include/sdf/Mesh.hh | 40 ++++++++++++ sdf/1.11/mesh_shape.sdf | 11 +++- sdf/1.12/mesh_shape.sdf | 11 +++- src/Mesh.cc | 105 ++++++++++++++++++++++++++++++- src/Mesh_TEST.cc | 33 ++++++++-- test/integration/geometry_dom.cc | 6 +- test/sdf/shapes.sdf | 5 +- 7 files changed, 198 insertions(+), 13 deletions(-) diff --git a/include/sdf/Mesh.hh b/include/sdf/Mesh.hh index a354141dd..5fc3a34f4 100644 --- a/include/sdf/Mesh.hh +++ b/include/sdf/Mesh.hh @@ -48,6 +48,36 @@ namespace sdf CONVEX_DECOMPOSITION }; + /// \brief Convex decomposition + class SDFORMAT_VISIBLE ConvexDecomposition + { + /// \brief Default constructor + public: ConvexDecomposition(); + + /// \brief Load the contact based on a element pointer. This is *not* the + /// usual entry point. Typical usage of the SDF DOM is through the Root + /// object. + /// \param[in] _sdf The SDF Element pointer + /// \return Errors, which is a vector of Error objects. Each Error includes + /// an error code and message. An empty vector indicates no error. + public: Errors Load(ElementPtr _sdf); + + /// \brief Get a pointer to the SDF element that was used during + /// load. + /// \return SDF element pointer. The value will be nullptr if Load has + /// not been called. + public: sdf::ElementPtr Element() const; + + /// \brief Get the maximum number of convex hulls that can be generated. + public: unsigned int MaxConvexHulls() const; + + /// \brief Set the maximum number of convex hulls that can be generated. + public: void SetMaxConvexHulls(unsigned int _maxConvexHulls); + + /// \brief Private data pointer. + GZ_UTILS_IMPL_PTR(dataPtr) + }; + /// \brief Mesh represents a mesh shape, and is usually accessed through a /// Geometry. class SDFORMAT_VISIBLE Mesh @@ -93,6 +123,16 @@ namespace sdf /// could not be set. public: bool SetOptimization(const std::string &_optimizationStr); + /// \brief Get the associated ConvexDecomposition object + /// \returns Pointer to the associated ConvexDecomposition object, + /// nullptr if the Mesh doesn't contain a ConvexDecomposition element. + public: const sdf::ConvexDecomposition *ConvexDecomposition() const; + + /// \brief Set the associated ConvexDecomposition object. + /// \param[in] _convexDecomposition The ConvexDecomposition object. + public: void SetConvexDecomposition( + const sdf::ConvexDecomposition &_convexDecomposition); + /// \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 347414eca..a59300d46 100644 --- a/sdf/1.11/mesh_shape.sdf +++ b/sdf/1.11/mesh_shape.sdf @@ -1,12 +1,19 @@ Mesh shape - + - 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. + Set whether to optimize 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 optimization. + + Convex decomposition parameters. Applicable if the mesh optimization attribute is set to convex_decomposition + + Maximum number of convex hulls to decompose into. If the input mesh has multiple submeshes, this limit is applied when decomposing each submesh + + + Mesh uri diff --git a/sdf/1.12/mesh_shape.sdf b/sdf/1.12/mesh_shape.sdf index 347414eca..a59300d46 100644 --- a/sdf/1.12/mesh_shape.sdf +++ b/sdf/1.12/mesh_shape.sdf @@ -1,12 +1,19 @@ Mesh shape - + - 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. + Set whether to optimize 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 optimization. + + Convex decomposition parameters. Applicable if the mesh optimization attribute is set to convex_decomposition + + Maximum number of convex hulls to decompose into. If the input mesh has multiple submeshes, this limit is applied when decomposing each submesh + + + Mesh uri diff --git a/src/Mesh.cc b/src/Mesh.cc index 1c1be1416..f026e2d63 100644 --- a/src/Mesh.cc +++ b/src/Mesh.cc @@ -39,12 +39,25 @@ constexpr std::array kMeshOptimizationStrs = "convex_decomposition" }; -// Private data class +// Private data class for ConvexDecomposition +class sdf::ConvexDecomposition::Implementation +{ + /// \brief Maximum number of convex hulls to generate. + public: unsigned int maxConvexHulls{16u}; + + /// \brief The SDF element pointer used during load. + public: sdf::ElementPtr sdf = nullptr; +}; + +// Private data class for Mesh class sdf::Mesh::Implementation { /// \brief Mesh optimization method public: MeshOptimization optimization = MeshOptimization::NONE; + /// \brief Optional convex decomposition. + public: std::optional convexDecomposition; + /// \brief The mesh's URI. public: std::string uri = ""; @@ -64,6 +77,62 @@ class sdf::Mesh::Implementation public: sdf::ElementPtr sdf = nullptr; }; +///////////////////////////////////////////////// +ConvexDecomposition::ConvexDecomposition() + : dataPtr(gz::utils::MakeImpl()) +{ +} + +///////////////////////////////////////////////// +Errors ConvexDecomposition::Load(ElementPtr _sdf) +{ + Errors errors; + + this->dataPtr->sdf = _sdf; + + // Check that sdf is a valid pointer + if (!_sdf) + { + errors.push_back({ErrorCode::ELEMENT_MISSING, + "Attempting to load convex decomposition, " + "but the provided SDF element is null."}); + return errors; + } + + // We need a convex_decomposition element + if (_sdf->GetName() != "convex_decomposition") + { + errors.push_back({ErrorCode::ELEMENT_INCORRECT_TYPE, + "Attempting to load convex decomposition, but the provided SDF " + "element is not ."}); + return errors; + } + + this->dataPtr->maxConvexHulls = _sdf->Get( + errors, "max_convex_hulls", + this->dataPtr->maxConvexHulls).first; + + return errors; +} + +///////////////////////////////////////////////// +sdf::ElementPtr ConvexDecomposition::Element() const +{ + return this->dataPtr->sdf; +} + +///////////////////////////////////////////////// +unsigned int ConvexDecomposition::MaxConvexHulls() const +{ + return this->dataPtr->maxConvexHulls; +} + +///////////////////////////////////////////////// +void ConvexDecomposition::SetMaxConvexHulls(unsigned int _maxConvexHulls) +{ + this->dataPtr->maxConvexHulls = _maxConvexHulls; +} + ///////////////////////////////////////////////// Mesh::Mesh() : dataPtr(gz::utils::MakeImpl()) @@ -76,6 +145,7 @@ Errors Mesh::Load(ElementPtr _sdf) return this->Load(_sdf, ParserConfig::GlobalConfig()); } + ///////////////////////////////////////////////// Errors Mesh::Load(ElementPtr _sdf, const ParserConfig &_config) { @@ -102,12 +172,20 @@ Errors Mesh::Load(ElementPtr _sdf, const ParserConfig &_config) return errors; } - // Simplify + // Optimization if (_sdf->HasAttribute("optimization")) { this->SetOptimization(_sdf->Get("optimization", "").first); } + if (_sdf->HasElement("convex_decomposition")) + { + this->dataPtr->convexDecomposition.emplace(); + Errors err = this->dataPtr->convexDecomposition->Load( + _sdf->GetElement("convex_decomposition", errors)); + errors.insert(errors.end(), err.begin(), err.end()); + } + if (_sdf->HasElement("uri")) { std::unordered_set paths; @@ -196,6 +274,21 @@ void Mesh::SetOptimization(MeshOptimization _optimization) this->dataPtr->optimization = _optimization; } +////////////////////////////////////////////////// +const sdf::ConvexDecomposition *Mesh::ConvexDecomposition() const +{ + if (this->dataPtr->convexDecomposition.has_value()) + return &this->dataPtr->convexDecomposition.value(); + return nullptr; +} + +////////////////////////////////////////////////// + void Mesh::SetConvexDecomposition( + const sdf::ConvexDecomposition &_convexDecomposition) +{ + this->dataPtr->convexDecomposition = _convexDecomposition; +} + ////////////////////////////////////////////////// std::string Mesh::Uri() const { @@ -304,6 +397,14 @@ sdf::ElementPtr Mesh::ToElement(sdf::Errors &_errors) const elem->GetAttribute("optimization")->Set( this->OptimizationStr()); + if (this->dataPtr->convexDecomposition.has_value()) + { + sdf::ElementPtr convexDecomp = elem->GetElement("convex_decomposition", + _errors); + convexDecomp->GetElement("max_convex_hulls")->Set( + this->dataPtr->convexDecomposition->MaxConvexHulls()); + } + // 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 512f09e1f..c7095559d 100644 --- a/src/Mesh_TEST.cc +++ b/src/Mesh_TEST.cc @@ -36,6 +36,7 @@ TEST(DOMMesh, Construction) EXPECT_EQ(std::string(), mesh.OptimizationStr()); EXPECT_EQ(sdf::MeshOptimization::NONE, mesh.Optimization()); + EXPECT_EQ(nullptr, mesh.ConvexDecomposition()); EXPECT_EQ(std::string(), mesh.FilePath()); EXPECT_EQ(std::string(), mesh.Uri()); EXPECT_EQ(std::string(), mesh.Submesh()); @@ -47,21 +48,29 @@ TEST(DOMMesh, Construction) TEST(DOMMesh, MoveConstructor) { sdf::Mesh mesh; - mesh.SetOptimization("convex_hull"); + mesh.SetOptimization("convex_decomposition"); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); mesh.SetScale({0.5, 0.6, 0.7}); mesh.SetFilePath("/pear"); + sdf::ConvexDecomposition convexDecomp; + convexDecomp.SetMaxConvexHulls(10u); + mesh.SetConvexDecomposition(convexDecomp); + sdf::Mesh mesh2(std::move(mesh)); - EXPECT_EQ("convex_hull", mesh2.OptimizationStr()); - EXPECT_EQ(sdf::MeshOptimization::CONVEX_HULL, mesh2.Optimization()); + EXPECT_EQ("convex_decomposition", mesh2.OptimizationStr()); + EXPECT_EQ(sdf::MeshOptimization::CONVEX_DECOMPOSITION, mesh2.Optimization()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); EXPECT_TRUE(mesh2.CenterSubmesh()); EXPECT_EQ("/pear", mesh2.FilePath()); + + auto convexDecomp2 = mesh2.ConvexDecomposition(); + ASSERT_NE(nullptr, convexDecomp2); + EXPECT_EQ(10u, convexDecomp2->MaxConvexHulls()); } ///////////////////////////////////////////////// @@ -78,6 +87,7 @@ TEST(DOMMesh, CopyConstructor) sdf::Mesh mesh2(mesh); EXPECT_EQ("convex_hull", mesh2.OptimizationStr()); EXPECT_EQ(sdf::MeshOptimization::CONVEX_HULL, mesh2.Optimization()); + EXPECT_EQ(nullptr, mesh2.ConvexDecomposition()); 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 +110,7 @@ TEST(DOMMesh, CopyAssignmentOperator) mesh2 = mesh; EXPECT_EQ("convex_hull", mesh2.OptimizationStr()); EXPECT_EQ(sdf::MeshOptimization::CONVEX_HULL, mesh2.Optimization()); + EXPECT_EQ(nullptr, mesh2.ConvexDecomposition()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -122,6 +133,7 @@ TEST(DOMMesh, MoveAssignmentOperator) mesh2 = std::move(mesh); EXPECT_EQ("convex_hull", mesh2.OptimizationStr()); EXPECT_EQ(sdf::MeshOptimization::CONVEX_HULL, mesh2.Optimization()); + EXPECT_EQ(nullptr, mesh2.ConvexDecomposition()); EXPECT_EQ("banana", mesh2.Uri()); EXPECT_EQ("watermelon", mesh2.Submesh()); EXPECT_EQ(gz::math::Vector3d(0.5, 0.6, 0.7), mesh2.Scale()); @@ -163,6 +175,12 @@ TEST(DOMMesh, Set) EXPECT_EQ(sdf::MeshOptimization::CONVEX_DECOMPOSITION, mesh.Optimization()); + sdf::ConvexDecomposition convexDecomp; + convexDecomp.SetMaxConvexHulls(10u); + mesh.SetConvexDecomposition(convexDecomp); + ASSERT_NE(nullptr, mesh.ConvexDecomposition()); + EXPECT_EQ(10u, mesh.ConvexDecomposition()->MaxConvexHulls()); + EXPECT_EQ(std::string(), mesh.Uri()); mesh.SetUri("http://myuri.com"); EXPECT_EQ("http://myuri.com", mesh.Uri()); @@ -319,12 +337,16 @@ TEST(DOMMesh, ToElement) { sdf::Mesh mesh; - mesh.SetOptimization("convex_hull"); + mesh.SetOptimization("convex_decomposition"); mesh.SetUri("mesh-uri"); mesh.SetScale(gz::math::Vector3d(1, 2, 3)); mesh.SetSubmesh("submesh"); mesh.SetCenterSubmesh(false); + sdf::ConvexDecomposition convexDecomp; + convexDecomp.SetMaxConvexHulls(10u); + mesh.SetConvexDecomposition(convexDecomp); + sdf::ElementPtr elem = mesh.ToElement(); ASSERT_NE(nullptr, elem); @@ -337,6 +359,8 @@ TEST(DOMMesh, ToElement) EXPECT_EQ(mesh.Scale(), mesh2.Scale()); EXPECT_EQ(mesh.Submesh(), mesh2.Submesh()); EXPECT_EQ(mesh.CenterSubmesh(), mesh2.CenterSubmesh()); + ASSERT_NE(nullptr, mesh2.ConvexDecomposition()); + EXPECT_EQ(10u, mesh2.ConvexDecomposition()->MaxConvexHulls()); } ///////////////////////////////////////////////// @@ -374,6 +398,7 @@ TEST(DOMMesh, ToElementErrorOutput) EXPECT_EQ(mesh.OptimizationStr(), mesh2.OptimizationStr()); EXPECT_EQ(mesh.Optimization(), mesh2.Optimization()); + EXPECT_EQ(nullptr, mesh2.ConvexDecomposition()); 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 30bcb1f7b..297d1f0af 100644 --- a/test/integration/geometry_dom.cc +++ b/test/integration/geometry_dom.cc @@ -179,9 +179,11 @@ 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->OptimizationStr()); - EXPECT_EQ(sdf::MeshOptimization::CONVEX_HULL, + EXPECT_EQ("convex_decomposition", meshColGeom->OptimizationStr()); + EXPECT_EQ(sdf::MeshOptimization::CONVEX_DECOMPOSITION, meshColGeom->Optimization()); + ASSERT_NE(nullptr, meshColGeom->ConvexDecomposition()); + EXPECT_EQ(4u, meshColGeom->ConvexDecomposition()->MaxConvexHulls()); EXPECT_EQ("https://fuel.gazebosim.org/1.0/an_org/models/a_model/mesh/" "mesh.dae", meshColGeom->Uri()); diff --git a/test/sdf/shapes.sdf b/test/sdf/shapes.sdf index bfa50c934..f411afa37 100644 --- a/test/sdf/shapes.sdf +++ b/test/sdf/shapes.sdf @@ -120,7 +120,10 @@ - + + + 4 + https://fuel.gazebosim.org/1.0/an_org/models/a_model/mesh/mesh.dae my_submesh From f82be1f92390c6b2795bd18ae49875fb6ddb638a Mon Sep 17 00:00:00 2001 From: Ian Chen Date: Wed, 20 Mar 2024 17:43:14 +0000 Subject: [PATCH 6/7] coverage Signed-off-by: Ian Chen --- include/sdf/Mesh.hh | 2 +- src/Mesh_TEST.cc | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/sdf/Mesh.hh b/include/sdf/Mesh.hh index 5fc3a34f4..7cc48c955 100644 --- a/include/sdf/Mesh.hh +++ b/include/sdf/Mesh.hh @@ -120,7 +120,7 @@ namespace sdf /// \param[in] _optimization The mesh optimization method. /// \return True if the _optimizationStr parameter matched a known /// mesh optimization method. False if the mesh optimization method - /// could not be set. + /// could not be set. public: bool SetOptimization(const std::string &_optimizationStr); /// \brief Get the associated ConvexDecomposition object diff --git a/src/Mesh_TEST.cc b/src/Mesh_TEST.cc index c7095559d..ad45d77cc 100644 --- a/src/Mesh_TEST.cc +++ b/src/Mesh_TEST.cc @@ -48,7 +48,7 @@ TEST(DOMMesh, Construction) TEST(DOMMesh, MoveConstructor) { sdf::Mesh mesh; - mesh.SetOptimization("convex_decomposition"); + EXPECT_TRUE(mesh.SetOptimization("convex_decomposition")); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); @@ -56,6 +56,7 @@ TEST(DOMMesh, MoveConstructor) mesh.SetFilePath("/pear"); sdf::ConvexDecomposition convexDecomp; + EXPECT_EQ(nullptr, convexDecomp.Element()); convexDecomp.SetMaxConvexHulls(10u); mesh.SetConvexDecomposition(convexDecomp); @@ -77,7 +78,7 @@ TEST(DOMMesh, MoveConstructor) TEST(DOMMesh, CopyConstructor) { sdf::Mesh mesh; - mesh.SetOptimization("convex_hull"); + EXPECT_TRUE(mesh.SetOptimization("convex_hull")); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); @@ -99,7 +100,7 @@ TEST(DOMMesh, CopyConstructor) TEST(DOMMesh, CopyAssignmentOperator) { sdf::Mesh mesh; - mesh.SetOptimization("convex_hull"); + EXPECT_TRUE(mesh.SetOptimization("convex_hull")); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); @@ -122,7 +123,7 @@ TEST(DOMMesh, CopyAssignmentOperator) TEST(DOMMesh, MoveAssignmentOperator) { sdf::Mesh mesh; - mesh.SetOptimization("convex_hull"); + EXPECT_TRUE(mesh.SetOptimization("convex_hull")); mesh.SetUri("banana"); mesh.SetSubmesh("watermelon"); mesh.SetCenterSubmesh(true); @@ -167,13 +168,14 @@ TEST(DOMMesh, Set) EXPECT_EQ(nullptr, mesh.Element()); EXPECT_EQ(std::string(), mesh.OptimizationStr()); - mesh.SetOptimization("convex_hull"); + EXPECT_TRUE(mesh.SetOptimization("convex_hull")); EXPECT_EQ("convex_hull", mesh.OptimizationStr()); EXPECT_EQ(sdf::MeshOptimization::CONVEX_HULL, mesh.Optimization()); mesh.SetOptimization(sdf::MeshOptimization::CONVEX_DECOMPOSITION); EXPECT_EQ("convex_decomposition", mesh.OptimizationStr()); EXPECT_EQ(sdf::MeshOptimization::CONVEX_DECOMPOSITION, mesh.Optimization()); + EXPECT_FALSE(mesh.SetOptimization("invalid")); sdf::ConvexDecomposition convexDecomp; convexDecomp.SetMaxConvexHulls(10u); @@ -337,7 +339,7 @@ TEST(DOMMesh, ToElement) { sdf::Mesh mesh; - mesh.SetOptimization("convex_decomposition"); + EXPECT_TRUE(mesh.SetOptimization("convex_decomposition")); mesh.SetUri("mesh-uri"); mesh.SetScale(gz::math::Vector3d(1, 2, 3)); mesh.SetSubmesh("submesh"); @@ -382,7 +384,7 @@ TEST(DOMMesh, ToElementErrorOutput) sdf::Mesh mesh; sdf::Errors errors; - mesh.SetOptimization("convex_hull"); + EXPECT_TRUE(mesh.SetOptimization("convex_hull")); mesh.SetUri("mesh-uri"); mesh.SetScale(gz::math::Vector3d(1, 2, 3)); mesh.SetSubmesh("submesh"); From 1b0736ea2a90a6bb068b90edc8df2a4d0787896a Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Wed, 20 Mar 2024 16:50:03 -0700 Subject: [PATCH 7/7] Mesh_TEST: improve coverage Signed-off-by: Steve Peters --- src/Mesh_TEST.cc | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/Mesh_TEST.cc b/src/Mesh_TEST.cc index ad45d77cc..29ef70d85 100644 --- a/src/Mesh_TEST.cc +++ b/src/Mesh_TEST.cc @@ -175,7 +175,14 @@ TEST(DOMMesh, Set) EXPECT_EQ("convex_decomposition", mesh.OptimizationStr()); EXPECT_EQ(sdf::MeshOptimization::CONVEX_DECOMPOSITION, mesh.Optimization()); + // check invalid inputs EXPECT_FALSE(mesh.SetOptimization("invalid")); + { + auto invalidMeshOpt = static_cast(99); + mesh.SetOptimization(invalidMeshOpt); + EXPECT_EQ(invalidMeshOpt, mesh.Optimization()); + EXPECT_EQ("", mesh.OptimizationStr()); + } sdf::ConvexDecomposition convexDecomp; convexDecomp.SetMaxConvexHulls(10u); @@ -208,6 +215,7 @@ TEST(DOMMesh, Set) TEST(DOMMesh, Load) { sdf::Mesh mesh; + sdf::ConvexDecomposition convexDecomp; sdf::Errors errors; // Null element name @@ -216,6 +224,11 @@ TEST(DOMMesh, Load) EXPECT_EQ(sdf::ErrorCode::ELEMENT_MISSING, errors[0].Code()); EXPECT_EQ(nullptr, mesh.Element()); + errors = convexDecomp.Load(nullptr); + ASSERT_EQ(1u, errors.size()); + EXPECT_EQ(sdf::ErrorCode::ELEMENT_MISSING, errors[0].Code()); + EXPECT_EQ(nullptr, convexDecomp.Element()); + // Bad element name sdf::ElementPtr sdf(new sdf::Element()); sdf->SetName("bad"); @@ -224,6 +237,11 @@ TEST(DOMMesh, Load) EXPECT_EQ(sdf::ErrorCode::ELEMENT_INCORRECT_TYPE, errors[0].Code()); EXPECT_NE(nullptr, mesh.Element()); + errors = convexDecomp.Load(sdf); + ASSERT_EQ(1u, errors.size()); + EXPECT_EQ(sdf::ErrorCode::ELEMENT_INCORRECT_TYPE, errors[0].Code()); + EXPECT_NE(nullptr, convexDecomp.Element()); + // Missing element sdf->SetName("mesh"); errors = mesh.Load(sdf);