mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-14 23:25:59 +08:00
Small refactoring of Cursors in TriangleSelector.
This commit is contained in:
parent
d23e114aed
commit
f253822707
@ -247,21 +247,15 @@ void TriangleSelector::select_patch(int facet_start, std::unique_ptr<Cursor> &&c
|
|||||||
// have to pass it around.
|
// have to pass it around.
|
||||||
m_cursor = std::move(cursor);
|
m_cursor = std::move(cursor);
|
||||||
|
|
||||||
// In case user changed cursor size since last time, update triangle edge limit.
|
// In case user changed cursor parameters size since last time, update triangle edge limit.
|
||||||
// It is necessary to compare the internal radius in m_cursor! radius is in
|
set_edge_limit(m_cursor->get_edge_limit());
|
||||||
// world coords and does not change after scaling.
|
|
||||||
if (m_old_cursor_radius_sqr != m_cursor->radius_sqr) {
|
|
||||||
set_edge_limit(std::sqrt(m_cursor->radius_sqr) / 5.f);
|
|
||||||
m_old_cursor_radius_sqr = m_cursor->radius_sqr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const float highlight_angle_limit = cos(Geometry::deg2rad(highlight_by_angle_deg));
|
const float highlight_angle_limit = cos(Geometry::deg2rad(highlight_by_angle_deg));
|
||||||
Vec3f vec_down = (trafo_no_translate.inverse() * -Vec3d::UnitZ()).normalized().cast<float>();
|
Vec3f vec_down = (trafo_no_translate.inverse() * -Vec3d::UnitZ()).normalized().cast<float>();
|
||||||
|
|
||||||
// Now start with the facet the pointer points to and check all adjacent facets.
|
// Now start with the facet the pointer points to and check all adjacent facets.
|
||||||
std::vector<int> facets_to_check;
|
std::vector<int> facets_to_check = m_cursor->get_facets_to_select(facet_start, m_vertices, m_triangles, m_orig_size_vertices, m_orig_size_indices);
|
||||||
facets_to_check.reserve(16);
|
facets_to_check.reserve(16);
|
||||||
facets_to_check.emplace_back(facet_start);
|
|
||||||
// Keep track of facets of the original mesh we already processed.
|
// Keep track of facets of the original mesh we already processed.
|
||||||
std::vector<bool> visited(m_orig_size_indices, false);
|
std::vector<bool> visited(m_orig_size_indices, false);
|
||||||
// Breadth-first search around the hit point. facets_to_check may grow significantly large.
|
// Breadth-first search around the hit point. facets_to_check may grow significantly large.
|
||||||
@ -293,13 +287,13 @@ bool TriangleSelector::is_facet_clipped(int facet_idx, const ClippingPlane &clp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TriangleSelector::seed_fill_select_triangles(const Vec3f &hit, int facet_start, const Transform3d& trafo_no_translate,
|
void TriangleSelector::seed_fill_select_triangles(const Vec3f &hit, int facet_start, const Transform3d& trafo_no_translate,
|
||||||
const ClippingPlane &clp, float seed_fill_angle, float highlight_by_angle_deg,
|
const ClippingPlane &clp, float seed_fill_angle,
|
||||||
bool force_reselection)
|
float highlight_by_angle_deg, ForceReselection force_reselection)
|
||||||
{
|
{
|
||||||
assert(facet_start < m_orig_size_indices);
|
assert(facet_start < m_orig_size_indices);
|
||||||
|
|
||||||
// Recompute seed fill only if the cursor is pointing on facet unselected by seed fill or a clipping plane is active.
|
// Recompute seed fill only if the cursor is pointing on facet unselected by seed fill or a clipping plane is active.
|
||||||
if (int start_facet_idx = select_unsplit_triangle(hit, facet_start); start_facet_idx >= 0 && m_triangles[start_facet_idx].is_selected_by_seed_fill() && !force_reselection && !clp.is_active())
|
if (int start_facet_idx = select_unsplit_triangle(hit, facet_start); start_facet_idx >= 0 && m_triangles[start_facet_idx].is_selected_by_seed_fill() && force_reselection == ForceReselection::NO && !clp.is_active())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this->seed_fill_unselect_all_triangles();
|
this->seed_fill_unselect_all_triangles();
|
||||||
@ -451,19 +445,20 @@ void TriangleSelector::append_touching_edges(int itriangle, int vertexi, int ver
|
|||||||
process_subtriangle(touching.second, Partition::Second);
|
process_subtriangle(touching.second, Partition::Second);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleSelector::bucket_fill_select_triangles(const Vec3f& hit, int facet_start, const ClippingPlane &clp, bool propagate, bool force_reselection)
|
void TriangleSelector::bucket_fill_select_triangles(const Vec3f &hit, int facet_start, const ClippingPlane &clp,
|
||||||
{
|
BucketFillPropagate propagate,
|
||||||
|
ForceReselection force_reselection) {
|
||||||
int start_facet_idx = select_unsplit_triangle(hit, facet_start);
|
int start_facet_idx = select_unsplit_triangle(hit, facet_start);
|
||||||
assert(start_facet_idx != -1);
|
assert(start_facet_idx != -1);
|
||||||
// Recompute bucket fill only if the cursor is pointing on facet unselected by bucket fill or a clipping plane is active.
|
// Recompute bucket fill only if the cursor is pointing on facet unselected by bucket fill or a clipping plane is active.
|
||||||
if (start_facet_idx == -1 || (m_triangles[start_facet_idx].is_selected_by_seed_fill() && !force_reselection && !clp.is_active()))
|
if (start_facet_idx == -1 || (m_triangles[start_facet_idx].is_selected_by_seed_fill() && force_reselection == ForceReselection::NO && !clp.is_active()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(!m_triangles[start_facet_idx].is_split());
|
assert(!m_triangles[start_facet_idx].is_split());
|
||||||
TriangleStateType start_facet_state = m_triangles[start_facet_idx].get_state();
|
TriangleStateType start_facet_state = m_triangles[start_facet_idx].get_state();
|
||||||
this->seed_fill_unselect_all_triangles();
|
this->seed_fill_unselect_all_triangles();
|
||||||
|
|
||||||
if (!propagate) {
|
if (propagate == BucketFillPropagate::NO) {
|
||||||
m_triangles[start_facet_idx].select_by_seed_fill();
|
m_triangles[start_facet_idx].select_by_seed_fill();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -878,7 +873,7 @@ bool TriangleSelector::select_triangle_recursive(int facet_idx, const Vec3i &nei
|
|||||||
|
|
||||||
if (num_of_inside_vertices == 0
|
if (num_of_inside_vertices == 0
|
||||||
&& ! m_cursor->is_pointer_in_triangle(*tr, m_vertices)
|
&& ! m_cursor->is_pointer_in_triangle(*tr, m_vertices)
|
||||||
&& ! m_cursor->is_edge_inside_cursor(*tr, m_vertices))
|
&& ! m_cursor->is_any_edge_inside_cursor(*tr, m_vertices))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (num_of_inside_vertices == 3) {
|
if (num_of_inside_vertices == 3) {
|
||||||
@ -1011,16 +1006,21 @@ int TriangleSelector::Cursor::vertices_inside(const Triangle &tr, const std::vec
|
|||||||
return inside;
|
return inside;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is any edge inside Sphere cursor?
|
inline std::array<Vec3f, 3> TriangleSelector::Cursor::transform_triangle(const Triangle &tr, const std::vector<Vertex> &vertices) const {
|
||||||
bool TriangleSelector::Sphere::is_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const
|
|
||||||
{
|
|
||||||
std::array<Vec3f, 3> pts;
|
std::array<Vec3f, 3> pts;
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (size_t i = 0; i < 3; ++i) {
|
||||||
pts[i] = vertices[tr.verts_idxs[i]].v;
|
pts[i] = vertices[tr.verts_idxs[i]].v;
|
||||||
if (!this->uniform_scaling)
|
if (!this->uniform_scaling)
|
||||||
pts[i] = this->trafo * pts[i];
|
pts[i] = this->trafo * pts[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return pts;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is any edge inside Sphere cursor?
|
||||||
|
bool TriangleSelector::Sphere::is_any_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const
|
||||||
|
{
|
||||||
|
const std::array<Vec3f, 3> pts = this->transform_triangle(tr, vertices);
|
||||||
for (int side = 0; side < 3; ++side) {
|
for (int side = 0; side < 3; ++side) {
|
||||||
const Vec3f &edge_a = pts[side];
|
const Vec3f &edge_a = pts[side];
|
||||||
const Vec3f &edge_b = pts[side < 2 ? side + 1 : 0];
|
const Vec3f &edge_b = pts[side < 2 ? side + 1 : 0];
|
||||||
@ -1031,15 +1031,9 @@ bool TriangleSelector::Sphere::is_edge_inside_cursor(const Triangle &tr, const s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Is edge inside cursor?
|
// Is edge inside cursor?
|
||||||
bool TriangleSelector::Circle::is_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const
|
bool TriangleSelector::Circle::is_any_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const
|
||||||
{
|
{
|
||||||
std::array<Vec3f, 3> pts;
|
const std::array<Vec3f, 3> pts = this->transform_triangle(tr, vertices);
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
pts[i] = vertices[tr.verts_idxs[i]].v;
|
|
||||||
if (!this->uniform_scaling)
|
|
||||||
pts[i] = this->trafo * pts[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vec3f &p = this->center;
|
const Vec3f &p = this->center;
|
||||||
for (int side = 0; side < 3; ++side) {
|
for (int side = 0; side < 3; ++side) {
|
||||||
const Vec3f &a = pts[side];
|
const Vec3f &a = pts[side];
|
||||||
@ -1216,7 +1210,7 @@ void TriangleSelector::reset()
|
|||||||
|
|
||||||
void TriangleSelector::set_edge_limit(float edge_limit)
|
void TriangleSelector::set_edge_limit(float edge_limit)
|
||||||
{
|
{
|
||||||
m_edge_limit_sqr = std::pow(edge_limit, 2.f);
|
m_edge_limit_sqr = Slic3r::sqr(edge_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
int TriangleSelector::push_triangle(int a, int b, int c, int source_triangle, const TriangleStateType state) {
|
int TriangleSelector::push_triangle(int a, int b, int c, int source_triangle, const TriangleStateType state) {
|
||||||
@ -1890,6 +1884,8 @@ TriangleSelector::Cursor::Cursor(const Vec3f &source_, float radius_world, const
|
|||||||
radius_sqr = Slic3r::sqr(radius_world);
|
radius_sqr = Slic3r::sqr(radius_world);
|
||||||
trafo_normal = trafo.linear().inverse().transpose();
|
trafo_normal = trafo.linear().inverse().transpose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_edge_limit = std::sqrt(radius_sqr) / 5.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
TriangleSelector::SinglePointCursor::SinglePointCursor(const Vec3f& center_, const Vec3f& source_, float radius_world, const Transform3d& trafo_, const ClippingPlane &clipping_plane_)
|
TriangleSelector::SinglePointCursor::SinglePointCursor(const Vec3f& center_, const Vec3f& source_, float radius_world, const Transform3d& trafo_, const ClippingPlane &clipping_plane_)
|
||||||
@ -2048,15 +2044,9 @@ bool line_plane_intersection(const Vec3f &line_a, const Vec3f &line_b, const Vec
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TriangleSelector::Capsule3D::is_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const
|
bool TriangleSelector::Capsule3D::is_any_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const
|
||||||
{
|
{
|
||||||
std::array<Vec3f, 3> pts;
|
const std::array<Vec3f, 3> pts = this->transform_triangle(tr, vertices);
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
pts[i] = vertices[tr.verts_idxs[i]].v;
|
|
||||||
if (!this->uniform_scaling)
|
|
||||||
pts[i] = this->trafo * pts[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int side = 0; side < 3; ++side) {
|
for (int side = 0; side < 3; ++side) {
|
||||||
const Vec3f &edge_a = pts[side];
|
const Vec3f &edge_a = pts[side];
|
||||||
const Vec3f &edge_b = pts[side < 2 ? side + 1 : 0];
|
const Vec3f &edge_b = pts[side < 2 ? side + 1 : 0];
|
||||||
@ -2068,15 +2058,8 @@ bool TriangleSelector::Capsule3D::is_edge_inside_cursor(const Triangle &tr, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Is edge inside cursor?
|
// Is edge inside cursor?
|
||||||
bool TriangleSelector::Capsule2D::is_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const
|
bool TriangleSelector::Capsule2D::is_any_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const
|
||||||
{
|
{
|
||||||
std::array<Vec3f, 3> pts;
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
|
||||||
pts[i] = vertices[tr.verts_idxs[i]].v;
|
|
||||||
if (!this->uniform_scaling)
|
|
||||||
pts[i] = this->trafo * pts[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vec3f centers_diff = this->second_center - this->first_center;
|
const Vec3f centers_diff = this->second_center - this->first_center;
|
||||||
// Vector in the direction of line |AD| of the rectangle that intersects the circle with the center in first_center.
|
// Vector in the direction of line |AD| of the rectangle that intersects the circle with the center in first_center.
|
||||||
const Vec3f rectangle_da_dir = centers_diff.cross(this->dir);
|
const Vec3f rectangle_da_dir = centers_diff.cross(this->dir);
|
||||||
@ -2095,6 +2078,7 @@ bool TriangleSelector::Capsule2D::is_edge_inside_cursor(const Triangle &tr, cons
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const std::array<Vec3f, 3> pts = this->transform_triangle(tr, vertices);
|
||||||
for (int side = 0; side < 3; ++side) {
|
for (int side = 0; side < 3; ++side) {
|
||||||
const Vec3f &edge_a = pts[side];
|
const Vec3f &edge_a = pts[side];
|
||||||
const Vec3f &edge_b = pts[side < 2 ? side + 1 : 0];
|
const Vec3f &edge_b = pts[side < 2 ? side + 1 : 0];
|
||||||
|
@ -67,12 +67,22 @@ protected:
|
|||||||
struct Vertex;
|
struct Vertex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum CursorType {
|
enum class CursorType {
|
||||||
CIRCLE,
|
CIRCLE,
|
||||||
SPHERE,
|
SPHERE,
|
||||||
POINTER
|
POINTER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class ForceReselection {
|
||||||
|
NO,
|
||||||
|
YES
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BucketFillPropagate {
|
||||||
|
NO,
|
||||||
|
YES
|
||||||
|
};
|
||||||
|
|
||||||
struct ClippingPlane
|
struct ClippingPlane
|
||||||
{
|
{
|
||||||
Vec3f normal;
|
Vec3f normal;
|
||||||
@ -91,14 +101,21 @@ public:
|
|||||||
Cursor() = delete;
|
Cursor() = delete;
|
||||||
virtual ~Cursor() = default;
|
virtual ~Cursor() = default;
|
||||||
|
|
||||||
|
float get_edge_limit() { return m_edge_limit; };
|
||||||
|
|
||||||
bool is_pointer_in_triangle(const Triangle &tr, const std::vector<Vertex> &vertices) const;
|
bool is_pointer_in_triangle(const Triangle &tr, const std::vector<Vertex> &vertices) const;
|
||||||
|
std::array<Vec3f, 3> transform_triangle(const Triangle &tr, const std::vector<Vertex> &vertices) const;
|
||||||
|
|
||||||
virtual bool is_mesh_point_inside(const Vec3f &point) const = 0;
|
virtual bool is_mesh_point_inside(const Vec3f &point) const = 0;
|
||||||
virtual bool is_pointer_in_triangle(const Vec3f &p1, const Vec3f &p2, const Vec3f &p3) const = 0;
|
virtual bool is_pointer_in_triangle(const Vec3f &p1, const Vec3f &p2, const Vec3f &p3) const = 0;
|
||||||
virtual int vertices_inside(const Triangle &tr, const std::vector<Vertex> &vertices) const;
|
virtual int vertices_inside(const Triangle &tr, const std::vector<Vertex> &vertices) const;
|
||||||
virtual bool is_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const = 0;
|
virtual bool is_any_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const = 0;
|
||||||
virtual bool is_facet_visible(int facet_idx, const std::vector<Vec3f> &face_normals) const = 0;
|
virtual bool is_facet_visible(int facet_idx, const std::vector<Vec3f> &face_normals) const = 0;
|
||||||
|
|
||||||
|
virtual std::vector<int> get_facets_to_select(int facet_idx, const std::vector<Vertex> &vertices, const std::vector<Triangle> &triangles, int orig_size_vertices, int orig_size_indices) const {
|
||||||
|
return { facet_idx };
|
||||||
|
};
|
||||||
|
|
||||||
static bool is_facet_visible(const Cursor &cursor, int facet_idx, const std::vector<Vec3f> &face_normals);
|
static bool is_facet_visible(const Cursor &cursor, int facet_idx, const std::vector<Vec3f> &face_normals);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -115,6 +132,8 @@ public:
|
|||||||
|
|
||||||
ClippingPlane clipping_plane; // Clipping plane to limit painting to not clipped facets only
|
ClippingPlane clipping_plane; // Clipping plane to limit painting to not clipped facets only
|
||||||
|
|
||||||
|
float m_edge_limit;
|
||||||
|
|
||||||
friend TriangleSelector;
|
friend TriangleSelector;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -174,7 +193,7 @@ public:
|
|||||||
~Sphere() override = default;
|
~Sphere() override = default;
|
||||||
|
|
||||||
bool is_mesh_point_inside(const Vec3f &point) const override;
|
bool is_mesh_point_inside(const Vec3f &point) const override;
|
||||||
bool is_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const override;
|
bool is_any_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const override;
|
||||||
bool is_facet_visible(int facet_idx, const std::vector<Vec3f> &face_normals) const override { return true; }
|
bool is_facet_visible(int facet_idx, const std::vector<Vec3f> &face_normals) const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -187,9 +206,8 @@ public:
|
|||||||
~Circle() override = default;
|
~Circle() override = default;
|
||||||
|
|
||||||
bool is_mesh_point_inside(const Vec3f &point) const override;
|
bool is_mesh_point_inside(const Vec3f &point) const override;
|
||||||
bool is_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const override;
|
bool is_any_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const override;
|
||||||
bool is_facet_visible(int facet_idx, const std::vector<Vec3f> &face_normals) const override
|
bool is_facet_visible(int facet_idx, const std::vector<Vec3f> &face_normals) const override {
|
||||||
{
|
|
||||||
return TriangleSelector::Cursor::is_facet_visible(*this, facet_idx, face_normals);
|
return TriangleSelector::Cursor::is_facet_visible(*this, facet_idx, face_normals);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -204,7 +222,7 @@ public:
|
|||||||
~Capsule3D() override = default;
|
~Capsule3D() override = default;
|
||||||
|
|
||||||
bool is_mesh_point_inside(const Vec3f &point) const override;
|
bool is_mesh_point_inside(const Vec3f &point) const override;
|
||||||
bool is_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const override;
|
bool is_any_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const override;
|
||||||
bool is_facet_visible(int facet_idx, const std::vector<Vec3f> &face_normals) const override { return true; }
|
bool is_facet_visible(int facet_idx, const std::vector<Vec3f> &face_normals) const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -218,9 +236,8 @@ public:
|
|||||||
~Capsule2D() override = default;
|
~Capsule2D() override = default;
|
||||||
|
|
||||||
bool is_mesh_point_inside(const Vec3f &point) const override;
|
bool is_mesh_point_inside(const Vec3f &point) const override;
|
||||||
bool is_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const override;
|
bool is_any_edge_inside_cursor(const Triangle &tr, const std::vector<Vertex> &vertices) const override;
|
||||||
bool is_facet_visible(int facet_idx, const std::vector<Vec3f> &face_normals) const override
|
bool is_facet_visible(int facet_idx, const std::vector<Vec3f> &face_normals) const override {
|
||||||
{
|
|
||||||
return TriangleSelector::Cursor::is_facet_visible(*this, facet_idx, face_normals);
|
return TriangleSelector::Cursor::is_facet_visible(*this, facet_idx, face_normals);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -304,13 +321,13 @@ public:
|
|||||||
const ClippingPlane &clp, // Clipping plane to limit painting to not clipped facets only
|
const ClippingPlane &clp, // Clipping plane to limit painting to not clipped facets only
|
||||||
float seed_fill_angle, // the maximal angle between two facets to be painted by the same color
|
float seed_fill_angle, // the maximal angle between two facets to be painted by the same color
|
||||||
float highlight_by_angle_deg = 0.f, // The maximal angle of overhang. If it is set to a non-zero value, it is possible to paint only the triangles of overhang defined by this angle in degrees.
|
float highlight_by_angle_deg = 0.f, // The maximal angle of overhang. If it is set to a non-zero value, it is possible to paint only the triangles of overhang defined by this angle in degrees.
|
||||||
bool force_reselection = false); // force reselection of the triangle mesh even in cases that mouse is pointing on the selected triangle
|
ForceReselection force_reselection = ForceReselection::NO); // force reselection of the triangle mesh even in cases that mouse is pointing on the selected triangle
|
||||||
|
|
||||||
void bucket_fill_select_triangles(const Vec3f &hit, // point where to start
|
void bucket_fill_select_triangles(const Vec3f &hit, // point where to start
|
||||||
int facet_start, // facet of the original mesh (unsplit) that the hit point belongs to
|
int facet_start, // facet of the original mesh (unsplit) that the hit point belongs to
|
||||||
const ClippingPlane &clp, // Clipping plane to limit painting to not clipped facets only
|
const ClippingPlane &clp, // Clipping plane to limit painting to not clipped facets only
|
||||||
bool propagate, // if bucket fill is propagated to neighbor faces or if it fills the only facet of the modified mesh that the hit point belongs to.
|
BucketFillPropagate propagate, // if bucket fill is propagated to neighbor faces or if it fills the only facet of the modified mesh that the hit point belongs to.
|
||||||
bool force_reselection = false); // force reselection of the triangle mesh even in cases that mouse is pointing on the selected triangle
|
ForceReselection force_reselection = ForceReselection::NO); // force reselection of the triangle mesh even in cases that mouse is pointing on the selected triangle
|
||||||
|
|
||||||
bool has_facets(TriangleStateType state) const;
|
bool has_facets(TriangleStateType state) const;
|
||||||
static bool has_facets(const TriangleSplittingData &data, TriangleStateType test_state);
|
static bool has_facets(const TriangleSplittingData &data, TriangleStateType test_state);
|
||||||
@ -450,8 +467,6 @@ protected:
|
|||||||
int m_orig_size_indices = 0;
|
int m_orig_size_indices = 0;
|
||||||
|
|
||||||
std::unique_ptr<Cursor> m_cursor;
|
std::unique_ptr<Cursor> m_cursor;
|
||||||
// Zero indicates an uninitialized state.
|
|
||||||
float m_old_cursor_radius_sqr = 0;
|
|
||||||
|
|
||||||
// Private functions:
|
// Private functions:
|
||||||
private:
|
private:
|
||||||
|
@ -139,9 +139,9 @@ void GLGizmoPainterBase::render_cursor()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_tool_type == ToolType::BRUSH) {
|
if (m_tool_type == ToolType::BRUSH) {
|
||||||
if (m_cursor_type == TriangleSelector::SPHERE)
|
if (m_cursor_type == TriangleSelector::CursorType::SPHERE)
|
||||||
render_cursor_sphere(trafo_matrices[m_rr.mesh_id]);
|
render_cursor_sphere(trafo_matrices[m_rr.mesh_id]);
|
||||||
else if (m_cursor_type == TriangleSelector::CIRCLE)
|
else if (m_cursor_type == TriangleSelector::CursorType::CIRCLE)
|
||||||
render_cursor_circle();
|
render_cursor_circle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -480,7 +480,7 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||||||
const Transform3d trafo_matrix_not_translate = mi->get_transformation().get_matrix_no_offset() * mo->volumes[m_rr.mesh_id]->get_matrix_no_offset();
|
const Transform3d trafo_matrix_not_translate = mi->get_transformation().get_matrix_no_offset() * mo->volumes[m_rr.mesh_id]->get_matrix_no_offset();
|
||||||
const Transform3d trafo_matrix = mi->get_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix();
|
const Transform3d trafo_matrix = mi->get_transformation().get_matrix() * mo->volumes[m_rr.mesh_id]->get_matrix();
|
||||||
m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), trafo_matrix_not_translate, this->get_clipping_plane_in_volume_coordinates(trafo_matrix), m_smart_fill_angle,
|
m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), trafo_matrix_not_translate, this->get_clipping_plane_in_volume_coordinates(trafo_matrix), m_smart_fill_angle,
|
||||||
m_paint_on_overhangs_only ? m_highlight_by_angle_threshold_deg : 0.f, true);
|
m_paint_on_overhangs_only ? m_highlight_by_angle_threshold_deg : 0.f, TriangleSelector::ForceReselection::YES);
|
||||||
m_triangle_selectors[m_rr.mesh_id]->request_update_render_data();
|
m_triangle_selectors[m_rr.mesh_id]->request_update_render_data();
|
||||||
m_seed_fill_last_mesh_id = m_rr.mesh_id;
|
m_seed_fill_last_mesh_id = m_rr.mesh_id;
|
||||||
}
|
}
|
||||||
@ -561,13 +561,14 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||||||
const Vec3f mesh_hit = projected_mouse_position.mesh_hit;
|
const Vec3f mesh_hit = projected_mouse_position.mesh_hit;
|
||||||
const int facet_idx = int(projected_mouse_position.facet_idx);
|
const int facet_idx = int(projected_mouse_position.facet_idx);
|
||||||
m_triangle_selectors[mesh_idx]->seed_fill_apply_on_triangles(new_state);
|
m_triangle_selectors[mesh_idx]->seed_fill_apply_on_triangles(new_state);
|
||||||
if (m_tool_type == ToolType::SMART_FILL)
|
if (m_tool_type == ToolType::SMART_FILL) {
|
||||||
m_triangle_selectors[mesh_idx]->seed_fill_select_triangles(mesh_hit, facet_idx, trafo_matrix_not_translate, clp, m_smart_fill_angle,
|
m_triangle_selectors[mesh_idx]->seed_fill_select_triangles(mesh_hit, facet_idx, trafo_matrix_not_translate, clp, m_smart_fill_angle,
|
||||||
m_paint_on_overhangs_only ? m_highlight_by_angle_threshold_deg : 0.f, true);
|
(m_paint_on_overhangs_only ? m_highlight_by_angle_threshold_deg : 0.f), TriangleSelector::ForceReselection::YES);
|
||||||
else if (m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::POINTER)
|
} else if (m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::POINTER) {
|
||||||
m_triangle_selectors[mesh_idx]->bucket_fill_select_triangles(mesh_hit, facet_idx, clp, false, true);
|
m_triangle_selectors[mesh_idx]->bucket_fill_select_triangles(mesh_hit, facet_idx, clp, TriangleSelector::BucketFillPropagate::NO, TriangleSelector::ForceReselection::YES);
|
||||||
else if (m_tool_type == ToolType::BUCKET_FILL)
|
} else if (m_tool_type == ToolType::BUCKET_FILL) {
|
||||||
m_triangle_selectors[mesh_idx]->bucket_fill_select_triangles(mesh_hit, facet_idx, clp, true, true);
|
m_triangle_selectors[mesh_idx]->bucket_fill_select_triangles(mesh_hit, facet_idx, clp, TriangleSelector::BucketFillPropagate::YES, TriangleSelector::ForceReselection::YES);
|
||||||
|
}
|
||||||
|
|
||||||
m_seed_fill_last_mesh_id = -1;
|
m_seed_fill_last_mesh_id = -1;
|
||||||
}
|
}
|
||||||
@ -649,9 +650,9 @@ bool GLGizmoPainterBase::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||||||
m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), trafo_matrix_not_translate, clp, m_smart_fill_angle,
|
m_triangle_selectors[m_rr.mesh_id]->seed_fill_select_triangles(m_rr.hit, int(m_rr.facet), trafo_matrix_not_translate, clp, m_smart_fill_angle,
|
||||||
m_paint_on_overhangs_only ? m_highlight_by_angle_threshold_deg : 0.f);
|
m_paint_on_overhangs_only ? m_highlight_by_angle_threshold_deg : 0.f);
|
||||||
else if (m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::POINTER)
|
else if (m_tool_type == ToolType::BRUSH && m_cursor_type == TriangleSelector::CursorType::POINTER)
|
||||||
m_triangle_selectors[m_rr.mesh_id]->bucket_fill_select_triangles(m_rr.hit, int(m_rr.facet), clp, false);
|
m_triangle_selectors[m_rr.mesh_id]->bucket_fill_select_triangles(m_rr.hit, int(m_rr.facet), clp, TriangleSelector::BucketFillPropagate::NO);
|
||||||
else if (m_tool_type == ToolType::BUCKET_FILL)
|
else if (m_tool_type == ToolType::BUCKET_FILL)
|
||||||
m_triangle_selectors[m_rr.mesh_id]->bucket_fill_select_triangles(m_rr.hit, int(m_rr.facet), clp, true);
|
m_triangle_selectors[m_rr.mesh_id]->bucket_fill_select_triangles(m_rr.hit, int(m_rr.facet), clp, TriangleSelector::BucketFillPropagate::YES);
|
||||||
m_triangle_selectors[m_rr.mesh_id]->request_update_render_data();
|
m_triangle_selectors[m_rr.mesh_id]->request_update_render_data();
|
||||||
m_seed_fill_last_mesh_id = m_rr.mesh_id;
|
m_seed_fill_last_mesh_id = m_rr.mesh_id;
|
||||||
return true;
|
return true;
|
||||||
|
@ -132,7 +132,7 @@ protected:
|
|||||||
// For each model-part volume, store status and division of the triangles.
|
// For each model-part volume, store status and division of the triangles.
|
||||||
std::vector<std::unique_ptr<TriangleSelectorGUI>> m_triangle_selectors;
|
std::vector<std::unique_ptr<TriangleSelectorGUI>> m_triangle_selectors;
|
||||||
|
|
||||||
TriangleSelector::CursorType m_cursor_type = TriangleSelector::SPHERE;
|
TriangleSelector::CursorType m_cursor_type = TriangleSelector::CursorType::SPHERE;
|
||||||
|
|
||||||
enum class ToolType {
|
enum class ToolType {
|
||||||
BRUSH,
|
BRUSH,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user