From e5c8c2c9910a8a9a6e4ccd775546b238f00d4ee0 Mon Sep 17 00:00:00 2001 From: "Jeongseok (JS) Lee" Date: Mon, 2 Sep 2024 19:50:41 -0700 Subject: [PATCH] Allow negative scale for MeshShape (#1841) --- dart/dynamics/MeshShape.cpp | 46 +++++++++++++------------------- dart/dynamics/MeshShape.hpp | 16 +++++++++++ python/dartpy/dynamics/Shape.cpp | 11 +++++--- 3 files changed, 42 insertions(+), 31 deletions(-) diff --git a/dart/dynamics/MeshShape.cpp b/dart/dynamics/MeshShape.cpp index e960b4e971a90..de95aad749ad6 100644 --- a/dart/dynamics/MeshShape.cpp +++ b/dart/dynamics/MeshShape.cpp @@ -236,8 +236,6 @@ void MeshShape::setMesh( //============================================================================== void MeshShape::setScale(const Eigen::Vector3d& scale) { - assert((scale.array() > 0.0).all()); - mScale = scale; mIsBoundingBoxDirty = true; mIsVolumeDirty = true; @@ -245,6 +243,12 @@ void MeshShape::setScale(const Eigen::Vector3d& scale) incrementVersion(); } +//============================================================================== +void MeshShape::setScale(const double scale) +{ + setScale(Eigen::Vector3d::Constant(scale)); +} + //============================================================================== const Eigen::Vector3d& MeshShape::getScale() const { @@ -332,33 +336,21 @@ void MeshShape::updateBoundingBox() const return; } - double max_X = -std::numeric_limits::infinity(); - double max_Y = -std::numeric_limits::infinity(); - double max_Z = -std::numeric_limits::infinity(); - double min_X = std::numeric_limits::infinity(); - double min_Y = std::numeric_limits::infinity(); - double min_Z = std::numeric_limits::infinity(); - - for (unsigned int i = 0; i < mMesh->mNumMeshes; i++) { - for (unsigned int j = 0; j < mMesh->mMeshes[i]->mNumVertices; j++) { - if (mMesh->mMeshes[i]->mVertices[j].x > max_X) - max_X = mMesh->mMeshes[i]->mVertices[j].x; - if (mMesh->mMeshes[i]->mVertices[j].x < min_X) - min_X = mMesh->mMeshes[i]->mVertices[j].x; - if (mMesh->mMeshes[i]->mVertices[j].y > max_Y) - max_Y = mMesh->mMeshes[i]->mVertices[j].y; - if (mMesh->mMeshes[i]->mVertices[j].y < min_Y) - min_Y = mMesh->mMeshes[i]->mVertices[j].y; - if (mMesh->mMeshes[i]->mVertices[j].z > max_Z) - max_Z = mMesh->mMeshes[i]->mVertices[j].z; - if (mMesh->mMeshes[i]->mVertices[j].z < min_Z) - min_Z = mMesh->mMeshes[i]->mVertices[j].z; + Eigen::Vector3d minPoint + = Eigen::Vector3d::Constant(std::numeric_limits::infinity()); + Eigen::Vector3d maxPoint = -minPoint; + + for (unsigned i = 0u; i < mMesh->mNumMeshes; i++) { + for (unsigned j = 0u; j < mMesh->mMeshes[i]->mNumVertices; j++) { + const auto& vertex = mMesh->mMeshes[i]->mVertices[j]; + const Eigen::Vector3d eigenVertex(vertex.x, vertex.y, vertex.z); + minPoint = minPoint.cwiseMin(eigenVertex.cwiseProduct(mScale)); + maxPoint = maxPoint.cwiseMax(eigenVertex.cwiseProduct(mScale)); } } - mBoundingBox.setMin( - Eigen::Vector3d(min_X * mScale[0], min_Y * mScale[1], min_Z * mScale[2])); - mBoundingBox.setMax( - Eigen::Vector3d(max_X * mScale[0], max_Y * mScale[1], max_Z * mScale[2])); + + mBoundingBox.setMin(minPoint); + mBoundingBox.setMax(maxPoint); mIsBoundingBoxDirty = false; } diff --git a/dart/dynamics/MeshShape.hpp b/dart/dynamics/MeshShape.hpp index acf4b9e39c84b..c2dd54dd3b4e9 100644 --- a/dart/dynamics/MeshShape.hpp +++ b/dart/dynamics/MeshShape.hpp @@ -124,8 +124,24 @@ class MeshShape : public Shape common::ResourceRetrieverPtr getResourceRetriever(); + /// Sets the scale of the object using a 3D vector. + /// + /// The scale is applied independently along each axis (x, y, z). Negative + /// values will mirror the object along the corresponding axis, potentially + /// flipping normals and causing inside-out geometry. + /// + /// Use caution when applying negative scales as it may affect rendering and + /// physics calculations. void setScale(const Eigen::Vector3d& scale); + /// Sets a uniform scale for the object across all axes. + void setScale(double scale); + + /// Returns the current scale of the object as a 3D vector. + /// + /// Each component of the vector represents the scale factor along the + /// corresponding axis (x, y, z). Negative values indicate that the object has + /// been mirrored along that axis. const Eigen::Vector3d& getScale() const; /// Set how the color of this mesh should be determined diff --git a/python/dartpy/dynamics/Shape.cpp b/python/dartpy/dynamics/Shape.cpp index bf39f02360cce..ae6d4270a1855 100644 --- a/python/dartpy/dynamics/Shape.cpp +++ b/python/dartpy/dynamics/Shape.cpp @@ -399,10 +399,13 @@ void Shape(py::module& m) }) .def( "setScale", - +[](dart::dynamics::MeshShape* self, const Eigen::Vector3d& scale) { - self->setScale(scale); - }, - ::py::arg("scale")) + py::overload_cast( + &dart::dynamics::MeshShape::setScale), + py::arg("scale")) + .def( + "setScale", + py::overload_cast(&dart::dynamics::MeshShape::setScale), + py::arg("scale")) .def( "getScale", +[](const dart::dynamics::MeshShape* self) -> const Eigen::Vector3d& {