Raise error if mesh has flipped faces.

PiperOrigin-RevId: 461860424
Change-Id: Ib23c50cf7f64de1173404d2f65ad87177fab45b3
This commit is contained in:
Alessio Quaglino
2022-07-19 05:47:08 -07:00
committed by Copybara-Service
parent e6480c76a9
commit 8dd9971409
6 changed files with 95 additions and 14 deletions
+9
View File
@@ -0,0 +1,9 @@
v 0 0 0
v 1 0 0
v 0 1 0
v 0 0 1
f 3 1 4
f 1 2 4
f 2 3 4
# malformed face
f 1 2 3
+8
View File
@@ -0,0 +1,8 @@
<mujoco>
<asset>
<mesh file="malformed_face.obj"/>
</asset>
<worldbody>
<geom type="mesh" mesh="malformed_face"/>
</worldbody>
</mujoco>
+28
View File
@@ -43,6 +43,8 @@ static const char* const kTexturedTorusPath =
"user/testdata/textured_torus.xml";
static const char* const kDuplicateOBJPath =
"user/testdata/duplicate.xml";
static const char* const kMalformedFaceOBJPath =
"user/testdata/malformed_face.xml";
using ::testing::HasSubstr;
@@ -174,5 +176,31 @@ TEST_F(MujocoTest, TinyInertiaFails) {
"mass and inertia of moving bodies must be larger than mjMINVAL"));
}
TEST_F(MujocoTest, MalformedFaceFails) {
const std::string xml_path = GetTestDataFilePath(kMalformedFaceOBJPath);
std::array<char, 1024> error;
mjModel* model = mj_loadXML(xml_path.c_str(), 0, error.data(), error.size());
ASSERT_THAT(model, testing::IsNull());
EXPECT_THAT(error.data(), HasSubstr("faces have inconsistent orientation"));
}
TEST_F(MujocoTest, FlippedFaceFails) {
static constexpr char xml[] = R"(
<mujoco>
<asset>
<mesh name="example_mesh"
vertex="0 0 0 1 0 0 0 1 0 0 0 1"
face="2 0 3 0 1 3 1 2 3 0 1 2" />
</asset>
<worldbody>
<geom type="mesh" mesh="example_mesh"/>
</worldbody>
</mujoco>
)";
std::array<char, 1024> error;
LoadModelFromString(xml, error.data(), error.size());
EXPECT_THAT(error.data(), HasSubstr("faces have inconsistent orientation"));
}
} // namespace
} // namespace mujoco
+7 -1
View File
@@ -34,6 +34,7 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <absl/container/flat_hash_set.h>
#include <absl/strings/match.h>
#include <mujoco/mjmodel.h>
#include <mujoco/mjtnum.h>
#include <mujoco/mjxmacro.h>
@@ -416,10 +417,15 @@ TEST_F(XMLWriterTest, WriteReadCompare) {
if (p.path().extension() == ext) {
std::string xml = p.path().string();
// if file is meant to fail, skip it
if (absl::StrContains(p.path().string(), "malformed_")) {
continue;
}
// load model
std::array<char, 1000> error;
mjModel* m = mj_loadXML(xml.c_str(), nullptr, error.data(), error.size());
ASSERT_THAT(m, NotNull()) << "Failed to load model: " << error.data();
ASSERT_THAT(m, NotNull()) << "Failed to load " << xml.c_str() << ": " << error.data();
// make data
mjData* d = mj_makeData(m);