diff --git a/src/user/user_mesh.cc b/src/user/user_mesh.cc
index 32b281de..7c691dc8 100644
--- a/src/user/user_mesh.cc
+++ b/src/user/user_mesh.cc
@@ -2526,16 +2526,15 @@ void mjCSkin::Compile(const mjVFS* vfs) {
// load file
if (!file_.empty()) {
// make sure data is not present
- if (!vert_.empty() ||
- !texcoord_.empty() ||
- !face_.empty() ||
- !bodyname_.empty() ||
- !bindpos_.empty() ||
- !bindquat_.empty() ||
- !vertid_.empty() ||
- !vertweight_.empty() ||
- !bodyid.empty()) {
- throw mjCError(this, "Data already exists, trying to load from skin file: %s", file_.c_str());
+ if (!spec_vert_.empty() ||
+ !spec_texcoord_.empty() ||
+ !spec_face_.empty() ||
+ !spec_bodyname_.empty() ||
+ !spec_bindpos_.empty() ||
+ !spec_bindquat_.empty() ||
+ !spec_vertid_.empty() ||
+ !spec_vertweight_.empty()) {
+ throw mjCError(this, "Both skin data and file were specified: %s", file_.c_str());
}
// remove path from file if necessary
diff --git a/test/user/testdata/cube.skn b/test/user/testdata/cube.skn
new file mode 100644
index 00000000..498a7926
Binary files /dev/null and b/test/user/testdata/cube.skn differ
diff --git a/test/user/testdata/cube.stl b/test/user/testdata/cube.stl
new file mode 100644
index 00000000..e2f72542
Binary files /dev/null and b/test/user/testdata/cube.stl differ
diff --git a/test/user/testdata/cube_skin.xml b/test/user/testdata/cube_skin.xml
new file mode 100644
index 00000000..69004072
--- /dev/null
+++ b/test/user/testdata/cube_skin.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/user/user_mesh_test.cc b/test/user/user_mesh_test.cc
index 2e1eb1e0..167b1480 100644
--- a/test/user/user_mesh_test.cc
+++ b/test/user/user_mesh_test.cc
@@ -66,6 +66,8 @@ static const char* const kDuplicateOBJPath =
"user/testdata/duplicate.xml";
static const char* const kMalformedFaceOBJPath =
"user/testdata/malformed_face.xml";
+static const char* const kCubeSkinPath =
+ "user/testdata/cube_skin.xml";
using ::testing::ElementsAre;
using ::testing::HasSubstr;
@@ -1184,6 +1186,19 @@ TEST_F(MjCMeshTest, InvalidIndexInFace) {
mj_deleteModel(model);
}
+TEST_F(MjCMeshTest, LoadSkin) {
+ const std::string xml_path = GetTestDataFilePath(kCubeSkinPath);
+ std::array error;
+ mjSpec* spec = mj_parseXML(xml_path.c_str(), 0, error.data(), error.size());
+ EXPECT_THAT(spec, NotNull()) << error.data();
+ mjModel* m1 = mj_compile(spec, 0);
+ EXPECT_THAT(m1, NotNull());
+ mj_deleteModel(m1);
+ mjModel* m2 = mj_compile(spec, 0);
+ EXPECT_THAT(m2, NotNull());
+ mj_deleteModel(m2);
+ mj_deleteSpec(spec);
+}
} // namespace