Correct polygon winding order for all meshes not only when loaded from a file.
PiperOrigin-RevId: 882053060 Change-Id: I94ee81838fa4074a1a890de4f282eca45ee9e820
This commit is contained in:
committed by
Copybara-Service
parent
db9ab94555
commit
ecc22667fa
+14
-13
@@ -647,19 +647,6 @@ void mjCMesh::LoadFromDecoder(mjResource* resource, bool remove_repeated) {
|
||||
facenormal_.assign(src_mesh->userfacenormal->begin(), src_mesh->userfacenormal->end());
|
||||
facetexcoord_.assign(src_mesh->userfacetexcoord->begin(), src_mesh->userfacetexcoord->end());
|
||||
|
||||
// correct winding order for left-handed coordinate systems
|
||||
bool righthand = scale[0] * scale[1] * scale[2] > 0;
|
||||
if (!righthand) {
|
||||
for (size_t i = 0; i < face_.size(); i += 3) {
|
||||
std::swap(face_[i + 1], face_[i + 2]);
|
||||
}
|
||||
for (size_t i = 0; i < facenormal_.size(); i += 3) {
|
||||
std::swap(facenormal_[i + 1], facenormal_[i + 2]);
|
||||
}
|
||||
for (size_t i = 0; i < facetexcoord_.size(); i += 3) {
|
||||
std::swap(facetexcoord_[i + 1], facetexcoord_[i + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<float> vert(src_mesh->uservert->begin(), src_mesh->uservert->end());
|
||||
mj_deleteSpec(mesh_spec);
|
||||
@@ -1434,6 +1421,20 @@ void mjCMesh::Process() {
|
||||
polygon_map_.resize(nvert());
|
||||
}
|
||||
|
||||
// correct winding order for left-handed coordinate systems
|
||||
bool righthand = scale[0] * scale[1] * scale[2] > 0;
|
||||
if (!righthand) {
|
||||
for (size_t i = 0; i < face_.size(); i += 3) {
|
||||
std::swap(face_[i + 1], face_[i + 2]);
|
||||
}
|
||||
for (size_t i = 0; i < facenormal_.size(); i += 3) {
|
||||
std::swap(facenormal_[i + 1], facenormal_[i + 2]);
|
||||
}
|
||||
for (size_t i = 0; i < facetexcoord_.size(); i += 3) {
|
||||
std::swap(facetexcoord_[i + 1], facetexcoord_[i + 2]);
|
||||
}
|
||||
}
|
||||
|
||||
// user offset, rotation, scaling
|
||||
ApplyTransformations();
|
||||
|
||||
|
||||
@@ -1086,6 +1086,71 @@ TEST_F(MjCMeshTest, MeshScale) {
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(MjCMeshTest, NegativeScaleUserMeshCompiles) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
<asset>
|
||||
<mesh name="example_mesh" scale="-1 1 1" inertia="exact"
|
||||
vertex="0 0 0 1 0 0 0 1 0 0 0 1"
|
||||
face="0 2 1 0 3 2 1 3 0 1 2 3" />
|
||||
</asset>
|
||||
<worldbody>
|
||||
<geom type="mesh" mesh="example_mesh"/>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
char error[1024];
|
||||
mjModel* model = LoadModelFromString(xml, error, sizeof(error));
|
||||
ASSERT_THAT(model, NotNull()) << error;
|
||||
mj_deleteModel(model);
|
||||
}
|
||||
|
||||
TEST_F(MjCMeshTest, NegativeScaleUserMeshMatchesPositiveScale) {
|
||||
static constexpr char pos_xml[] = R"(
|
||||
<mujoco>
|
||||
<asset>
|
||||
<mesh name="pos_mesh"
|
||||
vertex="0 0 0 1 0 0 0 1 0 0 0 1"
|
||||
face="0 2 1 0 3 2 1 3 0 1 2 3" />
|
||||
</asset>
|
||||
<worldbody>
|
||||
<geom type="mesh" mesh="pos_mesh"/>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
|
||||
static constexpr char neg_xml[] = R"(
|
||||
<mujoco>
|
||||
<asset>
|
||||
<mesh name="neg_mesh" scale="-1 1 1"
|
||||
vertex="0 0 0 1 0 0 0 1 0 0 0 1"
|
||||
face="0 2 1 0 3 2 1 3 0 1 2 3" />
|
||||
</asset>
|
||||
<worldbody>
|
||||
<geom type="mesh" mesh="neg_mesh"/>
|
||||
</worldbody>
|
||||
</mujoco>
|
||||
)";
|
||||
|
||||
char error[1024];
|
||||
mjModel* pos_model = LoadModelFromString(pos_xml, error, sizeof(error));
|
||||
ASSERT_THAT(pos_model, NotNull()) << error;
|
||||
|
||||
mjModel* neg_model = LoadModelFromString(neg_xml, error, sizeof(error));
|
||||
ASSERT_THAT(neg_model, NotNull()) << error;
|
||||
|
||||
ASSERT_EQ(pos_model->nmeshface, neg_model->nmeshface);
|
||||
|
||||
for (int i = 0; i < pos_model->nmeshface; i++) {
|
||||
EXPECT_EQ(pos_model->mesh_face[3*i + 0], neg_model->mesh_face[3*i + 0]);
|
||||
EXPECT_EQ(pos_model->mesh_face[3*i + 1], neg_model->mesh_face[3*i + 2]);
|
||||
EXPECT_EQ(pos_model->mesh_face[3*i + 2], neg_model->mesh_face[3*i + 1]);
|
||||
}
|
||||
|
||||
mj_deleteModel(pos_model);
|
||||
mj_deleteModel(neg_model);
|
||||
}
|
||||
|
||||
TEST_F(MjCMeshTest, ShellInertiaTest) {
|
||||
static constexpr char xml[] = R"(
|
||||
<mujoco>
|
||||
|
||||
Reference in New Issue
Block a user