Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorenricoturri1966 <enricoturri@seznam.cz>2021-01-18 11:59:05 +0300
committerenricoturri1966 <enricoturri@seznam.cz>2021-04-12 15:09:12 +0300
commit7bce69f9c76da9ae90d0b737f216fe59174b3439 (patch)
tree123f00757c76d7c06f6e03b5ebca1b660e53f060
parent6e554626a64f5e0d285f1ad0589b902169dde26d (diff)
ENABLE_SPLITTED_VERTEX_BUFFER - fixed cracks in toolpaths when splitting vertex and index buffers
-rw-r--r--src/libslic3r/Technologies.hpp1
-rw-r--r--src/slic3r/GUI/GCodeViewer.cpp221
2 files changed, 219 insertions, 3 deletions
diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index 1ebfd7b3a..f61de0dc6 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -114,6 +114,7 @@
#define ENABLE_2_3_1 1
#define ENABLE_SPLITTED_VERTEX_BUFFER (1 && ENABLE_2_3_1)
+#define ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING (1 && ENABLE_SPLITTED_VERTEX_BUFFER)
#endif // _prusaslicer_technologies_h_
diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index b3794175e..510aa2529 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -1219,6 +1219,65 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
};
// format data into the buffers to be rendered as solid
+#if ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING
+ auto add_vertices_as_solid = [](const GCodeProcessor::MoveVertex& prev, const GCodeProcessor::MoveVertex& curr, TBuffer& buffer, unsigned int vbuffer_id, VertexBuffer& vertices, size_t move_id) {
+ auto store_vertex = [](VertexBuffer& vertices, const Vec3f& position, const Vec3f& normal) {
+ // append position
+ vertices.push_back(position[0]);
+ vertices.push_back(position[1]);
+ vertices.push_back(position[2]);
+ // append normal
+ vertices.push_back(normal[0]);
+ vertices.push_back(normal[1]);
+ vertices.push_back(normal[2]);
+ };
+
+ if (prev.type != curr.type || !buffer.paths.back().matches(curr)) {
+ buffer.add_path(curr, vbuffer_id, vertices.size(), move_id - 1);
+ buffer.paths.back().sub_paths.back().first.position = prev.position;
+ }
+
+ Path& last_path = buffer.paths.back();
+
+ Vec3f dir = (curr.position - prev.position).normalized();
+ Vec3f right = Vec3f(dir[1], -dir[0], 0.0f).normalized();
+ Vec3f left = -right;
+ Vec3f up = right.cross(dir);
+ Vec3f down = -up;
+ float half_width = 0.5f * last_path.width;
+ float half_height = 0.5f * last_path.height;
+ Vec3f prev_pos = prev.position - half_height * up;
+ Vec3f curr_pos = curr.position - half_height * up;
+ Vec3f d_up = half_height * up;
+ Vec3f d_down = -half_height * up;
+ Vec3f d_right = half_width * right;
+ Vec3f d_left = -half_width * right;
+
+ // vertices 1st endpoint
+ if (last_path.vertices_count() == 1 || vertices.empty()) {
+ // 1st segment or restart into a new vertex buffer
+ // ===============================================
+ store_vertex(vertices, prev_pos + d_up, up);
+ store_vertex(vertices, prev_pos + d_right, right);
+ store_vertex(vertices, prev_pos + d_down, down);
+ store_vertex(vertices, prev_pos + d_left, left);
+ }
+ else {
+ // any other segment
+ // =================
+ store_vertex(vertices, prev_pos + d_right, right);
+ store_vertex(vertices, prev_pos + d_left, left);
+ }
+
+ // vertices 2nd endpoint
+ store_vertex(vertices, curr_pos + d_up, up);
+ store_vertex(vertices, curr_pos + d_right, right);
+ store_vertex(vertices, curr_pos + d_down, down);
+ store_vertex(vertices, curr_pos + d_left, left);
+
+ last_path.sub_paths.back().last = { vbuffer_id, vertices.size(), move_id, curr.position };
+ };
+#else
auto add_vertices_as_solid = [](const GCodeProcessor::MoveVertex& prev, const GCodeProcessor::MoveVertex& curr, TBuffer& buffer, VertexBuffer& vertices, size_t move_id) {
static Vec3f prev_dir;
static Vec3f prev_up;
@@ -1293,7 +1352,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
}
Vec3f displacement_vec = displacement * prev_dir;
- bool can_displace = displacement > 0.0f && displacement < prev_length&& displacement < length;
+ bool can_displace = displacement > 0.0f && displacement < prev_length && displacement < length;
size_t prev_right_id = (starting_vertices_size - 3) * buffer.vertices.vertex_size_floats();
size_t prev_left_id = (starting_vertices_size - 1) * buffer.vertices.vertex_size_floats();
@@ -1366,6 +1425,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
prev_up = up;
prev_length = length;
};
+#endif // ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING
auto add_indices_as_solid = [](const GCodeProcessor::MoveVertex& prev, const GCodeProcessor::MoveVertex& curr, TBuffer& buffer,
size_t& vbuffer_size, unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) {
static Vec3f prev_dir;
@@ -1573,8 +1633,19 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
// if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer
// add another vertex buffer
+#if ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING
+ if (v_multibuffer.back().size() * sizeof(float) > VBUFFER_THRESHOLD_BYTES - t_buffer.max_vertices_per_segment_size_bytes()) {
+ v_multibuffer.push_back(VertexBuffer());
+ if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) {
+ Path& last_path = t_buffer.paths.back();
+ if (prev.type == curr.type && last_path.matches(curr))
+ last_path.add_sub_path(prev, static_cast<unsigned int>(v_multibuffer.size()) - 1, 0, i - 1);
+ }
+ }
+#else
if (v_multibuffer.back().size() * sizeof(float) > VBUFFER_THRESHOLD_BYTES - t_buffer.max_vertices_per_segment_size_bytes())
v_multibuffer.push_back(VertexBuffer());
+#endif // ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING
VertexBuffer& v_buffer = v_multibuffer.back();
@@ -1582,7 +1653,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
{
case TBuffer::ERenderPrimitiveType::Point: { add_vertices_as_point(curr, v_buffer); break; }
case TBuffer::ERenderPrimitiveType::Line: { add_vertices_as_line(prev, curr, v_buffer); break; }
+#if ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING
+ case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, static_cast<unsigned int>(v_multibuffer.size()) - 1, v_buffer, i); break; }
+#else
case TBuffer::ERenderPrimitiveType::Triangle: { add_vertices_as_solid(prev, curr, t_buffer, v_buffer, i); break; }
+#endif // ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING
}
// collect options zs for later use
@@ -1593,6 +1668,138 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
}
}
+#if ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING
+ // smooth toolpaths corners for the given TBuffer using triangles
+ auto smooth_triangle_toolpaths_corners = [&gcode_result](const TBuffer& t_buffer, MultiVertexBuffer& v_multibuffer) {
+ auto extract_position_at = [](const VertexBuffer& vertices, size_t offset) {
+ return Vec3f(vertices[offset + 0], vertices[offset + 1], vertices[offset + 2]);
+ };
+ auto update_position_at = [](VertexBuffer& vertices, size_t offset, const Vec3f& position) {
+ vertices[offset + 0] = position[0];
+ vertices[offset + 1] = position[1];
+ vertices[offset + 2] = position[2];
+ };
+
+ size_t vertex_size_floats = t_buffer.vertices.vertex_size_floats();
+ for (const Path& path : t_buffer.paths) {
+ // the two segments of the path sharing the current vertex may belong
+ // to two different vertex buffers
+ size_t prev_sub_path_id = 0;
+ size_t next_sub_path_id = 0;
+ size_t path_vertices_count = path.vertices_count();
+ float half_width = 0.5f * path.width;
+ for (size_t j = 1; j < path_vertices_count - 1; ++j) {
+ size_t curr_s_id = path.sub_paths.front().first.s_id + j;
+ const Vec3f& prev = gcode_result.moves[curr_s_id - 1].position;
+ const Vec3f& curr = gcode_result.moves[curr_s_id].position;
+ const Vec3f& next = gcode_result.moves[curr_s_id + 1].position;
+
+ // select the subpaths which contains the previous/next segments
+ if (!path.sub_paths[prev_sub_path_id].contains(curr_s_id))
+ ++prev_sub_path_id;
+ if (!path.sub_paths[next_sub_path_id].contains(curr_s_id + 1))
+ ++next_sub_path_id;
+ const Path::Sub_Path& prev_sub_path = path.sub_paths[prev_sub_path_id];
+ const Path::Sub_Path& next_sub_path = path.sub_paths[next_sub_path_id];
+
+ Vec3f prev_dir = (curr - prev).normalized();
+ Vec3f prev_right = Vec3f(prev_dir[1], -prev_dir[0], 0.0f).normalized();
+ Vec3f prev_up = prev_right.cross(prev_dir);
+
+ Vec3f next_dir = (next - curr).normalized();
+ Vec3f next_right = Vec3f(next_dir[1], -next_dir[0], 0.0f).normalized();
+ Vec3f next_up = next_right.cross(next_dir);
+
+ bool is_right_turn = prev_up.dot(prev_dir.cross(next_dir)) <= 0.0f;
+ float cos_dir = prev_dir.dot(next_dir);
+ // whether the angle between adjacent segments is greater than 45 degrees
+ bool is_sharp = cos_dir < 0.7071068f;
+
+ float displacement = 0.0f;
+ if (cos_dir > -0.9998477f) {
+ // if the angle between adjacent segments is smaller than 179 degrees
+ Vec3f med_dir = (prev_dir + next_dir).normalized();
+ displacement = half_width * ::tan(::acos(std::clamp(next_dir.dot(med_dir), -1.0f, 1.0f)));
+ }
+
+ float sq_prev_length = (curr - prev).squaredNorm();
+ float sq_next_length = (next - curr).squaredNorm();
+ float sq_displacement = sqr(displacement);
+ bool can_displace = displacement > 0.0f && sq_displacement < sq_prev_length&& sq_displacement < sq_next_length;
+
+ if (can_displace) {
+ Vec3f displacement_vec = displacement * prev_dir;
+ // matches inner corner vertices
+ if (is_right_turn) {
+ // offset into the vertex buffer of the right vertex of the previous segment
+ size_t prev_right_offset = prev_sub_path.last.i_id - ((prev_sub_path.last.s_id - curr_s_id) * 6 + 3) * vertex_size_floats;
+ // new position of the right vertices
+ Vec3f shared_right = extract_position_at(v_multibuffer[prev_sub_path.first.b_id], prev_right_offset) - displacement_vec;
+ // update previous segment
+ update_position_at(v_multibuffer[prev_sub_path.first.b_id], prev_right_offset, shared_right);
+ // offset into the vertex buffer of the right vertex of the next segment
+ size_t r_offset = (curr_s_id == next_sub_path.first.i_id) ? 1 : 0;
+ size_t next_right_offset = next_sub_path.last.i_id - ((next_sub_path.last.s_id - curr_s_id) * 6 - r_offset) * vertex_size_floats;
+ // update next segment
+ update_position_at(v_multibuffer[next_sub_path.first.b_id], next_right_offset, shared_right);
+ }
+ else {
+ // offset into the vertex buffer of the left vertex of the previous segment
+ size_t prev_left_offset = prev_sub_path.last.i_id - ((prev_sub_path.last.s_id - curr_s_id) * 6 + 1) * vertex_size_floats;
+ // new position of the left vertices
+ Vec3f shared_left = extract_position_at(v_multibuffer[prev_sub_path.first.b_id], prev_left_offset) - displacement_vec;
+ // update previous segment
+ update_position_at(v_multibuffer[prev_sub_path.first.b_id], prev_left_offset, shared_left);
+ // offset into the vertex buffer of the left vertex of the next segment
+ size_t l_offset = (curr_s_id == next_sub_path.first.i_id) ? 3 : 1;
+ size_t next_left_offset = next_sub_path.last.i_id - ((next_sub_path.last.s_id - curr_s_id) * 6 - l_offset) * vertex_size_floats;
+ // update next segment
+ update_position_at(v_multibuffer[next_sub_path.first.b_id], next_left_offset, shared_left);
+ }
+
+ if (!is_sharp) {
+ // matches outer corner vertices
+ if (is_right_turn) {
+ // offset into the vertex buffer of the left vertex of the previous segment
+ size_t prev_left_offset = prev_sub_path.last.i_id - ((prev_sub_path.last.s_id - curr_s_id) * 6 + 1) * vertex_size_floats;
+ // new position of the left vertices
+ Vec3f shared_left = extract_position_at(v_multibuffer[prev_sub_path.first.b_id], prev_left_offset) + displacement_vec;
+ // update previous segment
+ update_position_at(v_multibuffer[prev_sub_path.first.b_id], prev_left_offset, shared_left);
+ // offset into the vertex buffer of the left vertex of the next segment
+ size_t l_offset = (curr_s_id == next_sub_path.first.i_id) ? 3 : 1;
+ size_t next_left_offset = next_sub_path.last.i_id - ((next_sub_path.last.s_id - curr_s_id) * 6 - l_offset) * vertex_size_floats;
+ // update next segment
+ update_position_at(v_multibuffer[next_sub_path.first.b_id], next_left_offset, shared_left);
+ }
+ else {
+ // offset into the vertex buffer of the right vertex of the previous segment
+ size_t prev_right_offset = prev_sub_path.last.i_id - ((prev_sub_path.last.s_id - curr_s_id) * 6 + 3) * vertex_size_floats;
+ // new position of the right vertices
+ Vec3f shared_right = extract_position_at(v_multibuffer[prev_sub_path.first.b_id], prev_right_offset) + displacement_vec;
+ // update previous segment
+ update_position_at(v_multibuffer[prev_sub_path.first.b_id], prev_right_offset, shared_right);
+ // offset into the vertex buffer of the right vertex of the next segment
+ size_t r_offset = (curr_s_id == next_sub_path.first.i_id) ? 1 : 0;
+ size_t next_right_offset = next_sub_path.last.i_id - ((next_sub_path.last.s_id - curr_s_id) * 6 - r_offset) * vertex_size_floats;
+ // update next segment
+ update_position_at(v_multibuffer[next_sub_path.first.b_id], next_right_offset, shared_right);
+ }
+ }
+ }
+ }
+ }
+ };
+
+ // smooth toolpaths corners for TBuffers using triangles
+ for (size_t i = 0; i < m_buffers.size(); ++i) {
+ const TBuffer& t_buffer = m_buffers[i];
+ if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) {
+ smooth_triangle_toolpaths_corners(t_buffer, vertices[i]);
+ }
+ }
+#endif // ENABLE_TOOLPATHS_ALTERNATE_SMOOTHING
+
for (MultiVertexBuffer& v_multibuffer : vertices) {
for (VertexBuffer& v_buffer : v_multibuffer) {
v_buffer.shrink_to_fit();
@@ -1693,7 +1900,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]);
if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) {
Path& last_path = t_buffer.paths.back();
- --last_path.sub_paths.back().last.s_id;
last_path.add_sub_path(prev, static_cast<unsigned int>(i_multibuffer.size()) - 1, 0, i - 1);
}
}
@@ -1709,7 +1915,6 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) {
Path& last_path = t_buffer.paths.back();
- --last_path.sub_paths.back().last.s_id;
last_path.add_sub_path(prev, static_cast<unsigned int>(i_multibuffer.size()) - 1, 0, i - 1);
}
}
@@ -2819,6 +3024,16 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
delta_1st *= buffer->indices_per_segment();
render_path->offsets.push_back(static_cast<size_t>((sub_path.first.i_id + delta_1st) * sizeof(unsigned int)));
+
+#if 0
+ // check sizes and offsets against index buffer size on gpu
+ GLint buffer_size;
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer->indices[render_path->index_buffer_id].ibo));
+ glsafe(::glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &buffer_size));
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+ if (render_path->offsets.back() + render_path->sizes.back() * sizeof(unsigned int) > buffer_size)
+ BOOST_LOG_TRIVIAL(error) << "GCodeViewer::refresh_render_paths: Invalid render path data";
+#endif
}
// set sequential data to their final value