Fix wrong extent authoring for Cube.

PiperOrigin-RevId: 779230125
Change-Id: I96c3d5daa7a760cd87a714a14ea74a15faf3d7db
This commit is contained in:
Robin Alazard
2025-07-04 10:38:41 -07:00
committed by Copybara-Service
parent 21a852504c
commit e69b6cc5f3
2 changed files with 35 additions and 28 deletions
@@ -337,8 +337,8 @@ class ModelWriter {
} }
void WriteMesh(const mjsMesh *mesh, const pxr::SdfPath &parent_path) { void WriteMesh(const mjsMesh *mesh, const pxr::SdfPath &parent_path) {
auto name = GetAvailablePrimName(*mjs_getName(mesh->element), pxr::UsdGeomTokens->Mesh, auto name = GetAvailablePrimName(*mjs_getName(mesh->element),
parent_path); pxr::UsdGeomTokens->Mesh, parent_path);
pxr::SdfPath subcomponent_path = pxr::SdfPath subcomponent_path =
CreatePrimSpec(data_, parent_path, name, pxr::UsdGeomTokens->Xform); CreatePrimSpec(data_, parent_path, name, pxr::UsdGeomTokens->Xform);
pxr::SdfPath mesh_path = pxr::SdfPath mesh_path =
@@ -967,44 +967,50 @@ class ModelWriter {
pxr::SdfPath qpos_attr_path = pxr::SdfPath qpos_attr_path =
CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcQpos, CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcQpos,
pxr::SdfValueTypeNames->DoubleArray); pxr::SdfValueTypeNames->DoubleArray);
set_attribute_data(qpos_attr_path, set_attribute_data(
pxr::VtDoubleArray(keyframe->qpos->begin(), qpos_attr_path,
keyframe->qpos->end()), keyframe); pxr::VtDoubleArray(keyframe->qpos->begin(), keyframe->qpos->end()),
keyframe);
pxr::SdfPath qvel_attr_path = pxr::SdfPath qvel_attr_path =
CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcQvel, CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcQvel,
pxr::SdfValueTypeNames->DoubleArray); pxr::SdfValueTypeNames->DoubleArray);
set_attribute_data(qvel_attr_path, set_attribute_data(
pxr::VtDoubleArray(keyframe->qvel->begin(), qvel_attr_path,
keyframe->qvel->end()), keyframe); pxr::VtDoubleArray(keyframe->qvel->begin(), keyframe->qvel->end()),
keyframe);
pxr::SdfPath act_attr_path = pxr::SdfPath act_attr_path =
CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcAct, CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcAct,
pxr::SdfValueTypeNames->DoubleArray); pxr::SdfValueTypeNames->DoubleArray);
set_attribute_data(act_attr_path, set_attribute_data(
pxr::VtDoubleArray(keyframe->act->begin(), act_attr_path,
keyframe->act->end()), keyframe); pxr::VtDoubleArray(keyframe->act->begin(), keyframe->act->end()),
keyframe);
pxr::SdfPath ctrl_attr_path = pxr::SdfPath ctrl_attr_path =
CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcCtrl, CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcCtrl,
pxr::SdfValueTypeNames->DoubleArray); pxr::SdfValueTypeNames->DoubleArray);
set_attribute_data(ctrl_attr_path, set_attribute_data(
pxr::VtDoubleArray(keyframe->ctrl->begin(), ctrl_attr_path,
keyframe->ctrl->end()), keyframe); pxr::VtDoubleArray(keyframe->ctrl->begin(), keyframe->ctrl->end()),
keyframe);
pxr::SdfPath mpos_attr_path = pxr::SdfPath mpos_attr_path =
CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcMpos, CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcMpos,
pxr::SdfValueTypeNames->DoubleArray); pxr::SdfValueTypeNames->DoubleArray);
set_attribute_data(mpos_attr_path, set_attribute_data(
pxr::VtDoubleArray(keyframe->mpos->begin(), mpos_attr_path,
keyframe->mpos->end()), keyframe); pxr::VtDoubleArray(keyframe->mpos->begin(), keyframe->mpos->end()),
keyframe);
pxr::SdfPath mquat_attr_path = pxr::SdfPath mquat_attr_path =
CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcMquat, CreateAttributeSpec(data_, keyframe_path, MjcPhysicsTokens->mjcMquat,
pxr::SdfValueTypeNames->DoubleArray); pxr::SdfValueTypeNames->DoubleArray);
set_attribute_data(mquat_attr_path, set_attribute_data(
pxr::VtDoubleArray(keyframe->mquat->begin(), mquat_attr_path,
keyframe->mquat->end()), keyframe); pxr::VtDoubleArray(keyframe->mquat->begin(), keyframe->mquat->end()),
keyframe);
} }
} }
@@ -1235,23 +1241,22 @@ class ModelWriter {
const pxr::SdfPath &body_path) { const pxr::SdfPath &body_path) {
pxr::SdfPath box_path = pxr::SdfPath box_path =
CreatePrimSpec(data_, body_path, name, pxr::UsdGeomTokens->Cube); CreatePrimSpec(data_, body_path, name, pxr::UsdGeomTokens->Cube);
// MuJoCo uses half sizes. // MuJoCo uses half sizes. Always set size to 2 (and correspondingly extent
// from -1 to 1), and let scale determine the actual size.
pxr::SdfPath size_attr_path = pxr::SdfPath size_attr_path =
CreateAttributeSpec(data_, box_path, pxr::UsdGeomTokens->size, CreateAttributeSpec(data_, box_path, pxr::UsdGeomTokens->size,
pxr::SdfValueTypeNames->Double); pxr::SdfValueTypeNames->Double);
pxr::GfVec3f scale(static_cast<float>(size[0]), static_cast<float>(size[1]),
static_cast<float>(size[2]));
SetAttributeDefault(data_, size_attr_path, 2.0); SetAttributeDefault(data_, size_attr_path, 2.0);
pxr::SdfPath extent_attr_path = pxr::SdfPath extent_attr_path =
CreateAttributeSpec(data_, box_path, pxr::UsdGeomTokens->extent, CreateAttributeSpec(data_, box_path, pxr::UsdGeomTokens->extent,
pxr::SdfValueTypeNames->Float3Array); pxr::SdfValueTypeNames->Float3Array);
SetAttributeDefault(data_, extent_attr_path, SetAttributeDefault(data_, extent_attr_path,
pxr::VtArray<pxr::GfVec3f>({ pxr::VtArray<pxr::GfVec3f>(
pxr::GfVec3f(-size[0], -size[1], -size[2]), {pxr::GfVec3f(-1, -1, -1), pxr::GfVec3f(1, 1, 1)}));
pxr::GfVec3f(size[0], size[1], size[2]),
}));
pxr::GfVec3f scale(static_cast<float>(size[0]), static_cast<float>(size[1]),
static_cast<float>(size[2]));
WriteScaleXformOp(box_path, scale); WriteScaleXformOp(box_path, scale);
WriteXformOpOrder(box_path, WriteXformOpOrder(box_path,
pxr::VtArray<pxr::TfToken>{kTokens->xformOpScale}); pxr::VtArray<pxr::TfToken>{kTokens->xformOpScale});
@@ -619,8 +619,10 @@ TEST_F(MjcfSdfFileFormatPluginTest, TestGeomsPrims) {
EXPECT_PRIM_VALID(stage, "/test/box_geom"); EXPECT_PRIM_VALID(stage, "/test/box_geom");
EXPECT_PRIM_IS_A(stage, "/test/box_geom", pxr::UsdGeomCube); EXPECT_PRIM_IS_A(stage, "/test/box_geom", pxr::UsdGeomCube);
// Box is a special case, it uses a UsdGeomCube and scales it with // Box is a special case, it uses a UsdGeomCube and scales it with
// xformOp:scale. The radius is always set to 2. // xformOp:scale. The radius is always set to 2 and the extent from -1 to 1.
ExpectAttributeEqual(stage, "/test/box_geom.size", 2.0); ExpectAttributeEqual(stage, "/test/box_geom.size", 2.0);
ExpectAttributeEqual(stage, "/test/box_geom.extent",
pxr::VtArray<pxr::GfVec3f>({{-1, -1, -1}, {1, 1, 1}}));
ExpectAttributeEqual(stage, "/test/box_geom.xformOp:scale", ExpectAttributeEqual(stage, "/test/box_geom.xformOp:scale",
pxr::GfVec3f(10.0, 20.0, 30.0)); pxr::GfVec3f(10.0, 20.0, 30.0));
// Sphere // Sphere