diff --git a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp index 86ad8d0a0..8c705fef8 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoHollow.cpp @@ -119,6 +119,7 @@ void GLGizmoHollow::on_render() const m_selection_rectangle.render(m_parent); //render_clipping_plane(selection); m_c->object_clipper()->render_cut(); + m_c->supports_clipper()->render_cut(); glsafe(::glDisable(GL_BLEND)); } @@ -929,7 +930,8 @@ CommonGizmosDataID GLGizmoHollow::on_get_requirements() const | int(CommonGizmosDataID::InstancesHider) | int(CommonGizmosDataID::Raycaster) | int(CommonGizmosDataID::HollowedMesh) - | int(CommonGizmosDataID::ObjectClipper)); + | int(CommonGizmosDataID::ObjectClipper) + | int(CommonGizmosDataID::SupportsClipper)); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp index a6fbabfa2..380aa4e7d 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.cpp @@ -18,12 +18,12 @@ CommonGizmosDataPool::CommonGizmosDataPool(GLCanvas3D* canvas) : m_canvas(canvas) { using c = CommonGizmosDataID; - m_data[c::SelectionInfo].reset( new SelectionInfo(this)); - m_data[c::InstancesHider].reset( new InstancesHider(this)); - m_data[c::HollowedMesh].reset( new HollowedMesh(this)); - m_data[c::Raycaster].reset( new Raycaster(this)); - m_data[c::ObjectClipper].reset(new ObjectClipper(this)); - //m_data[c::SupportsClipper].reset( new SupportsClipper(this)); + m_data[c::SelectionInfo].reset( new SelectionInfo(this)); + m_data[c::InstancesHider].reset( new InstancesHider(this)); + m_data[c::HollowedMesh].reset( new HollowedMesh(this)); + m_data[c::Raycaster].reset( new Raycaster(this)); + m_data[c::ObjectClipper].reset( new ObjectClipper(this)); + m_data[c::SupportsClipper].reset( new SupportsClipper(this)); } @@ -77,6 +77,13 @@ ObjectClipper* CommonGizmosDataPool::object_clipper() const return oc->is_valid() ? oc : nullptr; } +SupportsClipper* CommonGizmosDataPool::supports_clipper() const +{ + SupportsClipper* sc = dynamic_cast(m_data.at(CommonGizmosDataID::SupportsClipper).get()); + assert(sc); + return sc->is_valid() ? sc : nullptr; +} + #ifndef NDEBUG // Check the required resources one by one and return true if all // dependencies are met. @@ -346,5 +353,98 @@ void ObjectClipper::set_position(double pos, bool keep_normal) +void SupportsClipper::on_update() +{ + const ModelObject* mo = get_pool()->selection_info()->model_object(); + if (! mo) + return; + + const GLCanvas3D* canvas = get_pool()->get_canvas(); + const PrintObjects& print_objects = canvas->sla_print()->objects(); + const SLAPrintObject* print_object = m_print_object_idx != -1 + ? print_objects[m_print_object_idx] + : nullptr; + + // Find the respective SLAPrintObject. + if (m_print_object_idx < 0 || m_print_objects_count != int(print_objects.size())) { + m_print_objects_count = print_objects.size(); + m_print_object_idx = -1; + for (const SLAPrintObject* po : print_objects) { + ++m_print_object_idx; + if (po->model_object()->id() == mo->id()) { + print_object = po; + break; + } + } + } + + if (print_object + && print_object->is_step_done(slaposSupportTree) + && ! print_object->support_mesh().empty()) + { + // If the supports are already calculated, save the timestamp of the respective step + // so we can later tell they were recalculated. + size_t timestamp = print_object->step_state_with_timestamp(slaposSupportTree).timestamp; + if (! m_clipper || timestamp != m_old_timestamp) { + // The timestamp has changed. + m_clipper.reset(new MeshClipper); + // The mesh should already have the shared vertices calculated. + m_clipper->set_mesh(print_object->support_mesh()); + m_old_timestamp = timestamp; + } + } + else + // The supports are not valid. We better dump the cached data. + m_clipper.reset(); +} + + +void SupportsClipper::on_release() +{ + m_clipper.reset(); + m_old_timestamp = 0; + m_print_object_idx = -1; +} + +void SupportsClipper::render_cut() const +{ + const CommonGizmosDataObjects::ObjectClipper* ocl = get_pool()->object_clipper(); + if (ocl->get_position() == 0. + || ! get_pool()->instances_hider()->are_supports_shown() + || ! m_clipper) + return; + + const SelectionInfo* sel_info = get_pool()->selection_info(); + const ModelObject* mo = sel_info->model_object(); + Geometry::Transformation inst_trafo = mo->instances[sel_info->get_active_instance()]->get_transformation(); + Geometry::Transformation vol_trafo = mo->volumes.front()->get_transformation(); + Geometry::Transformation trafo = inst_trafo;// * vol_trafo; + trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift())); + + + // Get transformation of supports + Geometry::Transformation supports_trafo = trafo; + supports_trafo.set_offset(Vec3d(trafo.get_offset()(0), trafo.get_offset()(1), sel_info->get_sla_shift())); + supports_trafo.set_rotation(Vec3d(0., 0., trafo.get_rotation()(2))); + // I don't know why, but following seems to be correct. + supports_trafo.set_mirror(Vec3d(trafo.get_mirror()(0) * trafo.get_mirror()(1) * trafo.get_mirror()(2), + 1, + 1.)); + + m_clipper->set_plane(*ocl->get_clipping_plane()); + m_clipper->set_transformation(supports_trafo); + + if (! m_clipper->get_triangles().empty()) { + ::glPushMatrix(); + ::glColor3f(1.0f, 0.f, 0.37f); + ::glBegin(GL_TRIANGLES); + for (const Vec3f& point : m_clipper->get_triangles()) + ::glVertex3f(point(0), point(1), point(2)); + ::glEnd(); + ::glPopMatrix(); + } +} + + } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp b/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp index a2fa598c9..54e561f2f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmosCommon.hpp @@ -26,6 +26,7 @@ namespace CommonGizmosDataObjects { class HollowedMesh; class Raycaster; class ObjectClipper; + class SupportsClipper; } // Some of the gizmos use the same data that need to be updated ocassionally. @@ -65,6 +66,7 @@ public: CommonGizmosDataObjects::HollowedMesh* hollowed_mesh() const; CommonGizmosDataObjects::Raycaster* raycaster() const; CommonGizmosDataObjects::ObjectClipper* object_clipper() const; + CommonGizmosDataObjects::SupportsClipper* supports_clipper() const; GLCanvas3D* get_canvas() const { return m_canvas; } @@ -226,7 +228,6 @@ public: CommonGizmosDataID get_dependencies() const override { return CommonGizmosDataID::SelectionInfo; } #endif // NDEBUG - MeshClipper* get_clipper() const { return m_clipper.get(); } void set_position(double pos, bool keep_normal); double get_position() const { return m_clp_ratio; } ClippingPlane* get_clipping_plane() const { return m_clp.get(); } @@ -243,17 +244,6 @@ private: std::unique_ptr m_clp; double m_clp_ratio = 0.; double m_active_inst_bb_radius = 0.; - -}; - -/* - -class ClippingPlaneWrapper : public CommonGizmosDataBase -{ -public: - explicit ClippingPlaneWrapper(CommonGizmosDataPool* cgdp) - : CommonGizmosDataBase(cgdp) {} - void update(bool required) override; }; @@ -263,10 +253,28 @@ class SupportsClipper : public CommonGizmosDataBase public: explicit SupportsClipper(CommonGizmosDataPool* cgdp) : CommonGizmosDataBase(cgdp) {} - void update(bool required) override; -}; +#ifndef NDEBUG + CommonGizmosDataID get_dependencies() const override { + return CommonGizmosDataID( + int(CommonGizmosDataID::SelectionInfo) + | int(CommonGizmosDataID::ObjectClipper) + ); + } +#endif // NDEBUG -*/ + void render_cut() const; + + +protected: + void on_update() override; + void on_release() override; + +private: + size_t m_old_timestamp = 0; + int m_print_object_idx = -1; + int m_print_objects_count = 0; + std::unique_ptr m_clipper; +}; } // namespace CommonGizmosDataObjects