Cut: ObjectClipper now allows to not render all the contours

This commit is contained in:
Lukas Matena 2023-04-20 11:15:15 +02:00
parent b9bba5ff6b
commit d0ee5e7ca3
6 changed files with 92 additions and 18 deletions

View File

@ -1467,6 +1467,19 @@ void GLGizmoCut3D::on_render()
m_c->selection_info()->set_use_shift(true); m_c->selection_info()->set_use_shift(true);
} }
::glDisable(GL_DEPTH_TEST);
std::vector<Vec3d> pts = m_c->object_clipper()->point_per_contour();
if (! pts.empty()) {
const Vec3d dir = (m_plane_center-pts.front()).dot(m_cut_normal) * m_cut_normal;
for (const Vec3d& pt : pts)
render_model(m_sphere.model, ColorRGBA::GREEN(), wxGetApp().plater()->get_camera().get_view_matrix() * translation_transform(pt+dir));
}
::glEnable(GL_DEPTH_TEST);
update_clipper(); update_clipper();
init_picking_models(); init_picking_models();
@ -1733,7 +1746,7 @@ void GLGizmoCut3D::flip_cut_plane()
} }
GLGizmoCut3D::PartSelection::PartSelection(const ModelObject* mo, const Transform3d& cut_matrix, int instance_idx_in, const Vec3d& center, const Vec3d& normal) GLGizmoCut3D::PartSelection::PartSelection(const ModelObject* mo, const Transform3d& cut_matrix, int instance_idx_in, const Vec3d& center, const Vec3d& normal, const CommonGizmosDataObjects::ObjectClipper& oc)
{ {
m_model = Model(); m_model = Model();
m_model.add_object(*mo); m_model.add_object(*mo);
@ -1773,6 +1786,15 @@ GLGizmoCut3D::PartSelection::PartSelection(const ModelObject* mo, const Transfor
} }
} }
} }
// Now go through the contours and create a map from contours to parts.
if (std::vector<Vec3d> pts = oc.point_per_contour();! pts.empty()) {
const Vec3d dir = (center-pts.front()).dot(normal) * normal;
for (Vec3d& pt : pts)
pt = pt+dir;
// pts are now in world coordinates.
}
m_valid = true; m_valid = true;
} }
@ -1798,7 +1820,7 @@ void GLGizmoCut3D::process_contours()
const int instance_idx = selection.get_instance_idx(); const int instance_idx = selection.get_instance_idx();
const int object_idx = selection.get_object_idx(); const int object_idx = selection.get_object_idx();
m_part_selection = PartSelection(model_objects[object_idx], get_cut_matrix(selection), instance_idx, m_plane_center, m_cut_normal); m_part_selection = PartSelection(model_objects[object_idx], get_cut_matrix(selection), instance_idx, m_plane_center, m_cut_normal, *m_c->object_clipper());
m_parent.toggle_model_objects_visibility(false); m_parent.toggle_model_objects_visibility(false);
} }

View File

@ -20,6 +20,8 @@ class Selection;
enum class SLAGizmoEventType : unsigned char; enum class SLAGizmoEventType : unsigned char;
namespace CommonGizmosDataObjects { class ObjectClipper; }
class GLGizmoCut3D : public GLGizmoBase class GLGizmoCut3D : public GLGizmoBase
{ {
enum GrabberID { enum GrabberID {
@ -140,7 +142,7 @@ class GLGizmoCut3D : public GLGizmoBase
class PartSelection { class PartSelection {
public: public:
PartSelection() = default; PartSelection() = default;
PartSelection(const ModelObject* mo, const Transform3d& cut_matrix, int instance_idx, const Vec3d& center, const Vec3d& normal); PartSelection(const ModelObject* mo, const Transform3d& cut_matrix, int instance_idx, const Vec3d& center, const Vec3d& normal, const CommonGizmosDataObjects::ObjectClipper& oc);
struct Part { struct Part {
GLModel glmodel; GLModel glmodel;

View File

@ -370,21 +370,30 @@ void ObjectClipper::on_release()
} }
void ObjectClipper::render_cut() const void ObjectClipper::render_cut(const std::vector<size_t>* ignore_idxs) const
{ {
if (m_clp_ratio == 0.) if (m_clp_ratio == 0.)
return; return;
const SelectionInfo* sel_info = get_pool()->selection_info(); const SelectionInfo* sel_info = get_pool()->selection_info();
const Geometry::Transformation inst_trafo = sel_info->model_object()->instances[sel_info->get_active_instance()]->get_transformation(); const Geometry::Transformation inst_trafo = sel_info->model_object()->instances[sel_info->get_active_instance()]->get_transformation();
std::vector<size_t> ignore_idxs_local = ignore_idxs ? *ignore_idxs : std::vector<size_t>();
for (auto& clipper : m_clippers) { for (auto& clipper : m_clippers) {
Geometry::Transformation trafo = inst_trafo * clipper.second; Geometry::Transformation trafo = inst_trafo * clipper.second;
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift())); trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift()));
clipper.first->set_plane(*m_clp); clipper.first->set_plane(*m_clp);
clipper.first->set_transformation(trafo); clipper.first->set_transformation(trafo);
clipper.first->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD)); clipper.first->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD));
clipper.first->render_cut({ 1.0f, 0.37f, 0.0f, 1.0f }); clipper.first->render_cut({ 1.0f, 0.37f, 0.0f, 1.0f }, &ignore_idxs_local);
clipper.first->render_contour({ 1.f, 1.f, 1.f, 1.f }); clipper.first->render_contour({ 1.f, 1.f, 1.f, 1.f }, &ignore_idxs_local);
// Now update the ignore idxs. Find the first element belonging to the next clipper,
// and remove everything before it and decrement everything by current number of contours.
const int num_of_contours = clipper.first->get_number_of_contours();
ignore_idxs_local.erase(ignore_idxs_local.begin(), std::find_if(ignore_idxs_local.begin(), ignore_idxs_local.end(), [num_of_contours](size_t idx) { return idx >= num_of_contours; } ));
for (size_t& idx : ignore_idxs_local)
idx -= num_of_contours;
} }
} }
@ -415,6 +424,25 @@ bool ObjectClipper::has_valid_contour() const
return m_clp_ratio != 0. && std::any_of(m_clippers.begin(), m_clippers.end(), [](const auto& cl) { return cl.first->has_valid_contour(); }); return m_clp_ratio != 0. && std::any_of(m_clippers.begin(), m_clippers.end(), [](const auto& cl) { return cl.first->has_valid_contour(); });
} }
std::vector<Vec3d> ObjectClipper::point_per_contour() const
{
std::vector<Vec3d> pts;
const SelectionInfo* sel_info = get_pool()->selection_info();
const Geometry::Transformation inst_trafo = sel_info->model_object()->instances[sel_info->get_active_instance()]->get_transformation();
for (auto& clipper : m_clippers) {
Geometry::Transformation trafo = inst_trafo * clipper.second;
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift()));
// FIXME: do not assume just one clipper
pts = clipper.first->point_per_contour();
//for (Vec3d& v : pts)
// v = trafo.get_matrix() * v;
}
return pts;
}
void ObjectClipper::set_position_by_ratio(double pos, bool keep_normal) void ObjectClipper::set_position_by_ratio(double pos, bool keep_normal)
{ {

View File

@ -242,12 +242,13 @@ public:
void set_normal(const Vec3d& dir); void set_normal(const Vec3d& dir);
double get_position() const { return m_clp_ratio; } double get_position() const { return m_clp_ratio; }
const ClippingPlane* get_clipping_plane(bool ignore_hide_clipped = false) const; const ClippingPlane* get_clipping_plane(bool ignore_hide_clipped = false) const;
void render_cut() const; void render_cut(const std::vector<size_t>* ignore_idxs = nullptr) const;
void set_position_by_ratio(double pos, bool keep_normal); void set_position_by_ratio(double pos, bool keep_normal);
void set_range_and_pos(const Vec3d& cpl_normal, double cpl_offset, double pos); void set_range_and_pos(const Vec3d& cpl_normal, double cpl_offset, double pos);
void set_behavior(bool hide_clipped, bool fill_cut, double contour_width); void set_behavior(bool hide_clipped, bool fill_cut, double contour_width);
int get_number_of_contours() const; int get_number_of_contours() const;
std::vector<Vec3d> point_per_contour() const;
int is_projection_inside_cut(const Vec3d& point_in) const; int is_projection_inside_cut(const Vec3d& point_in) const;
bool has_valid_contour() const; bool has_valid_contour() const;

View File

@ -94,7 +94,7 @@ void MeshClipper::set_transformation(const Geometry::Transformation& trafo)
} }
} }
void MeshClipper::render_cut(const ColorRGBA& color) void MeshClipper::render_cut(const ColorRGBA& color, const std::vector<size_t>* ignore_idxs)
{ {
if (! m_result) if (! m_result)
recalculate_triangles(); recalculate_triangles();
@ -108,7 +108,10 @@ void MeshClipper::render_cut(const ColorRGBA& color)
const Camera& camera = wxGetApp().plater()->get_camera(); const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix()); shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix()); shader->set_uniform("projection_matrix", camera.get_projection_matrix());
for (CutIsland& isl : m_result->cut_islands) { for (size_t i=0; i<m_result->cut_islands.size(); ++i) {
if (ignore_idxs && std::binary_search(ignore_idxs->begin(), ignore_idxs->end(), i))
continue;
CutIsland& isl = m_result->cut_islands[i];
isl.model.set_color(isl.disabled ? ColorRGBA(0.5f, 0.5f, 0.5f, 1.f) : color); isl.model.set_color(isl.disabled ? ColorRGBA(0.5f, 0.5f, 0.5f, 1.f) : color);
isl.model.render(); isl.model.render();
} }
@ -120,7 +123,7 @@ void MeshClipper::render_cut(const ColorRGBA& color)
} }
void MeshClipper::render_contour(const ColorRGBA& color) void MeshClipper::render_contour(const ColorRGBA& color, const std::vector<size_t>* ignore_idxs)
{ {
if (! m_result) if (! m_result)
recalculate_triangles(); recalculate_triangles();
@ -135,7 +138,10 @@ void MeshClipper::render_contour(const ColorRGBA& color)
const Camera& camera = wxGetApp().plater()->get_camera(); const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix()); shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix()); shader->set_uniform("projection_matrix", camera.get_projection_matrix());
for (CutIsland& isl : m_result->cut_islands) { for (size_t i=0; i<m_result->cut_islands.size(); ++i) {
if (ignore_idxs && std::binary_search(ignore_idxs->begin(), ignore_idxs->end(), i))
continue;
CutIsland& isl = m_result->cut_islands[i];
isl.model_expanded.set_color(isl.disabled ? ColorRGBA(1.f, 0.f, 0.f, 1.f) : color); isl.model_expanded.set_color(isl.disabled ? ColorRGBA(1.f, 0.f, 0.f, 1.f) : color);
isl.model_expanded.render(); isl.model_expanded.render();
} }
@ -166,6 +172,20 @@ bool MeshClipper::has_valid_contour() const
return m_result && std::any_of(m_result->cut_islands.begin(), m_result->cut_islands.end(), [](const CutIsland& isl) { return !isl.expoly.empty(); }); return m_result && std::any_of(m_result->cut_islands.begin(), m_result->cut_islands.end(), [](const CutIsland& isl) { return !isl.expoly.empty(); });
} }
std::vector<Vec3d> MeshClipper::point_per_contour() const
{
std::vector<Vec3d> out;
if (!m_result || m_result->cut_islands.empty())
return out;
for (const CutIsland& isl : m_result->cut_islands) {
// FIXME: There might be holes !
Vec2d c = unscale(isl.expoly.contour.centroid());
out.emplace_back(m_result->trafo * Vec3d(c.x(), c.y(), 0.));
}
return out;
}
void MeshClipper::recalculate_triangles() void MeshClipper::recalculate_triangles()
{ {

View File

@ -115,13 +115,14 @@ public:
// Render the triangulated cut. Transformation matrices should // Render the triangulated cut. Transformation matrices should
// be set in world coords. // be set in world coords.
void render_cut(const ColorRGBA& color); void render_cut(const ColorRGBA& color, const std::vector<size_t>* ignore_idxs = nullptr);
void render_contour(const ColorRGBA& color); void render_contour(const ColorRGBA& color, const std::vector<size_t>* ignore_idxs = nullptr);
// Returns index of the contour which was clicked, -1 otherwise. // Returns index of the contour which was clicked, -1 otherwise.
int is_projection_inside_cut(const Vec3d& point) const; int is_projection_inside_cut(const Vec3d& point) const;
bool has_valid_contour() const; bool has_valid_contour() const;
int get_number_of_contours() const { return m_result ? m_result->cut_islands.size() : 0; } int get_number_of_contours() const { return m_result ? m_result->cut_islands.size() : 0; }
std::vector<Vec3d> point_per_contour() const;
private: private:
void recalculate_triangles(); void recalculate_triangles();