Fix normal direction when exporting STL (#6406)
The export function does not depend on Model/ModelObject::mesh() family of functions, changing them might break the already too brittle code.
This commit is contained in:
parent
d1cfdcb49e
commit
978b359492
6 changed files with 42 additions and 26 deletions
|
@ -833,18 +833,6 @@ indexed_triangle_set ModelObject::raw_indexed_triangle_set() const
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes.
|
|
||||||
TriangleMesh ModelObject::full_raw_mesh() const
|
|
||||||
{
|
|
||||||
TriangleMesh mesh;
|
|
||||||
for (const ModelVolume *v : this->volumes)
|
|
||||||
{
|
|
||||||
TriangleMesh vol_mesh(v->mesh());
|
|
||||||
vol_mesh.transform(v->get_matrix());
|
|
||||||
mesh.merge(vol_mesh);
|
|
||||||
}
|
|
||||||
return mesh;
|
|
||||||
}
|
|
||||||
|
|
||||||
const BoundingBoxf3& ModelObject::raw_mesh_bounding_box() const
|
const BoundingBoxf3& ModelObject::raw_mesh_bounding_box() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -289,8 +289,6 @@ public:
|
||||||
TriangleMesh raw_mesh() const;
|
TriangleMesh raw_mesh() const;
|
||||||
// The same as above, but producing a lightweight indexed_triangle_set.
|
// The same as above, but producing a lightweight indexed_triangle_set.
|
||||||
indexed_triangle_set raw_indexed_triangle_set() const;
|
indexed_triangle_set raw_indexed_triangle_set() const;
|
||||||
// Non-transformed (non-rotated, non-scaled, non-translated) sum of all object volumes.
|
|
||||||
TriangleMesh full_raw_mesh() const;
|
|
||||||
// A transformed snug bounding box around the non-modifier object volumes, without the translation applied.
|
// A transformed snug bounding box around the non-modifier object volumes, without the translation applied.
|
||||||
// This bounding box is only used for the actual slicing.
|
// This bounding box is only used for the actual slicing.
|
||||||
const BoundingBoxf3& raw_bounding_box() const;
|
const BoundingBoxf3& raw_bounding_box() const;
|
||||||
|
|
|
@ -2207,6 +2207,7 @@ std::vector<ExPolygons> PrintObject::slice_volumes(
|
||||||
TriangleMesh vol_mesh(model_volume.mesh());
|
TriangleMesh vol_mesh(model_volume.mesh());
|
||||||
vol_mesh.transform(model_volume.get_matrix(), true);
|
vol_mesh.transform(model_volume.get_matrix(), true);
|
||||||
mesh.merge(vol_mesh);
|
mesh.merge(vol_mesh);
|
||||||
|
mesh.repair(false);
|
||||||
}
|
}
|
||||||
if (mesh.stl.stats.number_of_facets > 0) {
|
if (mesh.stl.stats.number_of_facets > 0) {
|
||||||
mesh.transform(m_trafo, true);
|
mesh.transform(m_trafo, true);
|
||||||
|
|
|
@ -357,10 +357,14 @@ void TriangleMesh::transform(const Transform3d& t, bool fix_left_handed)
|
||||||
its_transform(its, t);
|
its_transform(its, t);
|
||||||
if (fix_left_handed && t.matrix().block(0, 0, 3, 3).determinant() < 0.) {
|
if (fix_left_handed && t.matrix().block(0, 0, 3, 3).determinant() < 0.) {
|
||||||
// Left handed transformation is being applied. It is a good idea to flip the faces and their normals.
|
// Left handed transformation is being applied. It is a good idea to flip the faces and their normals.
|
||||||
this->repair(false);
|
// As for the assert: the repair function would fix the normals, reversing would
|
||||||
stl_reverse_all_facets(&stl);
|
// break them again. The caller should provide a mesh that does not need repair.
|
||||||
this->its.clear();
|
// The repair call is left here so things don't break more than they were.
|
||||||
this->require_shared_vertices();
|
assert(this->repaired);
|
||||||
|
this->repair(false);
|
||||||
|
stl_reverse_all_facets(&stl);
|
||||||
|
this->its.clear();
|
||||||
|
this->require_shared_vertices();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,11 +373,12 @@ void TriangleMesh::transform(const Matrix3d& m, bool fix_left_handed)
|
||||||
stl_transform(&stl, m);
|
stl_transform(&stl, m);
|
||||||
its_transform(its, m);
|
its_transform(its, m);
|
||||||
if (fix_left_handed && m.determinant() < 0.) {
|
if (fix_left_handed && m.determinant() < 0.) {
|
||||||
// Left handed transformation is being applied. It is a good idea to flip the faces and their normals.
|
// See comments in function above.
|
||||||
|
assert(this->repaired);
|
||||||
this->repair(false);
|
this->repair(false);
|
||||||
stl_reverse_all_facets(&stl);
|
stl_reverse_all_facets(&stl);
|
||||||
this->its.clear();
|
this->its.clear();
|
||||||
this->require_shared_vertices();
|
this->require_shared_vertices();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
#include "GLCanvas3D.hpp"
|
#include "GLCanvas3D.hpp"
|
||||||
|
|
||||||
#include "admesh/stl.h"
|
|
||||||
#include "libslic3r/ClipperUtils.hpp"
|
#include "libslic3r/ClipperUtils.hpp"
|
||||||
#include "libslic3r/PrintConfig.hpp"
|
#include "libslic3r/PrintConfig.hpp"
|
||||||
#include "libslic3r/GCode/ThumbnailData.hpp"
|
#include "libslic3r/GCode/ThumbnailData.hpp"
|
||||||
|
|
|
@ -5085,6 +5085,30 @@ void Plater::export_stl(bool extended, bool selection_only)
|
||||||
if (selection_only && (obj_idx == -1 || selection.is_wipe_tower()))
|
if (selection_only && (obj_idx == -1 || selection.is_wipe_tower()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Following lambda generates a combined mesh for export with normals pointing outwards.
|
||||||
|
auto mesh_to_export = [](const ModelObject* mo, bool instances) -> TriangleMesh {
|
||||||
|
TriangleMesh mesh;
|
||||||
|
for (const ModelVolume *v : mo->volumes)
|
||||||
|
if (v->is_model_part()) {
|
||||||
|
TriangleMesh vol_mesh(v->mesh());
|
||||||
|
vol_mesh.repair();
|
||||||
|
vol_mesh.transform(v->get_matrix(), true);
|
||||||
|
mesh.merge(vol_mesh);
|
||||||
|
}
|
||||||
|
mesh.repair();
|
||||||
|
if (instances) {
|
||||||
|
TriangleMesh vols_mesh(mesh);
|
||||||
|
mesh = TriangleMesh();
|
||||||
|
for (const ModelInstance *i : mo->instances) {
|
||||||
|
TriangleMesh m = vols_mesh;
|
||||||
|
m.transform(i->get_matrix(), true);
|
||||||
|
mesh.merge(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mesh.repair();
|
||||||
|
return mesh;
|
||||||
|
};
|
||||||
|
|
||||||
TriangleMesh mesh;
|
TriangleMesh mesh;
|
||||||
if (p->printer_technology == ptFFF) {
|
if (p->printer_technology == ptFFF) {
|
||||||
if (selection_only) {
|
if (selection_only) {
|
||||||
|
@ -5092,20 +5116,21 @@ void Plater::export_stl(bool extended, bool selection_only)
|
||||||
if (selection.get_mode() == Selection::Instance)
|
if (selection.get_mode() == Selection::Instance)
|
||||||
{
|
{
|
||||||
if (selection.is_single_full_object())
|
if (selection.is_single_full_object())
|
||||||
mesh = model_object->mesh();
|
mesh = mesh_to_export(model_object, true);
|
||||||
else
|
else
|
||||||
mesh = model_object->full_raw_mesh();
|
mesh = mesh_to_export(model_object, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||||
mesh = model_object->volumes[volume->volume_idx()]->mesh();
|
mesh = model_object->volumes[volume->volume_idx()]->mesh();
|
||||||
mesh.transform(volume->get_volume_transformation().get_matrix());
|
mesh.transform(volume->get_volume_transformation().get_matrix(), true);
|
||||||
mesh.translate(-model_object->origin_translation.cast<float>());
|
mesh.translate(-model_object->origin_translation.cast<float>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mesh = p->model.mesh();
|
for (const ModelObject *o : p->model.objects)
|
||||||
|
mesh.merge(mesh_to_export(o, true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue