From 4ba7dfb6ddb6aa92456088184862a8ad1e2c7222 Mon Sep 17 00:00:00 2001 From: Enrico Turri Date: Mon, 8 Jul 2019 15:30:59 +0200 Subject: [PATCH] Refactoring of functions thick_lines_to_indexed_vertex_array() to reduce the amount of produced vertices while reducing visual artifacts in gcode toolpaths due to averaged normals --- src/slic3r/GUI/3DScene.cpp | 27 ++++++++++++++++++++++----- src/slic3r/GUI/3DScene.hpp | 2 -- src/slic3r/GUI/GLCanvas3D.cpp | 6 ------ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index fe0cd9ffb..c49c7c9ca 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -849,6 +849,7 @@ static void thick_lines_to_indexed_vertex_array( int idx_initial[4] = { -1, -1, -1, -1 }; double width_initial = 0.; double bottom_z_initial = 0.0; + double len_prev = 0.0; // loop once more in case of closed loops size_t lines_end = closed ? (lines.size() + 1) : lines.size(); @@ -864,6 +865,7 @@ static void thick_lines_to_indexed_vertex_array( bool is_closing = closed && is_last; Vec2d v = unscale(line.vector()).normalized(); + double len = unscale(line.length()); Vec2d a = unscale(line.a); Vec2d b = unscale(line.b); @@ -927,7 +929,14 @@ static void thick_lines_to_indexed_vertex_array( // Continuing a previous segment. // Share left / right vertices if possible. double v_dot = v_prev.dot(v); - bool sharp = v_dot < 0.9999; // v_dot < 0.9999; // cos(1 degree) + // To reduce gpu memory usage, we try to reuse vertices + // To reduce the visual artifacts, due to averaged normals, we allow to reuse vertices only when any of two adjacent edges + // is longer than a fixed threshold. + // The following value is arbitrary, it comes from tests made on a bunch of models showing the visual artifacts + double len_threshold = 2.5; + + // Generate new vertices if the angle between adjacent edges is greater than 45 degrees or thresholds conditions are met + bool sharp = (v_dot < 0.707) || (len_prev > len_threshold) || (len > len_threshold); if (sharp) { if (!bottom_z_different) { @@ -1003,6 +1012,7 @@ static void thick_lines_to_indexed_vertex_array( bottom_z_prev = bottom_z; b1_prev = b1; v_prev = v; + len_prev = len; if (bottom_z_different && (closed || (!is_first && !is_last))) { @@ -1056,6 +1066,7 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, int idx_initial[4] = { -1, -1, -1, -1 }; int idx_prev[4] = { -1, -1, -1, -1 }; double z_prev = 0.0; + double len_prev = 0.0; Vec3d n_right_prev = Vec3d::Zero(); Vec3d n_top_prev = Vec3d::Zero(); Vec3d unit_v_prev = Vec3d::Zero(); @@ -1077,6 +1088,7 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, double width = widths[i]; Vec3d unit_v = unscale(line.vector()).normalized(); + double len = unscale(line.length()); Vec3d n_top = Vec3d::Zero(); Vec3d n_right = Vec3d::Zero(); @@ -1153,9 +1165,16 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, // Continuing a previous segment. // Share left / right vertices if possible. double v_dot = unit_v_prev.dot(unit_v); - bool is_sharp = v_dot < 0.9999; // v_dot < 0.9999; // cos(1 degree) bool is_right_turn = n_top_prev.dot(unit_v_prev.cross(unit_v)) > 0.0; + // To reduce gpu memory usage, we try to reuse vertices + // To reduce the visual artifacts, due to averaged normals, we allow to reuse vertices only when any of two adjacent edges + // is longer than a fixed threshold. + // The following value is arbitrary, it comes from tests made on a bunch of models showing the visual artifacts + double len_threshold = 2.5; + + // Generate new vertices if the angle between adjacent edges is greater than 45 degrees or thresholds conditions are met + bool is_sharp = (v_dot < 0.707) || (len_prev > len_threshold) || (len > len_threshold); if (is_sharp) { // Allocate new left / right points for the start of this segment as these points will receive their own normals to indicate a sharp turn. @@ -1234,6 +1253,7 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines, n_right_prev = n_right; n_top_prev = n_top; unit_v_prev = unit_v; + len_prev = len; if (!closed) { @@ -1495,9 +1515,6 @@ void GLModel::set_scale(const Vec3d& scale) void GLModel::reset() { -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -// m_volume.release_geometry(); -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ m_filename = ""; } diff --git a/src/slic3r/GUI/3DScene.hpp b/src/slic3r/GUI/3DScene.hpp index bb629a1d8..50821a6ca 100644 --- a/src/slic3r/GUI/3DScene.hpp +++ b/src/slic3r/GUI/3DScene.hpp @@ -74,9 +74,7 @@ public: quad_indices_VBO_id(0) {} -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ~GLIndexedVertexArray() { release_geometry(); } -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ GLIndexedVertexArray& operator=(const GLIndexedVertexArray &rhs) { diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 77c755538..d15d9aa4d 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -1356,9 +1356,6 @@ void GLCanvas3D::reset_volumes() if (!m_volumes.empty()) { m_selection.clear(); -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -// m_volumes.release_geometry(); -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ m_volumes.clear(); m_dirty = true; } @@ -1920,9 +1917,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re assert(volume_idx_wipe_tower_old == -1); volume_idx_wipe_tower_old = (int)volume_id; } -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ -// volume->release_geometry(); -//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ if (! m_reload_delayed) delete volume; } else {