Fix a bug in MuJoCo's user_mesh.cc that caused meshdir_ to be overwritten when a model was loaded with a nested model.
PiperOrigin-RevId: 675092713 Change-Id: Iad6336141749510bf5544cab9c06533ee1589c08
This commit is contained in:
committed by
Copybara-Service
parent
fd17b2144a
commit
c77babe046
+12
-4
@@ -222,8 +222,12 @@ void mjCMesh::PointToLocal() {
|
|||||||
|
|
||||||
void mjCMesh::NameSpace(const mjCModel* m) {
|
void mjCMesh::NameSpace(const mjCModel* m) {
|
||||||
mjCBase::NameSpace(m);
|
mjCBase::NameSpace(m);
|
||||||
modelfiledir_ = FilePath(m->spec_modelfiledir_);
|
if (modelfiledir_.empty()) {
|
||||||
meshdir_ = FilePath(m->spec_meshdir_);
|
modelfiledir_ = FilePath(m->spec_modelfiledir_);
|
||||||
|
}
|
||||||
|
if (meshdir_.empty()) {
|
||||||
|
meshdir_ = FilePath(m->spec_meshdir_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2034,8 +2038,12 @@ void mjCSkin::NameSpace(const mjCModel* m) {
|
|||||||
for (auto& name : spec_bodyname_) {
|
for (auto& name : spec_bodyname_) {
|
||||||
name = m->prefix + name + m->suffix;
|
name = m->prefix + name + m->suffix;
|
||||||
}
|
}
|
||||||
modelfiledir_ = FilePath(m->spec_modelfiledir_);
|
if (modelfiledir_.empty()) {
|
||||||
meshdir_ = FilePath(m->spec_meshdir_);
|
modelfiledir_ = FilePath(m->spec_modelfiledir_);
|
||||||
|
}
|
||||||
|
if (meshdir_.empty()) {
|
||||||
|
meshdir_ = FilePath(m->spec_meshdir_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -607,6 +607,7 @@ mjCModel::~mjCModel() {
|
|||||||
for (int i=0; i<tuples_.size(); i++) delete tuples_[i];
|
for (int i=0; i<tuples_.size(); i++) delete tuples_[i];
|
||||||
for (int i=0; i<keys_.size(); i++) delete keys_[i];
|
for (int i=0; i<keys_.size(); i++) delete keys_[i];
|
||||||
for (int i=0; i<defaults_.size(); i++) delete defaults_[i];
|
for (int i=0; i<defaults_.size(); i++) delete defaults_[i];
|
||||||
|
for (int i=0; i<specs_.size(); i++) mj_deleteSpec(specs_[i]);
|
||||||
|
|
||||||
if (plugin_owner) {
|
if (plugin_owner) {
|
||||||
for (int i=0; i<plugins_.size(); i++) delete plugins_[i];
|
for (int i=0; i<plugins_.size(); i++) delete plugins_[i];
|
||||||
|
|||||||
@@ -3405,8 +3405,12 @@ void mjCHField::CopyFromSpec() {
|
|||||||
|
|
||||||
void mjCHField::NameSpace(const mjCModel* m) {
|
void mjCHField::NameSpace(const mjCModel* m) {
|
||||||
mjCBase::NameSpace(m);
|
mjCBase::NameSpace(m);
|
||||||
modelfiledir_ = FilePath(m->spec_modelfiledir_);
|
if (modelfiledir_.empty()) {
|
||||||
meshdir_ = FilePath(m->spec_meshdir_);
|
modelfiledir_ = FilePath(m->spec_modelfiledir_);
|
||||||
|
}
|
||||||
|
if (meshdir_.empty()) {
|
||||||
|
meshdir_ = FilePath(m->spec_meshdir_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -3650,8 +3654,12 @@ void mjCTexture::CopyFromSpec() {
|
|||||||
|
|
||||||
void mjCTexture::NameSpace(const mjCModel* m) {
|
void mjCTexture::NameSpace(const mjCModel* m) {
|
||||||
mjCBase::NameSpace(m);
|
mjCBase::NameSpace(m);
|
||||||
modelfiledir_ = FilePath(m->spec_modelfiledir_);
|
if (modelfiledir_.empty()) {
|
||||||
texturedir_ = FilePath(m->spec_texturedir_);
|
modelfiledir_ = FilePath(m->spec_modelfiledir_);
|
||||||
|
}
|
||||||
|
if (texturedir_.empty()) {
|
||||||
|
texturedir_ = FilePath(m->spec_texturedir_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3645,7 +3645,6 @@ void mjXReader::Body(XMLElement* section, mjsBody* body, mjsFrame* frame,
|
|||||||
throw mjXError(0, "could not find body '%s''%s'", body_name.c_str());
|
throw mjXError(0, "could not find body '%s''%s'", body_name.c_str());
|
||||||
}
|
}
|
||||||
if (mjs_attachBody(pframe, child, prefix.c_str(), "") != 0) {
|
if (mjs_attachBody(pframe, child, prefix.c_str(), "") != 0) {
|
||||||
mj_deleteSpec(asset);
|
|
||||||
throw mjXError(elem, mjs_getError(spec));
|
throw mjXError(elem, mjs_getError(spec));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -545,5 +545,96 @@ TEST_F(MujocoTest, Modeldir) {
|
|||||||
mj_deleteVFS(vfs.get());
|
mj_deleteVFS(vfs.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(MujocoTest, NestedMeshDir) {
|
||||||
|
static constexpr char cube[] = R"(
|
||||||
|
v -1 -1 1
|
||||||
|
v 1 -1 1
|
||||||
|
v -1 1 1
|
||||||
|
v 1 1 1
|
||||||
|
v -1 1 -1
|
||||||
|
v 1 1 -1
|
||||||
|
v -1 -1 -1
|
||||||
|
v 1 -1 -1)";
|
||||||
|
|
||||||
|
static constexpr char child_xml[] = R"(
|
||||||
|
<mujoco>
|
||||||
|
<compiler meshdir="child_meshdir"/>
|
||||||
|
|
||||||
|
<asset>
|
||||||
|
<mesh name="m" file="child_mesh.obj"/>
|
||||||
|
</asset>
|
||||||
|
|
||||||
|
<worldbody>
|
||||||
|
<body name="child">
|
||||||
|
<geom type="mesh" mesh="m"/>
|
||||||
|
</body>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
|
)";
|
||||||
|
|
||||||
|
static constexpr char parent_xml[] = R"(
|
||||||
|
<mujoco>
|
||||||
|
<compiler meshdir="parent_meshdir"/>
|
||||||
|
|
||||||
|
<asset>
|
||||||
|
<mesh name="m" file="parent_mesh.obj"/>
|
||||||
|
<model name="child" file="child.xml"/>
|
||||||
|
</asset>
|
||||||
|
|
||||||
|
<worldbody>
|
||||||
|
<body name="parent">
|
||||||
|
<geom type="mesh" mesh="m"/>
|
||||||
|
<attach model="child" body="child" prefix="child_"/>
|
||||||
|
</body>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
|
)";
|
||||||
|
|
||||||
|
static constexpr char grandparent_xml[] = R"(
|
||||||
|
<mujoco>
|
||||||
|
<compiler meshdir="grandparent_meshdir"/>
|
||||||
|
|
||||||
|
<asset>
|
||||||
|
<mesh name="m" file="grandparent_mesh.obj"/>
|
||||||
|
<model name="parent" file="parent.xml"/>
|
||||||
|
</asset>
|
||||||
|
|
||||||
|
<worldbody>
|
||||||
|
<geom type="mesh" mesh="m"/>
|
||||||
|
<attach model="parent" body="parent" prefix="parent_"/>
|
||||||
|
</worldbody>
|
||||||
|
</mujoco>
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto vfs = std::make_unique<mjVFS>();
|
||||||
|
mj_defaultVFS(vfs.get());
|
||||||
|
mj_addBufferVFS(vfs.get(), "child_meshdir/child_mesh.obj", cube,
|
||||||
|
sizeof(cube));
|
||||||
|
mj_addBufferVFS(vfs.get(), "child.xml", child_xml, sizeof(child_xml));
|
||||||
|
mj_addBufferVFS(vfs.get(), "parent_meshdir/parent_mesh.obj", cube,
|
||||||
|
sizeof(cube));
|
||||||
|
mj_addBufferVFS(vfs.get(), "parent.xml", parent_xml, sizeof(parent_xml));
|
||||||
|
mj_addBufferVFS(vfs.get(), "grandparent_meshdir/grandparent_mesh.obj", cube,
|
||||||
|
sizeof(cube));
|
||||||
|
|
||||||
|
std::array<char, 1024> error;
|
||||||
|
mjModel* child_model = LoadModelFromString(child_xml, error.data(),
|
||||||
|
error.size(), vfs.get());
|
||||||
|
EXPECT_THAT(child_model, NotNull()) << error.data();
|
||||||
|
mj_deleteModel(child_model);
|
||||||
|
|
||||||
|
mjModel* parent_model = LoadModelFromString(parent_xml, error.data(),
|
||||||
|
error.size(), vfs.get());
|
||||||
|
EXPECT_THAT(parent_model, NotNull()) << error.data();
|
||||||
|
mj_deleteModel(parent_model);
|
||||||
|
|
||||||
|
mjModel* grandparent_model = LoadModelFromString(
|
||||||
|
grandparent_xml, error.data(), error.size(), vfs.get());
|
||||||
|
EXPECT_THAT(grandparent_model, NotNull()) << error.data();
|
||||||
|
mj_deleteModel(grandparent_model);
|
||||||
|
|
||||||
|
mj_deleteVFS(vfs.get());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace mujoco
|
} // namespace mujoco
|
||||||
|
|||||||
Reference in New Issue
Block a user