diff --git a/include/mujoco/experimental/usd/mjcPhysics/meshCollisionAPI.h b/include/mujoco/experimental/usd/mjcPhysics/meshCollisionAPI.h
index b01756e4..653e6ecd 100644
--- a/include/mujoco/experimental/usd/mjcPhysics/meshCollisionAPI.h
+++ b/include/mujoco/experimental/usd/mjcPhysics/meshCollisionAPI.h
@@ -40,7 +40,7 @@ class SdfAssetPath;
/// \class MjcPhysicsMeshCollisionAPI
///
-/// API describing a Mujoco mesh collider.
+/// API describing a MuJoCo mesh collider.
///
/// For any described attribute \em Fallback \em Value or \em Allowed \em Values
/// below that are text/tokens, the actual token is published and defined in
@@ -173,6 +173,31 @@ class MjcPhysicsMeshCollisionAPI : public UsdAPISchemaBase {
UsdAttribute CreateInertiaAttr(VtValue const &defaultValue = VtValue(),
bool writeSparsely = false) const;
+ public:
+ // --------------------------------------------------------------------- //
+ // MAXHULLVERT
+ // --------------------------------------------------------------------- //
+ /// Sets an upper limit on the number of vertices in the meshes convex hull.
+ /// The default value of -1 means unlimited.
+ ///
+ /// | ||
+ /// | -- | -- |
+ /// | Declaration | `uniform int mjc:maxhullvert = -1` |
+ /// | C++ Type | int |
+ /// | \ref Usd_Datatypes "Usd Type" | SdfValueTypeNames->Int |
+ /// | \ref SdfVariability "Variability" | SdfVariabilityUniform |
+ MJCPHYSICS_API
+ UsdAttribute GetMaxHullVertAttr() const;
+
+ /// See GetMaxHullVertAttr(), and also
+ /// \ref Usd_Create_Or_Get_Property for when to use Get vs Create.
+ /// If specified, author \p defaultValue as the attribute's default,
+ /// sparsely (when it makes sense to do so) if \p writeSparsely is \c true -
+ /// the default for \p writeSparsely is \c false.
+ MJCPHYSICS_API
+ UsdAttribute CreateMaxHullVertAttr(VtValue const &defaultValue = VtValue(),
+ bool writeSparsely = false) const;
+
public:
// ===================================================================== //
// Feel free to add custom code below this line, it will be preserved by
diff --git a/include/mujoco/experimental/usd/mjcPhysics/tokens.h b/include/mujoco/experimental/usd/mjcPhysics/tokens.h
index af49243b..46ff1ad3 100644
--- a/include/mujoco/experimental/usd/mjcPhysics/tokens.h
+++ b/include/mujoco/experimental/usd/mjcPhysics/tokens.h
@@ -356,6 +356,10 @@ struct MjcPhysicsTokensType {
///
/// MjcPhysicsJointAPI
const TfToken mjcMargin;
+ /// \brief "mjc:maxhullvert"
+ ///
+ /// MjcPhysicsMeshCollisionAPI
+ const TfToken mjcMaxhullvert;
/// \brief "mjc:mpos"
///
/// MjcPhysicsKeyframe
diff --git a/src/experimental/usd/mjcPhysics/generatedSchema.usda b/src/experimental/usd/mjcPhysics/generatedSchema.usda
index d4b0b733..5efaff73 100644
--- a/src/experimental/usd/mjcPhysics/generatedSchema.usda
+++ b/src/experimental/usd/mjcPhysics/generatedSchema.usda
@@ -245,6 +245,10 @@ class "MjcMeshCollisionAPI" (
displayName = "Inertia"
doc = "Controls how a mesh is used when mass and inertia are inferred from geometry."
)
+ uniform int mjc:maxhullvert = -1 (
+ displayName = "Maximum Hull Vertices"
+ doc = "Sets an upper limit on the number of vertices in the meshes convex hull. The default value of -1 means unlimited."
+ )
}
class "MjcActuatorAPI" (
diff --git a/src/experimental/usd/mjcPhysics/meshCollisionAPI.cpp b/src/experimental/usd/mjcPhysics/meshCollisionAPI.cpp
index 9d9b00dc..e8db13f4 100644
--- a/src/experimental/usd/mjcPhysics/meshCollisionAPI.cpp
+++ b/src/experimental/usd/mjcPhysics/meshCollisionAPI.cpp
@@ -88,6 +88,17 @@ UsdAttribute MjcPhysicsMeshCollisionAPI::CreateInertiaAttr(
/* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely);
}
+UsdAttribute MjcPhysicsMeshCollisionAPI::GetMaxHullVertAttr() const {
+ return GetPrim().GetAttribute(MjcPhysicsTokens->mjcMaxhullvert);
+}
+
+UsdAttribute MjcPhysicsMeshCollisionAPI::CreateMaxHullVertAttr(
+ VtValue const &defaultValue, bool writeSparsely) const {
+ return UsdSchemaBase::_CreateAttr(
+ MjcPhysicsTokens->mjcMaxhullvert, SdfValueTypeNames->Int,
+ /* custom = */ false, SdfVariabilityUniform, defaultValue, writeSparsely);
+}
+
namespace {
static inline TfTokenVector _ConcatenateAttributeNames(
const TfTokenVector &left, const TfTokenVector &right) {
@@ -104,6 +115,7 @@ const TfTokenVector &MjcPhysicsMeshCollisionAPI::GetSchemaAttributeNames(
bool includeInherited) {
static TfTokenVector localNames = {
MjcPhysicsTokens->mjcInertia,
+ MjcPhysicsTokens->mjcMaxhullvert,
};
static TfTokenVector allNames = _ConcatenateAttributeNames(
UsdAPISchemaBase::GetSchemaAttributeNames(true), localNames);
diff --git a/src/experimental/usd/mjcPhysics/schema.usda b/src/experimental/usd/mjcPhysics/schema.usda
index cf27ceb5..e55a6f78 100644
--- a/src/experimental/usd/mjcPhysics/schema.usda
+++ b/src/experimental/usd/mjcPhysics/schema.usda
@@ -559,6 +559,14 @@ class "MjcMeshCollisionAPI"
displayName = "Inertia"
doc = """Controls how a mesh is used when mass and inertia are inferred from geometry."""
)
+
+ uniform int mjc:maxhullvert = -1 (
+ customData = {
+ string apiName = "MaxHullVert"
+ }
+ displayName = "Maximum Hull Vertices"
+ doc = """Sets an upper limit on the number of vertices in the meshes convex hull. The default value of -1 means unlimited."""
+ )
}
class "MjcActuatorAPI"
diff --git a/src/experimental/usd/mjcPhysics/tokens.cpp b/src/experimental/usd/mjcPhysics/tokens.cpp
index 11235ab2..433ed2f1 100644
--- a/src/experimental/usd/mjcPhysics/tokens.cpp
+++ b/src/experimental/usd/mjcPhysics/tokens.cpp
@@ -89,6 +89,7 @@ MjcPhysicsTokensType::MjcPhysicsTokensType()
mjcLengthRangeMax("mjc:lengthRange:max", TfToken::Immortal),
mjcLengthRangeMin("mjc:lengthRange:min", TfToken::Immortal),
mjcMargin("mjc:margin", TfToken::Immortal),
+ mjcMaxhullvert("mjc:maxhullvert", TfToken::Immortal),
mjcMpos("mjc:mpos", TfToken::Immortal),
mjcMquat("mjc:mquat", TfToken::Immortal),
mjcOptionActuatorgroupdisable("mjc:option:actuatorgroupdisable",
@@ -222,6 +223,7 @@ MjcPhysicsTokensType::MjcPhysicsTokensType()
mjcLengthRangeMax,
mjcLengthRangeMin,
mjcMargin,
+ mjcMaxhullvert,
mjcMpos,
mjcMquat,
mjcOptionActuatorgroupdisable,
diff --git a/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc b/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc
index d15c17d0..86c0fa9f 100644
--- a/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc
+++ b/src/experimental/usd/plugins/mjcf/mujoco_to_usd.cc
@@ -360,6 +360,10 @@ class ModelWriter {
WriteUniformAttribute(mesh_path, pxr::SdfValueTypeNames->Token,
MjcPhysicsTokens->mjcInertia, inertia);
+
+ WriteUniformAttribute(mesh_path, pxr::SdfValueTypeNames->Int,
+ MjcPhysicsTokens->mjcMaxhullvert,
+ mesh->maxhullvert);
}
// NOTE: The geometry data taken from the spec is the post-compilation
diff --git a/src/experimental/usd/usd_to_mjspec.cc b/src/experimental/usd/usd_to_mjspec.cc
index c923384c..394965b2 100644
--- a/src/experimental/usd/usd_to_mjspec.cc
+++ b/src/experimental/usd/usd_to_mjspec.cc
@@ -546,6 +546,11 @@ void ParseMjcPhysicsMeshCollisionAPI(
mesh->inertia = mjtMeshInertia::mjMESH_INERTIA_LEGACY;
}
}
+
+ auto maxhullvert_attr = mesh_collision_api.GetMaxHullVertAttr();
+ if (maxhullvert_attr.HasAuthoredValue()) {
+ maxhullvert_attr.Get(&mesh->maxhullvert);
+ }
}
void ParseMjcPhysicsGeneralActuatorAPI(mjSpec* spec,
diff --git a/test/experimental/usd/plugins/mjcf/mjcf_file_format_test.cc b/test/experimental/usd/plugins/mjcf/mjcf_file_format_test.cc
index 65c4b8dc..17204cf2 100644
--- a/test/experimental/usd/plugins/mjcf/mjcf_file_format_test.cc
+++ b/test/experimental/usd/plugins/mjcf/mjcf_file_format_test.cc
@@ -1440,6 +1440,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsMeshCollisionAPI) {
+
@@ -1447,6 +1448,7 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsMeshCollisionAPI) {
+
@@ -1461,6 +1463,8 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestMjcPhysicsMeshCollisionAPI) {
MjcPhysicsTokens->convex);
ExpectAttributeEqual(stage, "/test/body/tet_shell/Mesh.mjc:inertia",
MjcPhysicsTokens->shell);
+ ExpectAttributeEqual(stage, "/test/body/tet_max_vert/Mesh.mjc:maxhullvert",
+ 12);
}
TEST_F(MjcfSdfFileFormatPluginTest, TestMassAPIApplied) {