mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-05-20 20:03:47 +00:00
Check normal before expanding the painting to neighboring faces
This commit is contained in:
@@ -171,7 +171,7 @@ void TriangleSelector::Triangle::set_division(int sides_to_split, int special_si
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Real-time collision detection, Ericson, Chapter 3.4
|
// Real-time collision detection, Ericson, Chapter 3.4
|
||||||
inline Vec3f barycentric(const Vec3f& pt, const Vec3f& p1, const Vec3f& p2, const Vec3f& p3)
|
static Vec3f barycentric(const Vec3f& pt, const Vec3f& p1, const Vec3f& p2, const Vec3f& p3)
|
||||||
{
|
{
|
||||||
std::array<Vec3f, 3> v = {p2 - p1, p3 - p1, pt - p1};
|
std::array<Vec3f, 3> v = {p2 - p1, p3 - p1, pt - p1};
|
||||||
float d00 = v[0].dot(v[0]);
|
float d00 = v[0].dot(v[0]);
|
||||||
@@ -186,7 +186,7 @@ inline Vec3f barycentric(const Vec3f& pt, const Vec3f& p1, const Vec3f& p2, cons
|
|||||||
return barycentric_cords;
|
return barycentric_cords;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_point_inside_triangle(const Vec3f &pt, const Vec3f &p1, const Vec3f &p2, const Vec3f &p3)
|
static bool is_point_inside_triangle(const Vec3f &pt, const Vec3f &p1, const Vec3f &p2, const Vec3f &p3)
|
||||||
{
|
{
|
||||||
Vec3f barycentric_cords = barycentric(pt, p1, p2, p3);
|
Vec3f barycentric_cords = barycentric(pt, p1, p2, p3);
|
||||||
return std::all_of(begin(barycentric_cords), end(barycentric_cords), [](float cord) { return 0.f <= cord && cord <= 1.0; });
|
return std::all_of(begin(barycentric_cords), end(barycentric_cords), [](float cord) { return 0.f <= cord && cord <= 1.0; });
|
||||||
@@ -2211,8 +2211,7 @@ std::vector<EnforcerBlockerType> TriangleSelector::extract_used_facet_states(con
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool segments_intersect_proj(
|
static bool segments_intersect_proj(const Vec3f& p1, const Vec3f& p2, const Vec3f& p3, const Vec3f& p4, const std::function<std::pair<float, float>(const Vec3f&)>& proj)
|
||||||
const Vec3f& p1, const Vec3f& p2, const Vec3f& p3, const Vec3f& p4, const std::function<std::pair<float, float>(const Vec3f&)>& proj)
|
|
||||||
{
|
{
|
||||||
auto cross2d = [](float ax, float ay, float bx, float by) -> float { return ax * by - ay * bx; };
|
auto cross2d = [](float ax, float ay, float bx, float by) -> float { return ax * by - ay * bx; };
|
||||||
auto [u1, v1] = proj(p1);
|
auto [u1, v1] = proj(p1);
|
||||||
@@ -2332,13 +2331,22 @@ public:
|
|||||||
|
|
||||||
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);
|
const Vec3f& n = face_normals[facet_idx];
|
||||||
|
|
||||||
|
return check_normal(n, this->dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool check_normal(const Vec3f& facet_norm, const Vec3f& camera_dir)
|
||||||
|
{
|
||||||
|
const float a = -(facet_norm.dot(camera_dir));
|
||||||
|
return std::clamp(a, 0.f, 1.f) >= facet_angle_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::array<const Vec3f, 3> vertices_;
|
const std::array<const Vec3f, 3> vertices_;
|
||||||
const float tolerance_ = EPSILON;
|
const float tolerance_ = EPSILON;
|
||||||
const float tolerance_sqr_ = tolerance_ * tolerance_;
|
const float tolerance_sqr_ = tolerance_ * tolerance_;
|
||||||
|
static const double facet_angle_limit;
|
||||||
|
|
||||||
static float point_to_line_dist(const Vec3f& p, const Vec3f& a, const Vec3f& b)
|
static float point_to_line_dist(const Vec3f& p, const Vec3f& a, const Vec3f& b)
|
||||||
{
|
{
|
||||||
@@ -2346,6 +2354,8 @@ private:
|
|||||||
return line.distance(p);
|
return line.distance(p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const double TriangleCursor::facet_angle_limit = cos(Geometry::deg2rad(5));
|
||||||
|
|
||||||
|
|
||||||
// Remap painting data from source mesh to target mesh using spatial mapping.
|
// Remap painting data from source mesh to target mesh using spatial mapping.
|
||||||
TriangleSelector::TriangleSplittingData TriangleSelector::remap_painting(
|
TriangleSelector::TriangleSplittingData TriangleSelector::remap_painting(
|
||||||
@@ -2423,14 +2433,6 @@ TriangleSelector::TriangleSplittingData TriangleSelector::remap_painting(
|
|||||||
// 4. For each painted face, we find the nearest target face, and apply the TriangleCursor to paint it
|
// 4. For each painted face, we find the nearest target face, and apply the TriangleCursor to paint it
|
||||||
TriangleMesh target_mesh(target_its);
|
TriangleMesh target_mesh(target_its);
|
||||||
TriangleSelector target_selector(target_mesh);
|
TriangleSelector target_selector(target_mesh);
|
||||||
const auto facet_angle_limit = cos(Geometry::deg2rad(5));
|
|
||||||
auto check_normal = [&source_selector, &target_selector, facet_angle_limit](int src_idx, int dst_idx) -> bool {
|
|
||||||
const Vec3f& norm_a = source_selector.m_face_normals[src_idx];
|
|
||||||
const Vec3f& norm_b = target_selector.m_face_normals[dst_idx];
|
|
||||||
const float a = norm_a.dot(norm_b);
|
|
||||||
|
|
||||||
return std::clamp(a, 0.f, 1.f) >= facet_angle_limit;
|
|
||||||
};
|
|
||||||
for (auto tri_ref : painted_triangles) {
|
for (auto tri_ref : painted_triangles) {
|
||||||
const Triangle& tri = tri_ref.get();
|
const Triangle& tri = tri_ref.get();
|
||||||
const Vec3f& pv0 = source_selector.m_vertices[tri.verts_idxs[0]].v;
|
const Vec3f& pv0 = source_selector.m_vertices[tri.verts_idxs[0]].v;
|
||||||
@@ -2449,12 +2451,15 @@ TriangleSelector::TriangleSplittingData TriangleSelector::remap_painting(
|
|||||||
if (face_idx >= target_its.indices.size())
|
if (face_idx >= target_its.indices.size())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
const Vec3f& norm_a = source_selector.m_face_normals[tri.source_triangle];
|
||||||
|
const Vec3f& norm_b = target_selector.m_face_normals[face_idx];
|
||||||
|
|
||||||
const Vec3i32& face = target_its.indices[face_idx];
|
const Vec3i32& face = target_its.indices[face_idx];
|
||||||
const Vec3f& ta = target_its.vertices[face(0)];
|
const Vec3f& ta = target_its.vertices[face(0)];
|
||||||
const Vec3f& tb = target_its.vertices[face(1)];
|
const Vec3f& tb = target_its.vertices[face(1)];
|
||||||
const Vec3f& tc = target_its.vertices[face(2)];
|
const Vec3f& tc = target_its.vertices[face(2)];
|
||||||
|
|
||||||
if (check_normal(tri.source_triangle, face_idx) && check_overlap(pv0, pv1, pv2, ta, tb, tc)) {
|
if (TriangleCursor::check_normal(norm_b, -norm_a) && check_overlap(pv0, pv1, pv2, ta, tb, tc)) {
|
||||||
// Paint this face
|
// Paint this face
|
||||||
target_selector.select_patch(face_idx, TriangleCursor::build_cursor(source_selector, tri), tri.get_state(),
|
target_selector.select_patch(face_idx, TriangleCursor::build_cursor(source_selector, tri), tri.get_state(),
|
||||||
Transform3d::Identity(), true);
|
Transform3d::Identity(), true);
|
||||||
|
|||||||
Reference in New Issue
Block a user