mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-14 18:27:58 -06:00
Initial implementation of MeshClipper class
So far the work is shared between the old code in GLGizmoSlaSupports.cpp and the new class
This commit is contained in:
parent
cf23146ee3
commit
546917830b
5 changed files with 149 additions and 29 deletions
|
@ -85,6 +85,8 @@ set(SLIC3R_GUI_SOURCES
|
||||||
GUI/GUI_ObjectLayers.hpp
|
GUI/GUI_ObjectLayers.hpp
|
||||||
GUI/LambdaObjectDialog.cpp
|
GUI/LambdaObjectDialog.cpp
|
||||||
GUI/LambdaObjectDialog.hpp
|
GUI/LambdaObjectDialog.hpp
|
||||||
|
GUI/MeshClipper.cpp
|
||||||
|
GUI/MeshClipper.hpp
|
||||||
GUI/Tab.cpp
|
GUI/Tab.cpp
|
||||||
GUI/Tab.hpp
|
GUI/Tab.hpp
|
||||||
GUI/ConfigManipulation.cpp
|
GUI/ConfigManipulation.cpp
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "slic3r/GUI/GUI.hpp"
|
#include "slic3r/GUI/GUI.hpp"
|
||||||
#include "slic3r/GUI/GUI_ObjectSettings.hpp"
|
#include "slic3r/GUI/GUI_ObjectSettings.hpp"
|
||||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||||
|
#include "slic3r/GUI/MeshClipper.hpp"
|
||||||
#include "slic3r/GUI/Plater.hpp"
|
#include "slic3r/GUI/Plater.hpp"
|
||||||
#include "slic3r/GUI/PresetBundle.hpp"
|
#include "slic3r/GUI/PresetBundle.hpp"
|
||||||
#include "libslic3r/SLAPrint.hpp"
|
#include "libslic3r/SLAPrint.hpp"
|
||||||
|
@ -143,8 +144,9 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
||||||
|
|
||||||
// First cache instance transformation to be used later.
|
// First cache instance transformation to be used later.
|
||||||
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||||
Transform3f instance_matrix = vol->get_instance_transformation().get_matrix().cast<float>();
|
Geometry::Transformation trafo = vol->get_instance_transformation();
|
||||||
Transform3f instance_matrix_no_translation_no_scaling = vol->get_instance_transformation().get_matrix(true,false,true).cast<float>();
|
Transform3f instance_matrix = trafo.get_matrix().cast<float>();
|
||||||
|
Transform3f instance_matrix_no_translation_no_scaling = trafo.get_matrix(true,false,true).cast<float>();
|
||||||
Vec3f scaling = vol->get_instance_scaling_factor().cast<float>();
|
Vec3f scaling = vol->get_instance_scaling_factor().cast<float>();
|
||||||
Vec3d instance_offset = vol->get_instance_offset();
|
Vec3d instance_offset = vol->get_instance_offset();
|
||||||
// Calculate distance from mesh origin to the clipping plane (in mesh coordinates).
|
// Calculate distance from mesh origin to the clipping plane (in mesh coordinates).
|
||||||
|
@ -152,6 +154,7 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
||||||
Vec3f up = Vec3f(up_noscale(0)*scaling(0), up_noscale(1)*scaling(1), up_noscale(2)*scaling(2));
|
Vec3f up = Vec3f(up_noscale(0)*scaling(0), up_noscale(1)*scaling(1), up_noscale(2)*scaling(2));
|
||||||
float height_mesh = m_clipping_plane->distance(center) * (up_noscale.norm()/up.norm());
|
float height_mesh = m_clipping_plane->distance(center) * (up_noscale.norm()/up.norm());
|
||||||
|
|
||||||
|
|
||||||
// Get transformation of the supports and calculate how far from its origin the clipping plane is.
|
// Get transformation of the supports and calculate how far from its origin the clipping plane is.
|
||||||
Transform3d supports_trafo = Transform3d::Identity();
|
Transform3d supports_trafo = Transform3d::Identity();
|
||||||
supports_trafo = supports_trafo.rotate(Eigen::AngleAxisd(vol->get_instance_rotation()(2), Vec3d::UnitZ()));
|
supports_trafo = supports_trafo.rotate(Eigen::AngleAxisd(vol->get_instance_rotation()(2), Vec3d::UnitZ()));
|
||||||
|
@ -167,15 +170,13 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
||||||
*m_old_clipping_plane = *m_clipping_plane;
|
*m_old_clipping_plane = *m_clipping_plane;
|
||||||
|
|
||||||
// Now initialize the TMS for the object, perform the cut and save the result.
|
// Now initialize the TMS for the object, perform the cut and save the result.
|
||||||
if (! m_tms) {
|
if (! m_object_clipper) {
|
||||||
m_tms.reset(new TriangleMeshSlicer);
|
m_object_clipper.reset(new MeshClipper);
|
||||||
m_tms->init(m_mesh, [](){});
|
m_object_clipper->set_mesh(*m_mesh);
|
||||||
}
|
}
|
||||||
std::vector<ExPolygons> list_of_expolys;
|
m_object_clipper->set_plane(*m_clipping_plane);
|
||||||
m_tms->set_up_direction(up);
|
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_z_shift));
|
||||||
m_tms->slice(std::vector<float>{height_mesh}, 0.f, &list_of_expolys, [](){});
|
m_object_clipper->set_transformation(trafo);
|
||||||
m_triangles = triangulate_expolygons_2f(list_of_expolys[0]);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Next, ask the backend if supports are already calculated. If so, we are gonna cut them too.
|
// Next, ask the backend if supports are already calculated. If so, we are gonna cut them too.
|
||||||
|
@ -198,31 +199,27 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
||||||
// so we can later tell they were recalculated.
|
// so we can later tell they were recalculated.
|
||||||
size_t timestamp = print_object->step_state_with_timestamp(slaposSupportTree).timestamp;
|
size_t timestamp = print_object->step_state_with_timestamp(slaposSupportTree).timestamp;
|
||||||
|
|
||||||
if (!m_supports_tms || (int)timestamp != m_old_timestamp) {
|
if (! m_supports_clipper || (int)timestamp != m_old_timestamp) {
|
||||||
// The timestamp has changed - stash the mesh and initialize the TMS.
|
// The timestamp has changed - stash the mesh and initialize the TMS.
|
||||||
m_supports_mesh = &print_object->support_mesh();
|
m_supports_mesh = &print_object->support_mesh();
|
||||||
m_supports_tms.reset(new TriangleMeshSlicer);
|
m_supports_clipper.reset(new MeshClipper);
|
||||||
// The mesh should already have the shared vertices calculated.
|
// The mesh should already have the shared vertices calculated.
|
||||||
m_supports_tms->init(m_supports_mesh, [](){});
|
m_supports_clipper->set_mesh(*m_supports_mesh);
|
||||||
m_old_timestamp = timestamp;
|
m_old_timestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The TMS is initialized - let's do the cutting:
|
// The TMS is initialized - let's do the cutting:
|
||||||
list_of_expolys.clear();
|
m_supports_clipper->set_plane(*m_clipping_plane);
|
||||||
m_supports_tms->set_up_direction(up_supports);
|
m_supports_clipper->set_transformation(Geometry::Transformation(supports_trafo));
|
||||||
m_supports_tms->slice(std::vector<float>{height_supports}, 0.f, &list_of_expolys, [](){});
|
|
||||||
m_supports_triangles = triangulate_expolygons_2f(list_of_expolys[0]);
|
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
// The supports are not valid. We better dump the cached data.
|
// The supports are not valid. We better dump the cached data.
|
||||||
m_supports_tms.reset();
|
m_supports_clipper.reset();
|
||||||
m_supports_triangles.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point we have the triangulated cuts for both the object and supports - let's render.
|
// At this point we have the triangulated cuts for both the object and supports - let's render.
|
||||||
if (! m_triangles.empty()) {
|
if (! m_object_clipper->get_triangles().empty()) {
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
::glTranslated(0.0, 0.0, m_z_shift);
|
::glTranslated(0.0, 0.0, m_z_shift);
|
||||||
::glMultMatrixf(instance_matrix.data());
|
::glMultMatrixf(instance_matrix.data());
|
||||||
|
@ -233,14 +230,14 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
||||||
::glTranslatef(0.f, 0.f, 0.01f); // to make sure the cut does not intersect the structure itself
|
::glTranslatef(0.f, 0.f, 0.01f); // to make sure the cut does not intersect the structure itself
|
||||||
::glColor3f(1.0f, 0.37f, 0.0f);
|
::glColor3f(1.0f, 0.37f, 0.0f);
|
||||||
::glBegin(GL_TRIANGLES);
|
::glBegin(GL_TRIANGLES);
|
||||||
for (const Vec2f& point : m_triangles)
|
for (const Vec2f& point : m_object_clipper->get_triangles())
|
||||||
::glVertex3f(point(0), point(1), height_mesh);
|
::glVertex3f(point(0), point(1), height_mesh);
|
||||||
|
|
||||||
::glEnd();
|
::glEnd();
|
||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! m_supports_triangles.empty() && !m_editing_mode) {
|
if (m_supports_clipper && ! m_supports_clipper->get_triangles().empty() && !m_editing_mode) {
|
||||||
// The supports are hidden in the editing mode, so it makes no sense to render the cuts.
|
// The supports are hidden in the editing mode, so it makes no sense to render the cuts.
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
::glMultMatrixd(supports_trafo.data());
|
::glMultMatrixd(supports_trafo.data());
|
||||||
|
@ -251,7 +248,7 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
||||||
::glTranslatef(0.f, 0.f, 0.01f);
|
::glTranslatef(0.f, 0.f, 0.01f);
|
||||||
::glColor3f(1.0f, 0.f, 0.37f);
|
::glColor3f(1.0f, 0.f, 0.37f);
|
||||||
::glBegin(GL_TRIANGLES);
|
::glBegin(GL_TRIANGLES);
|
||||||
for (const Vec2f& point : m_supports_triangles)
|
for (const Vec2f& point : m_supports_clipper->get_triangles())
|
||||||
::glVertex3f(point(0), point(1), height_supports);
|
::glVertex3f(point(0), point(1), height_supports);
|
||||||
|
|
||||||
::glEnd();
|
::glEnd();
|
||||||
|
@ -1142,8 +1139,8 @@ void GLGizmoSlaSupports::on_set_state()
|
||||||
// Release triangle mesh slicer and the AABB spatial search structure.
|
// Release triangle mesh slicer and the AABB spatial search structure.
|
||||||
m_AABB.deinit();
|
m_AABB.deinit();
|
||||||
m_its = nullptr;
|
m_its = nullptr;
|
||||||
m_tms.reset();
|
m_object_clipper.reset();
|
||||||
m_supports_tms.reset();
|
m_supports_clipper.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_old_state = m_state;
|
m_old_state = m_state;
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace Slic3r {
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
class ClippingPlane;
|
class ClippingPlane;
|
||||||
|
class MeshClipper;
|
||||||
|
|
||||||
class GLGizmoSlaSupports : public GLGizmoBase
|
class GLGizmoSlaSupports : public GLGizmoBase
|
||||||
{
|
{
|
||||||
|
@ -126,8 +127,8 @@ private:
|
||||||
bool m_selection_empty = true;
|
bool m_selection_empty = true;
|
||||||
EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state)
|
EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state)
|
||||||
|
|
||||||
mutable std::unique_ptr<TriangleMeshSlicer> m_tms;
|
mutable std::unique_ptr<MeshClipper> m_object_clipper;
|
||||||
mutable std::unique_ptr<TriangleMeshSlicer> m_supports_tms;
|
mutable std::unique_ptr<MeshClipper> m_supports_clipper;
|
||||||
|
|
||||||
std::vector<const ConfigOption*> get_config_options(const std::vector<std::string>& keys) const;
|
std::vector<const ConfigOption*> get_config_options(const std::vector<std::string>& keys) const;
|
||||||
bool is_point_clipped(const Vec3d& point) const;
|
bool is_point_clipped(const Vec3d& point) const;
|
||||||
|
|
83
src/slic3r/GUI/MeshClipper.cpp
Normal file
83
src/slic3r/GUI/MeshClipper.cpp
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
#include "MeshClipper.hpp"
|
||||||
|
#include "GLCanvas3D.hpp"
|
||||||
|
#include "libslic3r/Tesselate.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
void MeshClipper::set_plane(const ClippingPlane& plane)
|
||||||
|
{
|
||||||
|
if (m_plane != plane) {
|
||||||
|
m_plane = plane;
|
||||||
|
m_triangles_valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshClipper::set_mesh(const TriangleMesh& mesh)
|
||||||
|
{
|
||||||
|
if (m_mesh != &mesh) {
|
||||||
|
m_mesh = &mesh;
|
||||||
|
m_triangles_valid = false;
|
||||||
|
m_triangles.resize(0);
|
||||||
|
m_tms.reset(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshClipper::set_transformation(const Geometry::Transformation& trafo)
|
||||||
|
{
|
||||||
|
if (! m_trafo.get_matrix().isApprox(trafo.get_matrix())) {
|
||||||
|
m_trafo = trafo;
|
||||||
|
m_triangles_valid = false;
|
||||||
|
m_triangles.resize(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const std::vector<Vec2f>& MeshClipper::get_triangles()
|
||||||
|
{
|
||||||
|
if (! m_triangles_valid)
|
||||||
|
recalculate_triangles();
|
||||||
|
|
||||||
|
return m_triangles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MeshClipper::recalculate_triangles()
|
||||||
|
{
|
||||||
|
if (! m_tms) {
|
||||||
|
m_tms.reset(new TriangleMeshSlicer);
|
||||||
|
m_tms->init(m_mesh, [](){});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto up_and_height = get_mesh_cut_normal();
|
||||||
|
Vec3f up = up_and_height.first;
|
||||||
|
float height_mesh = up_and_height.second;
|
||||||
|
|
||||||
|
std::vector<ExPolygons> list_of_expolys;
|
||||||
|
m_tms->set_up_direction(up);
|
||||||
|
m_tms->slice(std::vector<float>{height_mesh}, 0.f, &list_of_expolys, [](){});
|
||||||
|
m_triangles = triangulate_expolygons_2f(list_of_expolys[0]);
|
||||||
|
|
||||||
|
m_triangles_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<Vec3f, float> MeshClipper::get_mesh_cut_normal() const
|
||||||
|
{
|
||||||
|
Transform3f instance_matrix_no_translation_no_scaling = m_trafo.get_matrix(true,false,true).cast<float>();
|
||||||
|
Vec3f scaling = m_trafo.get_scaling_factor().cast<float>();
|
||||||
|
|
||||||
|
// Calculate distance from mesh origin to the clipping plane (in mesh coordinates).
|
||||||
|
Vec3f up_noscale = instance_matrix_no_translation_no_scaling.inverse() * m_plane.get_normal().cast<float>();
|
||||||
|
Vec3f up (up_noscale(0)*scaling(0), up_noscale(1)*scaling(1), up_noscale(2)*scaling(2));
|
||||||
|
|
||||||
|
float height_mesh = m_plane.distance(m_trafo.get_offset()) * (up_noscale.norm()/up.norm());
|
||||||
|
|
||||||
|
|
||||||
|
return std::make_pair(up, height_mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace GUI
|
||||||
|
} // namespace Slic3r
|
37
src/slic3r/GUI/MeshClipper.hpp
Normal file
37
src/slic3r/GUI/MeshClipper.hpp
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#ifndef slic3r_MeshClipper_hpp_
|
||||||
|
#define slic3r_MeshClipper_hpp_
|
||||||
|
|
||||||
|
#include "libslic3r/Point.hpp"
|
||||||
|
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
namespace GUI {
|
||||||
|
|
||||||
|
class MeshClipper {
|
||||||
|
public:
|
||||||
|
void set_plane(const ClippingPlane& plane);
|
||||||
|
void set_mesh(const TriangleMesh& mesh);
|
||||||
|
void set_transformation(const Geometry::Transformation& trafo);
|
||||||
|
|
||||||
|
const std::vector<Vec2f>& get_triangles();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void recalculate_triangles();
|
||||||
|
std::pair<Vec3f, float> get_mesh_cut_normal() const;
|
||||||
|
|
||||||
|
|
||||||
|
Geometry::Transformation m_trafo;
|
||||||
|
const TriangleMesh* m_mesh = nullptr;
|
||||||
|
ClippingPlane m_plane;
|
||||||
|
std::vector<Vec2f> m_triangles;
|
||||||
|
bool m_triangles_valid = false;
|
||||||
|
std::unique_ptr<TriangleMeshSlicer> m_tms;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace GUI
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
|
||||||
|
#endif // slic3r_MeshClipper_hpp_
|
Loading…
Add table
Add a link
Reference in a new issue