Allowed painting in the FDM supports, seam, and multi-material gizmo to only triangles not clipped by a clipping plane.
This commit is contained in:
parent
fc5560aac2
commit
d8a0d0523f
5 changed files with 95 additions and 46 deletions
|
@ -128,13 +128,13 @@ void TriangleSelector::select_patch(const Vec3f& hit, int facet_start,
|
|||
const Vec3f& source, float radius,
|
||||
CursorType cursor_type, EnforcerBlockerType new_state,
|
||||
const Transform3d& trafo, const Transform3d& trafo_no_translate,
|
||||
bool triangle_splitting, float highlight_by_angle_deg)
|
||||
bool triangle_splitting, const ClippingPlane &clp, float highlight_by_angle_deg)
|
||||
{
|
||||
assert(facet_start < m_orig_size_indices);
|
||||
|
||||
// Save current cursor center, squared radius and camera direction, so we don't
|
||||
// have to pass it around.
|
||||
m_cursor = Cursor(hit, source, radius, cursor_type, trafo);
|
||||
m_cursor = Cursor(hit, source, radius, cursor_type, trafo, clp);
|
||||
|
||||
// In case user changed cursor size since last time, update triangle edge limit.
|
||||
// It is necessary to compare the internal radius in m_cursor! radius is in
|
||||
|
@ -172,15 +172,23 @@ void TriangleSelector::select_patch(const Vec3f& hit, int facet_start,
|
|||
}
|
||||
}
|
||||
|
||||
void TriangleSelector::seed_fill_select_triangles(const Vec3f &hit, int facet_start,
|
||||
const Transform3d& trafo_no_translate,
|
||||
float seed_fill_angle, float highlight_by_angle_deg,
|
||||
bool TriangleSelector::is_facet_clipped(int facet_idx, const ClippingPlane &clp) const
|
||||
{
|
||||
for (int vert_idx : m_triangles[facet_idx].verts_idxs)
|
||||
if (clp.is_active() && clp.is_mesh_point_clipped(m_vertices[vert_idx].v))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
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,
|
||||
bool force_reselection)
|
||||
{
|
||||
assert(facet_start < m_orig_size_indices);
|
||||
|
||||
// Recompute seed fill only if the cursor is pointing on facet unselected by seed fill.
|
||||
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)
|
||||
// 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())
|
||||
return;
|
||||
|
||||
this->seed_fill_unselect_all_triangles();
|
||||
|
@ -215,7 +223,7 @@ void TriangleSelector::seed_fill_select_triangles(const Vec3f &hit, int facet_st
|
|||
// Propagate over the original triangles.
|
||||
for (int neighbor_idx : m_neighbors[current_facet]) {
|
||||
assert(neighbor_idx >= -1);
|
||||
if (neighbor_idx >= 0 && !visited[neighbor_idx]) {
|
||||
if (neighbor_idx >= 0 && !visited[neighbor_idx] && !is_facet_clipped(neighbor_idx, clp)) {
|
||||
// Check if neighbour_facet_idx is satisfies angle in seed_fill_angle and append it to facet_queue if it do.
|
||||
const Vec3f &n1 = m_face_normals[m_triangles[neighbor_idx].source_triangle];
|
||||
const Vec3f &n2 = m_face_normals[m_triangles[current_facet].source_triangle];
|
||||
|
@ -331,12 +339,12 @@ void TriangleSelector::append_touching_edges(int itriangle, int vertexi, int ver
|
|||
process_subtriangle(touching.second, Partition::Second);
|
||||
}
|
||||
|
||||
void TriangleSelector::bucket_fill_select_triangles(const Vec3f& hit, int facet_start, bool propagate, bool force_reselection)
|
||||
void TriangleSelector::bucket_fill_select_triangles(const Vec3f& hit, int facet_start, const ClippingPlane &clp, bool propagate, bool force_reselection)
|
||||
{
|
||||
int start_facet_idx = select_unsplit_triangle(hit, facet_start);
|
||||
assert(start_facet_idx != -1);
|
||||
// Recompute bucket fill only if the cursor is pointing on facet unselected by bucket fill.
|
||||
if (start_facet_idx == -1 || (m_triangles[start_facet_idx].is_selected_by_seed_fill() && !force_reselection))
|
||||
// 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()))
|
||||
return;
|
||||
|
||||
assert(!m_triangles[start_facet_idx].is_split());
|
||||
|
@ -379,7 +387,7 @@ void TriangleSelector::bucket_fill_select_triangles(const Vec3f& hit, int facet_
|
|||
|
||||
std::vector<int> touching_triangles = get_all_touching_triangles(current_facet, neighbors[current_facet], neighbors_propagated[current_facet]);
|
||||
for(const int tr_idx : touching_triangles) {
|
||||
if (tr_idx < 0 || visited[tr_idx] || m_triangles[tr_idx].get_state() != start_facet_state)
|
||||
if (tr_idx < 0 || visited[tr_idx] || m_triangles[tr_idx].get_state() != start_facet_state || is_facet_clipped(tr_idx, clp))
|
||||
continue;
|
||||
|
||||
assert(!m_triangles[tr_idx].is_split());
|
||||
|
@ -1687,11 +1695,12 @@ void TriangleSelector::seed_fill_apply_on_triangles(EnforcerBlockerType new_stat
|
|||
|
||||
TriangleSelector::Cursor::Cursor(
|
||||
const Vec3f& center_, const Vec3f& source_, float radius_world,
|
||||
CursorType type_, const Transform3d& trafo_)
|
||||
CursorType type_, const Transform3d& trafo_, const ClippingPlane &clipping_plane_)
|
||||
: center{center_},
|
||||
source{source_},
|
||||
type{type_},
|
||||
trafo{trafo_.cast<float>()}
|
||||
trafo{trafo_.cast<float>()},
|
||||
clipping_plane(clipping_plane_)
|
||||
{
|
||||
Vec3d sf = Geometry::Transformation(trafo_).get_scaling_factor();
|
||||
if (is_approx(sf(0), sf(1)) && is_approx(sf(1), sf(2))) {
|
||||
|
@ -1714,22 +1723,19 @@ TriangleSelector::Cursor::Cursor(
|
|||
dir = (center - source).normalized();
|
||||
}
|
||||
|
||||
|
||||
// Is a point (in mesh coords) inside a cursor?
|
||||
bool TriangleSelector::Cursor::is_mesh_point_inside(Vec3f point) const
|
||||
bool TriangleSelector::Cursor::is_mesh_point_inside(const Vec3f &point) const
|
||||
{
|
||||
if (! uniform_scaling)
|
||||
point = trafo * point;
|
||||
const Vec3f transformed_point = uniform_scaling ? point : Vec3f(trafo * point);
|
||||
const Vec3f diff = center - transformed_point;
|
||||
const bool is_point_inside = (type == CIRCLE ? (diff - diff.dot(dir) * dir).squaredNorm() : diff.squaredNorm()) < radius_sqr;
|
||||
|
||||
Vec3f diff = center - point;
|
||||
return (type == CIRCLE ?
|
||||
(diff - diff.dot(dir) * dir).squaredNorm() :
|
||||
diff.squaredNorm())
|
||||
< radius_sqr;
|
||||
if (is_point_inside && clipping_plane.is_active())
|
||||
return !clipping_plane.is_mesh_point_clipped(point);
|
||||
|
||||
return is_point_inside;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// p1, p2, p3 are in mesh coords!
|
||||
bool TriangleSelector::Cursor::is_pointer_in_triangle(const Vec3f& p1_,
|
||||
const Vec3f& p2_,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue