Skip to content

Commit e5c8c2c

Browse files
authored
Allow negative scale for MeshShape (#1841)
1 parent 9feb578 commit e5c8c2c

File tree

3 files changed

+42
-31
lines changed

3 files changed

+42
-31
lines changed

dart/dynamics/MeshShape.cpp

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -236,15 +236,19 @@ void MeshShape::setMesh(
236236
//==============================================================================
237237
void MeshShape::setScale(const Eigen::Vector3d& scale)
238238
{
239-
assert((scale.array() > 0.0).all());
240-
241239
mScale = scale;
242240
mIsBoundingBoxDirty = true;
243241
mIsVolumeDirty = true;
244242

245243
incrementVersion();
246244
}
247245

246+
//==============================================================================
247+
void MeshShape::setScale(const double scale)
248+
{
249+
setScale(Eigen::Vector3d::Constant(scale));
250+
}
251+
248252
//==============================================================================
249253
const Eigen::Vector3d& MeshShape::getScale() const
250254
{
@@ -332,33 +336,21 @@ void MeshShape::updateBoundingBox() const
332336
return;
333337
}
334338

335-
double max_X = -std::numeric_limits<double>::infinity();
336-
double max_Y = -std::numeric_limits<double>::infinity();
337-
double max_Z = -std::numeric_limits<double>::infinity();
338-
double min_X = std::numeric_limits<double>::infinity();
339-
double min_Y = std::numeric_limits<double>::infinity();
340-
double min_Z = std::numeric_limits<double>::infinity();
341-
342-
for (unsigned int i = 0; i < mMesh->mNumMeshes; i++) {
343-
for (unsigned int j = 0; j < mMesh->mMeshes[i]->mNumVertices; j++) {
344-
if (mMesh->mMeshes[i]->mVertices[j].x > max_X)
345-
max_X = mMesh->mMeshes[i]->mVertices[j].x;
346-
if (mMesh->mMeshes[i]->mVertices[j].x < min_X)
347-
min_X = mMesh->mMeshes[i]->mVertices[j].x;
348-
if (mMesh->mMeshes[i]->mVertices[j].y > max_Y)
349-
max_Y = mMesh->mMeshes[i]->mVertices[j].y;
350-
if (mMesh->mMeshes[i]->mVertices[j].y < min_Y)
351-
min_Y = mMesh->mMeshes[i]->mVertices[j].y;
352-
if (mMesh->mMeshes[i]->mVertices[j].z > max_Z)
353-
max_Z = mMesh->mMeshes[i]->mVertices[j].z;
354-
if (mMesh->mMeshes[i]->mVertices[j].z < min_Z)
355-
min_Z = mMesh->mMeshes[i]->mVertices[j].z;
339+
Eigen::Vector3d minPoint
340+
= Eigen::Vector3d::Constant(std::numeric_limits<double>::infinity());
341+
Eigen::Vector3d maxPoint = -minPoint;
342+
343+
for (unsigned i = 0u; i < mMesh->mNumMeshes; i++) {
344+
for (unsigned j = 0u; j < mMesh->mMeshes[i]->mNumVertices; j++) {
345+
const auto& vertex = mMesh->mMeshes[i]->mVertices[j];
346+
const Eigen::Vector3d eigenVertex(vertex.x, vertex.y, vertex.z);
347+
minPoint = minPoint.cwiseMin(eigenVertex.cwiseProduct(mScale));
348+
maxPoint = maxPoint.cwiseMax(eigenVertex.cwiseProduct(mScale));
356349
}
357350
}
358-
mBoundingBox.setMin(
359-
Eigen::Vector3d(min_X * mScale[0], min_Y * mScale[1], min_Z * mScale[2]));
360-
mBoundingBox.setMax(
361-
Eigen::Vector3d(max_X * mScale[0], max_Y * mScale[1], max_Z * mScale[2]));
351+
352+
mBoundingBox.setMin(minPoint);
353+
mBoundingBox.setMax(maxPoint);
362354

363355
mIsBoundingBoxDirty = false;
364356
}

dart/dynamics/MeshShape.hpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,24 @@ class MeshShape : public Shape
124124

125125
common::ResourceRetrieverPtr getResourceRetriever();
126126

127+
/// Sets the scale of the object using a 3D vector.
128+
///
129+
/// The scale is applied independently along each axis (x, y, z). Negative
130+
/// values will mirror the object along the corresponding axis, potentially
131+
/// flipping normals and causing inside-out geometry.
132+
///
133+
/// Use caution when applying negative scales as it may affect rendering and
134+
/// physics calculations.
127135
void setScale(const Eigen::Vector3d& scale);
128136

137+
/// Sets a uniform scale for the object across all axes.
138+
void setScale(double scale);
139+
140+
/// Returns the current scale of the object as a 3D vector.
141+
///
142+
/// Each component of the vector represents the scale factor along the
143+
/// corresponding axis (x, y, z). Negative values indicate that the object has
144+
/// been mirrored along that axis.
129145
const Eigen::Vector3d& getScale() const;
130146

131147
/// Set how the color of this mesh should be determined

python/dartpy/dynamics/Shape.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -399,10 +399,13 @@ void Shape(py::module& m)
399399
})
400400
.def(
401401
"setScale",
402-
+[](dart::dynamics::MeshShape* self, const Eigen::Vector3d& scale) {
403-
self->setScale(scale);
404-
},
405-
::py::arg("scale"))
402+
py::overload_cast<const Eigen::Vector3d&>(
403+
&dart::dynamics::MeshShape::setScale),
404+
py::arg("scale"))
405+
.def(
406+
"setScale",
407+
py::overload_cast<double>(&dart::dynamics::MeshShape::setScale),
408+
py::arg("scale"))
406409
.def(
407410
"getScale",
408411
+[](const dart::dynamics::MeshShape* self) -> const Eigen::Vector3d& {

0 commit comments

Comments
 (0)