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-02-05 13:53:39 +0300
committerenricoturri1966 <enricoturri@seznam.cz>2021-04-12 15:11:10 +0300
commit6a0e816d94a1dd71d1041742613bb0fd2d2dee71 (patch)
tree507739fccde6736d3af2c426670ea6803a9ff2b0
parent51dfccf1157c566b1cbb8891ecedefaa1e79269d (diff)
Fixed conflicts after cherry-picking 76a92e40befc9ce57d7436170786435041e56ab1
-rw-r--r--src/libslic3r/Technologies.hpp1
-rw-r--r--src/slic3r/GUI/GCodeViewer.cpp423
-rw-r--r--src/slic3r/GUI/GCodeViewer.hpp82
3 files changed, 440 insertions, 66 deletions
diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp
index d04496bbd..6f19485a0 100644
--- a/src/libslic3r/Technologies.hpp
+++ b/src/libslic3r/Technologies.hpp
@@ -114,6 +114,7 @@
#define ENABLE_2_3_1_ALPHA1 1
#define ENABLE_SPLITTED_VERTEX_BUFFER (1 && ENABLE_2_3_1_ALPHA1)
+#define ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS (1 && ENABLE_SPLITTED_VERTEX_BUFFER)
#endif // _prusaslicer_technologies_h_
diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp
index 8fac13733..e6c5f21de 100644
--- a/src/slic3r/GUI/GCodeViewer.cpp
+++ b/src/slic3r/GUI/GCodeViewer.cpp
@@ -240,6 +240,23 @@ GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at(float value) con
return ret;
}
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+GCodeViewer::SequentialRangeCap::~SequentialRangeCap() {
+ if (ibo > 0)
+ glsafe(::glDeleteBuffers(1, &ibo));
+}
+
+void GCodeViewer::SequentialRangeCap::reset() {
+ if (ibo > 0)
+ glsafe(::glDeleteBuffers(1, &ibo));
+
+ buffer = nullptr;
+ ibo = 0;
+ vbo = 0;
+ color = { 0.0f, 0.0f, 0.0f };
+}
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+
void GCodeViewer::SequentialView::Marker::init()
{
m_model.init_from(stilized_arrow(16, 2.0f, 4.0f, 1.0f, 8.0f));
@@ -574,7 +591,7 @@ void GCodeViewer::render() const
auto init_gl_data = [this]() {
// initializes opengl data of TBuffers
for (size_t i = 0; i < m_buffers.size(); ++i) {
- TBuffer& buffer = m_buffers[i];
+ TBuffer& buffer = const_cast<TBuffer&>(m_buffers[i]);
switch (buffer_type(i))
{
default: { break; }
@@ -600,17 +617,17 @@ void GCodeViewer::render() const
}
// initializes tool marker
- m_sequential_view.marker.init();
+ const_cast<SequentialView*>(&m_sequential_view)->marker.init();
// initializes point sizes
std::array<int, 2> point_sizes;
::glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, point_sizes.data());
- m_detected_point_sizes = { static_cast<float>(point_sizes[0]), static_cast<float>(point_sizes[1]) };
- m_gl_data_initialized = true;
+ *const_cast<std::array<float, 2>*>(&m_detected_point_sizes) = { static_cast<float>(point_sizes[0]), static_cast<float>(point_sizes[1]) };
+ *const_cast<bool*>(&m_gl_data_initialized) = true;
};
#if ENABLE_GCODE_VIEWER_STATISTICS
- m_statistics.reset_opengl();
+ const_cast<Statistics*>(&m_statistics)->reset_opengl();
#endif // ENABLE_GCODE_VIEWER_STATISTICS
// OpenGL data must be initialized after the glContext has been created.
@@ -623,9 +640,10 @@ void GCodeViewer::render() const
glsafe(::glEnable(GL_DEPTH_TEST));
render_toolpaths();
- if (m_sequential_view.current.last != m_sequential_view.endpoints.last) {
- m_sequential_view.marker.set_world_position(m_sequential_view.current_position);
- m_sequential_view.marker.render();
+ SequentialView* sequential_view = const_cast<SequentialView*>(&m_sequential_view);
+ if (sequential_view->current.last != sequential_view->endpoints.last) {
+ sequential_view->marker.set_world_position(sequential_view->current_position);
+ sequential_view->marker.render();
}
render_shells();
render_legend();
@@ -1279,8 +1297,13 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
last_path.sub_paths.back().last = { vbuffer_id, vertices.size(), move_id, curr.position };
};
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ auto add_indices_as_solid = [&](const GCodeProcessor::MoveVertex& prev, const GCodeProcessor::MoveVertex& curr, const GCodeProcessor::MoveVertex* next,
+ TBuffer& buffer, size_t& vbuffer_size, unsigned int ibuffer_id, IndexBuffer& indices, size_t move_id) {
+#else
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) {
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
static Vec3f prev_dir;
static Vec3f prev_up;
static float sq_prev_length;
@@ -1293,7 +1316,40 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
store_triangle(indices, id, id, id);
store_triangle(indices, id, id, id);
};
- auto store_main_triangles = [&](IndexBuffer& indices, size_t vbuffer_size, const std::array<int, 8>& v_offsets) {
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ auto convert_vertices_offset = [](size_t vbuffer_size, const std::array<int, 8>& v_offsets) {
+ std::array<IBufferType, 8> ret = {
+ static_cast<IBufferType>(static_cast<int>(vbuffer_size) + v_offsets[0]),
+ static_cast<IBufferType>(static_cast<int>(vbuffer_size) + v_offsets[1]),
+ static_cast<IBufferType>(static_cast<int>(vbuffer_size) + v_offsets[2]),
+ static_cast<IBufferType>(static_cast<int>(vbuffer_size) + v_offsets[3]),
+ static_cast<IBufferType>(static_cast<int>(vbuffer_size) + v_offsets[4]),
+ static_cast<IBufferType>(static_cast<int>(vbuffer_size) + v_offsets[5]),
+ static_cast<IBufferType>(static_cast<int>(vbuffer_size) + v_offsets[6]),
+ static_cast<IBufferType>(static_cast<int>(vbuffer_size) + v_offsets[7])
+ };
+ return ret;
+ };
+ auto append_starting_cap_triangles = [&](IndexBuffer& indices, const std::array<IBufferType, 8>& v_offsets) {
+ store_triangle(indices, v_offsets[0], v_offsets[2], v_offsets[1]);
+ store_triangle(indices, v_offsets[0], v_offsets[3], v_offsets[2]);
+ };
+ auto append_stem_triangles = [&](IndexBuffer& indices, const std::array<IBufferType, 8>& v_offsets) {
+ store_triangle(indices, v_offsets[0], v_offsets[1], v_offsets[4]);
+ store_triangle(indices, v_offsets[1], v_offsets[5], v_offsets[4]);
+ store_triangle(indices, v_offsets[1], v_offsets[2], v_offsets[5]);
+ store_triangle(indices, v_offsets[2], v_offsets[6], v_offsets[5]);
+ store_triangle(indices, v_offsets[2], v_offsets[3], v_offsets[6]);
+ store_triangle(indices, v_offsets[3], v_offsets[7], v_offsets[6]);
+ store_triangle(indices, v_offsets[3], v_offsets[0], v_offsets[7]);
+ store_triangle(indices, v_offsets[0], v_offsets[4], v_offsets[7]);
+ };
+ auto append_ending_cap_triangles = [&](IndexBuffer& indices, const std::array<IBufferType, 8>& v_offsets) {
+ store_triangle(indices, v_offsets[4], v_offsets[6], v_offsets[7]);
+ store_triangle(indices, v_offsets[4], v_offsets[5], v_offsets[6]);
+ };
+#else
+ auto append_stem_triangles = [&](IndexBuffer& indices, size_t vbuffer_size, const std::array<int, 8>& v_offsets) {
std::array<IBufferType, 8> v_ids;
for (size_t i = 0; i < v_ids.size(); ++i) {
v_ids[i] = static_cast<IBufferType>(static_cast<int>(vbuffer_size) + v_offsets[i]);
@@ -1317,6 +1373,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
store_triangle(indices, v_ids[4], v_ids[6], v_ids[7]);
store_triangle(indices, v_ids[4], v_ids[5], v_ids[6]);
};
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
if (prev.type != curr.type || !buffer.paths.back().matches(curr)) {
buffer.add_path(curr, ibuffer_id, indices.size(), move_id - 1);
@@ -1330,14 +1387,28 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
Vec3f up = right.cross(dir);
float sq_length = (curr.position - prev.position).squaredNorm();
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ const std::array<IBufferType, 8> first_seg_v_offsets = convert_vertices_offset(vbuffer_size, { 0, 1, 2, 3, 4, 5, 6, 7 });
+ const std::array<IBufferType, 8> non_first_seg_v_offsets = convert_vertices_offset(vbuffer_size, { -4, 0, -2, 1, 2, 3, 4, 5 });
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+
if (last_path.vertices_count() == 1 || vbuffer_size == 0) {
// 1st segment or restart into a new vertex buffer
// ===============================================
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ if (last_path.vertices_count() == 1)
+ // starting cap triangles
+ append_starting_cap_triangles(indices, first_seg_v_offsets);
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
// dummy triangles outer corner cap
append_dummy_cap(indices, vbuffer_size);
// stem triangles
- store_main_triangles(indices, vbuffer_size, { 0, 1, 2, 3, 4, 5, 6, 7 });
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ append_stem_triangles(indices, first_seg_v_offsets);
+#else
+ append_stem_triangles(indices, vbuffer_size, { 0, 1, 2, 3, 4, 5, 6, 7 });
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
vbuffer_size += 8;
}
@@ -1391,11 +1462,21 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
}
// stem triangles
- store_main_triangles(indices, vbuffer_size, { -4, 0, -2, 1, 2, 3, 4, 5 });
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ append_stem_triangles(indices, non_first_seg_v_offsets);
+#else
+ append_stem_triangles(indices, vbuffer_size, { -4, 0, -2, 1, 2, 3, 4, 5 });
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
vbuffer_size += 6;
}
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ if (next != nullptr && (curr.type != next->type || !last_path.matches(*next)))
+ // ending cap triangles
+ append_ending_cap_triangles(indices, non_first_seg_v_offsets);
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+
last_path.sub_paths.back().last = { ibuffer_id, indices.size() - 1, move_id, curr.position };
prev_dir = dir;
prev_up = up;
@@ -1635,6 +1716,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
}
};
+#if ENABLE_GCODE_VIEWER_STATISTICS
+ auto load_vertices_time = std::chrono::high_resolution_clock::now();
+ m_statistics.load_vertices = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();
+#endif // ENABLE_GCODE_VIEWER_STATISTICS
+
// smooth toolpaths corners for TBuffers using triangles
for (size_t i = 0; i < m_buffers.size(); ++i) {
const TBuffer& t_buffer = m_buffers[i];
@@ -1684,6 +1770,10 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
}
}
+#if ENABLE_GCODE_VIEWER_STATISTICS
+ auto smooth_vertices_time = std::chrono::high_resolution_clock::now();
+ m_statistics.smooth_vertices = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - load_vertices_time).count();
+#endif // ENABLE_GCODE_VIEWER_STATISTICS
log_memory_usage("Loaded G-code generated vertex buffers ", vertices, indices);
// dismiss vertices data, no more needed
@@ -1712,6 +1802,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
continue;
const GCodeProcessor::MoveVertex& prev = gcode_result.moves[i - 1];
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ const GCodeProcessor::MoveVertex* next = nullptr;
+ if (i < m_moves_count - 1)
+ next = &gcode_result.moves[i + 1];
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
++progress_count;
if (progress_dialog != nullptr && progress_count % progress_threshold == 0) {
@@ -1735,7 +1830,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
// if adding the indices for the current segment exceeds the threshold size of the current index buffer
// create another index buffer
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ if (i_multibuffer.back().size() * sizeof(IBufferType) >= IBUFFER_THRESHOLD_BYTES - t_buffer.max_indices_per_segment_size_bytes()) {
+#else
if (i_multibuffer.back().size() * sizeof(IBufferType) >= IBUFFER_THRESHOLD_BYTES - t_buffer.indices_per_segment_size_bytes()) {
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
i_multibuffer.push_back(IndexBuffer());
vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]);
if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) {
@@ -1774,7 +1873,11 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
break;
}
case TBuffer::ERenderPrimitiveType::Triangle: {
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ add_indices_as_solid(prev, curr, next, t_buffer, curr_vertex_buffer.second, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, i);
+#else
add_indices_as_solid(prev, curr, t_buffer, curr_vertex_buffer.second, static_cast<unsigned int>(i_multibuffer.size()) - 1, i_buffer, i);
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
break;
}
}
@@ -1826,14 +1929,28 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
auto update_segments_count = [&](EMoveType type, int64_t& count) {
unsigned int id = buffer_id(type);
const MultiIndexBuffer& buffers = indices[id];
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ int64_t indices_count = 0;
+ for (const IndexBuffer& buffer : buffers) {
+ indices_count += buffer.size();
+ }
+ const TBuffer& t_buffer = m_buffers[id];
+ if (t_buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle)
+ indices_count -= static_cast<int64_t>(12 * t_buffer.paths.size()); // remove the starting + ending caps = 4 triangles
+
+ count += indices_count / t_buffer.indices_per_segment();
+#else
for (const IndexBuffer& buffer : buffers) {
count += buffer.size() / m_buffers[id].indices_per_segment();
}
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
};
update_segments_count(EMoveType::Travel, m_statistics.travel_segments_count);
update_segments_count(EMoveType::Wipe, m_statistics.wipe_segments_count);
update_segments_count(EMoveType::Extrude, m_statistics.extrude_segments_count);
+
+ m_statistics.load_indices = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - smooth_vertices_time).count();
#endif // ENABLE_GCODE_VIEWER_STATISTICS
log_memory_usage("Loaded G-code generated indices buffers ", vertices, indices);
@@ -2669,14 +2786,6 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
};
auto is_travel_in_layers_range = [this](size_t path_id, size_t min_id, size_t max_id) {
- // auto is_in_z_range = [](const Path& path, double min_z, double max_z) {
- // auto in_z_range = [min_z, max_z](double z) {
- // return min_z - EPSILON < z && z < max_z + EPSILON;
- // };
- //
- // return in_z_range(path.sub_paths.front().first.position[2]) || in_z_range(path.sub_paths.back().last.position[2]);
- // };
-
const TBuffer& buffer = m_buffers[buffer_id(EMoveType::Travel)];
if (path_id >= buffer.paths.size())
return false;
@@ -2703,19 +2812,22 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
};
#if ENABLE_GCODE_VIEWER_STATISTICS
- m_statistics.render_paths_size = 0;
+ Statistics* statistics = const_cast<Statistics*>(&m_statistics);
+ statistics->render_paths_size = 0;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
bool top_layer_only = get_app_config()->get("seq_top_layer_only") == "1";
SequentialView::Endpoints global_endpoints = { m_moves_count , 0 };
SequentialView::Endpoints top_layer_endpoints = global_endpoints;
- if (top_layer_only || !keep_sequential_current_first) m_sequential_view.current.first = 0;
- if (!keep_sequential_current_last) m_sequential_view.current.last = m_moves_count;
+ SequentialView* sequential_view = const_cast<SequentialView*>(&m_sequential_view);
+ if (top_layer_only || !keep_sequential_current_first) sequential_view->current.first = 0;
+ if (!keep_sequential_current_last) sequential_view->current.last = m_moves_count;
// first pass: collect visible paths and update sequential view data
std::vector<std::tuple<TBuffer*, unsigned int, unsigned int, unsigned int>> paths;
- for (TBuffer& buffer : m_buffers) {
+ for (size_t b = 0; b < m_buffers.size(); ++b) {
+ TBuffer& buffer = const_cast<TBuffer&>(m_buffers[b]);
// reset render paths
buffer.render_paths.clear();
@@ -2758,8 +2870,8 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
}
// update current sequential position
- m_sequential_view.current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(m_sequential_view.current.first, global_endpoints.first, global_endpoints.last) : global_endpoints.first;
- m_sequential_view.current.last = keep_sequential_current_last ? std::clamp(m_sequential_view.current.last, global_endpoints.first, global_endpoints.last) : global_endpoints.last;
+ sequential_view->current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(sequential_view->current.first, global_endpoints.first, global_endpoints.last) : global_endpoints.first;
+ sequential_view->current.last = keep_sequential_current_last ? std::clamp(sequential_view->current.last, global_endpoints.first, global_endpoints.last) : global_endpoints.last;
// get the world position from gpu
bool found = false;
@@ -2776,7 +2888,13 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
offset = 2 * offset - 1;
else if (buffer.render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) {
unsigned int indices_count = buffer.indices_per_segment();
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ offset = indices_count * (offset - 1) + (indices_count - 2);
+ if (sub_path_id == 0)
+ offset += 6; // add 2 triangles for starting cap
+#else
offset = indices_count * (offset - 1) + (indices_count - 6);
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
}
}
offset += static_cast<unsigned int>(sub_path.first.i_id);
@@ -2790,7 +2908,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
// gets the position from the vertices buffer on gpu
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, i_buffer.vbo));
- glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(index * buffer.vertices.vertex_size_bytes()), static_cast<GLsizeiptr>(3 * sizeof(float)), static_cast<void*>(m_sequential_view.current_position.data())));
+ glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(index * buffer.vertices.vertex_size_bytes()), static_cast<GLsizeiptr>(3 * sizeof(float)), static_cast<void*>(sequential_view->current_position.data())));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
found = true;
@@ -2839,13 +2957,19 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
break;
}
case EMoveType::Wipe: { color = Wipe_Color; break; }
- default: { color = { 0.0f, 0.0f, 0.0f }; break; }
+ default: { color = { 0.0f, 0.0f, 0.0f }; break; }
}
RenderPath key{ color, static_cast<unsigned int>(ibuffer_id), path_id };
if (render_path == nullptr || !RenderPathPropertyEqual()(*render_path, key))
render_path = const_cast<RenderPath*>(&(*buffer->render_paths.emplace(key).first));
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ unsigned int delta_1st = 0;
+ if (sub_path.first.s_id < m_sequential_view.current.first && m_sequential_view.current.first <= sub_path.last.s_id)
+ delta_1st = static_cast<unsigned int>(m_sequential_view.current.first - sub_path.first.s_id);
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+
unsigned int size_in_indices = 0;
switch (buffer->render_primitive_type)
{
@@ -2860,14 +2984,42 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
break;
}
}
+
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ if (size_in_indices == 0)
+ continue;
+
+ if (buffer->render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) {
+ if (sub_path_id == 0 && delta_1st == 0)
+ size_in_indices += 6; // add 2 triangles for starting cap
+ if (sub_path_id == path.sub_paths.size() - 1 && path.sub_paths.back().last.s_id <= m_sequential_view.current.last)
+ size_in_indices += 6; // add 2 triangles for ending cap
+ if (delta_1st > 0)
+ size_in_indices -= 6; // remove 2 triangles for corner cap
+ }
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+
render_path->sizes.push_back(size_in_indices);
+#if !ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
unsigned int delta_1st = 0;
if (sub_path.first.s_id < m_sequential_view.current.first && m_sequential_view.current.first <= sub_path.last.s_id)
delta_1st = m_sequential_view.current.first - sub_path.first.s_id;
+#endif // !ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ if (buffer->render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle) {
+ delta_1st *= buffer->indices_per_segment();
+ if (delta_1st > 0) {
+ delta_1st += 6; // skip 2 triangles for corner cap
+ if (sub_path_id == 0)
+ delta_1st += 6; // skip 2 triangles for starting cap
+ }
+ }
+#else
if (buffer->render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle)
delta_1st *= buffer->indices_per_segment();
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
render_path->offsets.push_back(static_cast<size_t>((sub_path.first.i_id + delta_1st) * sizeof(IBufferType)));
@@ -2883,20 +3035,132 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
}
// set sequential data to their final value
- m_sequential_view.endpoints = top_layer_only ? top_layer_endpoints : global_endpoints;
- m_sequential_view.current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(m_sequential_view.current.first, m_sequential_view.endpoints.first, m_sequential_view.endpoints.last) : m_sequential_view.endpoints.first;
+ sequential_view->endpoints = top_layer_only ? top_layer_endpoints : global_endpoints;
+ sequential_view->current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(sequential_view->current.first, sequential_view->endpoints.first, sequential_view->endpoints.last) : sequential_view->endpoints.first;
+
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ // updates sequential range caps
+ std::array<SequentialRangeCap, 2>* sequential_range_caps = const_cast<std::array<SequentialRangeCap, 2>*>(&m_sequential_range_caps);
+ (*sequential_range_caps)[0].reset();
+ (*sequential_range_caps)[1].reset();
+
+ if (m_sequential_view.current.first != m_sequential_view.current.last) {
+ for (const auto& [buffer, ibuffer_id, path_id, sub_path_id] : paths) {
+ if (buffer->render_primitive_type != TBuffer::ERenderPrimitiveType::Triangle)
+ continue;
+
+ const Path& path = buffer->paths[path_id];
+ const Path::Sub_Path& sub_path = path.sub_paths[sub_path_id];
+ if (m_sequential_view.current.last <= sub_path.first.s_id || sub_path.last.s_id <= m_sequential_view.current.first)
+ continue;
+
+ // update cap for first endpoint of current range
+ if (m_sequential_view.current.first > sub_path.first.s_id) {
+ SequentialRangeCap& cap = (*sequential_range_caps)[0];
+ const IBuffer& i_buffer = buffer->indices[ibuffer_id];
+ cap.buffer = buffer;
+ cap.vbo = i_buffer.vbo;
+
+ // calculate offset into the index buffer
+ unsigned int offset = sub_path.first.i_id;
+ offset += 6; // add 2 triangles for corner cap
+ offset += static_cast<unsigned int>(m_sequential_view.current.first - sub_path.first.s_id) * buffer->indices_per_segment();
+ if (sub_path_id == 0)
+ offset += 6; // add 2 triangles for starting cap
+
+ // extract indices from index buffer
+ std::array<IBufferType, 6> indices{ 0, 0, 0, 0, 0, 0 };
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo));
+ glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLintptr>((offset + 0) * sizeof(IBufferType)), static_cast<GLsizeiptr>(sizeof(IBufferType)), static_cast<void*>(&indices[0])));
+ glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLintptr>((offset + 7) * sizeof(IBufferType)), static_cast<GLsizeiptr>(sizeof(IBufferType)), static_cast<void*>(&indices[1])));
+ glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLintptr>((offset + 1) * sizeof(IBufferType)), static_cast<GLsizeiptr>(sizeof(IBufferType)), static_cast<void*>(&indices[2])));
+ glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLintptr>((offset + 13) * sizeof(IBufferType)), static_cast<GLsizeiptr>(sizeof(IBufferType)), static_cast<void*>(&indices[4])));
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+ indices[3] = indices[0];
+ indices[5] = indices[1];
+
+ // send indices to gpu
+ glsafe(::glGenBuffers(1, &cap.ibo));
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cap.ibo));
+ glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(IBufferType), indices.data(), GL_STATIC_DRAW));
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+
+ // extract color from render path
+ size_t offset_bytes = offset * sizeof(IBufferType);
+ for (const RenderPath& render_path : buffer->render_paths) {
+ if (render_path.index_buffer_id == ibuffer_id) {
+ for (size_t j = 0; j < render_path.offsets.size(); ++j) {
+ if (render_path.contains(offset_bytes)) {
+ cap.color = render_path.color;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // update cap for last endpoint of current range
+ if (m_sequential_view.current.last < sub_path.last.s_id) {
+ SequentialRangeCap& cap = (*sequential_range_caps)[1];
+ const IBuffer& i_buffer = buffer->indices[ibuffer_id];
+ cap.buffer = buffer;
+ cap.vbo = i_buffer.vbo;
+
+ // calculate offset into the index buffer
+ unsigned int offset = sub_path.first.i_id;
+ offset += 6; // add 2 triangles for corner cap
+ offset += static_cast<unsigned int>(m_sequential_view.current.last - 1 - sub_path.first.s_id) * buffer->indices_per_segment();
+ if (sub_path_id == 0)
+ offset += 6; // add 2 triangles for starting cap
+
+ // extract indices from index buffer
+ std::array<IBufferType, 6> indices{ 0, 0, 0, 0, 0, 0 };
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, i_buffer.ibo));
+ glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLintptr>((offset + 2) * sizeof(IBufferType)), static_cast<GLsizeiptr>(sizeof(IBufferType)), static_cast<void*>(&indices[0])));
+ glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLintptr>((offset + 4) * sizeof(IBufferType)), static_cast<GLsizeiptr>(sizeof(IBufferType)), static_cast<void*>(&indices[1])));
+ glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLintptr>((offset + 10) * sizeof(IBufferType)), static_cast<GLsizeiptr>(sizeof(IBufferType)), static_cast<void*>(&indices[2])));
+ glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast<GLintptr>((offset + 16) * sizeof(IBufferType)), static_cast<GLsizeiptr>(sizeof(IBufferType)), static_cast<void*>(&indices[5])));
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+ indices[3] = indices[0];
+ indices[4] = indices[2];
+
+ // send indices to gpu
+ glsafe(::glGenBuffers(1, &cap.ibo));
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cap.ibo));
+ glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(IBufferType), indices.data(), GL_STATIC_DRAW));
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+
+ // extract color from render path
+ size_t offset_bytes = offset * sizeof(IBufferType);
+ for (const RenderPath& render_path : buffer->render_paths) {
+ if (render_path.index_buffer_id == ibuffer_id) {
+ for (size_t j = 0; j < render_path.offsets.size(); ++j) {
+ if (render_path.contains(offset_bytes)) {
+ cap.color = render_path.color;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if ((*sequential_range_caps)[0].is_renderable() && (*sequential_range_caps)[1].is_renderable())
+ break;
+ }
+ }
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
wxGetApp().plater()->enable_preview_moves_slider(!paths.empty());
#if ENABLE_GCODE_VIEWER_STATISTICS
for (const TBuffer& buffer : m_buffers) {
- m_statistics.render_paths_size += SLIC3R_STDUNORDEREDSET_MEMSIZE(buffer.render_paths, RenderPath);
+ statistics->render_paths_size += SLIC3R_STDUNORDEREDSET_MEMSIZE(buffer.render_paths, RenderPath);
for (const RenderPath& path : buffer.render_paths) {
- m_statistics.render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.sizes, unsigned int);
- m_statistics.render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t);
+ statistics->render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.sizes, unsigned int);
+ statistics->render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t);
}
}
- m_statistics.refresh_paths_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();
+ statistics->refresh_paths_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();
#endif // ENABLE_GCODE_VIEWER_STATISTICS
}
#else
@@ -2984,19 +3248,22 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
};
#if ENABLE_GCODE_VIEWER_STATISTICS
- m_statistics.render_paths_size = 0;
+ Statistics* statistics = const_cast<Statistics*>(&m_statistics);
+ statistics->render_paths_size = 0;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
bool top_layer_only = get_app_config()->get("seq_top_layer_only") == "1";
SequentialView::Endpoints global_endpoints = { m_moves_count , 0 };
SequentialView::Endpoints top_layer_endpoints = global_endpoints;
- if (top_layer_only || !keep_sequential_current_first) m_sequential_view.current.first = 0;
- if (!keep_sequential_current_last) m_sequential_view.current.last = m_moves_count;
+ SequentialView* sequential_view = const_cast<SequentialView*>(&m_sequential_view);
+ if (top_layer_only || !keep_sequential_current_first) sequential_view->current.first = 0;
+ if (!keep_sequential_current_last) sequential_view->current.last = m_moves_count;
// first pass: collect visible paths and update sequential view data
std::vector<std::tuple<TBuffer*, unsigned int, unsigned int>> paths;
- for (TBuffer& buffer : m_buffers) {
+ for (size_t b = 0; b < m_buffers.size(); ++b) {
+ TBuffer& buffer = const_cast<TBuffer&>(m_buffers[b]);
// reset render paths
buffer.render_paths.clear();
@@ -3037,8 +3304,8 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
}
// update current sequential position
- m_sequential_view.current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(m_sequential_view.current.first, global_endpoints.first, global_endpoints.last) : global_endpoints.first;
- m_sequential_view.current.last = keep_sequential_current_last ? std::clamp(m_sequential_view.current.last, global_endpoints.first, global_endpoints.last) : global_endpoints.last;
+ sequential_view->current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(sequential_view->current.first, global_endpoints.first, global_endpoints.last) : global_endpoints.first;
+ sequential_view->current.last = keep_sequential_current_last ? std::clamp(sequential_view->current.last, global_endpoints.first, global_endpoints.last) : global_endpoints.last;
// get the world position from gpu
bool found = false;
@@ -3065,7 +3332,7 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
// gets the position from the vertices buffer on gpu
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.vertices.id));
- glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(index * buffer.vertices.vertex_size_bytes()), static_cast<GLsizeiptr>(3 * sizeof(float)), static_cast<void*>(m_sequential_view.current_position.data())));
+ glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast<GLintptr>(index * buffer.vertices.vertex_size_bytes()), static_cast<GLsizeiptr>(3 * sizeof(float)), static_cast<void*>(sequential_view->current_position.data())));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
found = true;
break;
@@ -3131,20 +3398,20 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool
}
// set sequential data to their final value
- m_sequential_view.endpoints = top_layer_only ? top_layer_endpoints : global_endpoints;
- m_sequential_view.current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(m_sequential_view.current.first, m_sequential_view.endpoints.first, m_sequential_view.endpoints.last) : m_sequential_view.endpoints.first;
+ sequential_view->endpoints = top_layer_only ? top_layer_endpoints : global_endpoints;
+ sequential_view->current.first = !top_layer_only && keep_sequential_current_first ? std::clamp(sequential_view->current.first, sequential_view->endpoints.first, sequential_view->endpoints.last) : sequential_view->endpoints.first;
wxGetApp().plater()->enable_preview_moves_slider(!paths.empty());
#if ENABLE_GCODE_VIEWER_STATISTICS
for (const TBuffer& buffer : m_buffers) {
- m_statistics.render_paths_size += SLIC3R_STDUNORDEREDSET_MEMSIZE(buffer.render_paths, RenderPath);
+ statistics->render_paths_size += SLIC3R_STDUNORDEREDSET_MEMSIZE(buffer.render_paths, RenderPath);
for (const RenderPath& path : buffer.render_paths) {
- m_statistics.render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.sizes, unsigned int);
- m_statistics.render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t);
+ statistics->render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.sizes, unsigned int);
+ statistics->render_paths_size += SLIC3R_STDVEC_MEMSIZE(path.offsets, size_t);
}
}
- m_statistics.refresh_paths_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();
+ statistics->refresh_paths_time = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();
#endif // ENABLE_GCODE_VIEWER_STATISTICS
}
#endif // ENABLE_SPLITTED_VERTEX_BUFFER
@@ -3190,7 +3457,7 @@ void GCodeViewer::render_toolpaths() const
set_uniform_color(path.color, shader);
glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS
- ++m_statistics.gl_multi_points_calls_count;
+ ++const_cast<Statistics*>(&m_statistics)->gl_multi_points_calls_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
}
}
@@ -3206,7 +3473,7 @@ void GCodeViewer::render_toolpaths() const
set_uniform_color(path.color, shader);
glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS
- ++m_statistics.gl_multi_lines_calls_count;
+ ++const_cast<Statistics*>(&m_statistics)->gl_multi_lines_calls_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
}
}
@@ -3218,7 +3485,7 @@ void GCodeViewer::render_toolpaths() const
set_uniform_color(path.color, shader);
glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_SHORT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS
- ++m_statistics.gl_multi_triangles_calls_count;
+ ++const_cast<Statistics*>(&m_statistics)->gl_multi_triangles_calls_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
}
}
@@ -3284,6 +3551,47 @@ void GCodeViewer::render_toolpaths() const
shader->stop_using();
}
}
+
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ auto render_sequential_range_cap = [this, set_uniform_color](const SequentialRangeCap& cap) {
+ GLShaderProgram* shader = wxGetApp().get_shader(cap.buffer->shader.c_str());
+ if (shader != nullptr) {
+ shader->start_using();
+
+ glsafe(::glBindBuffer(GL_ARRAY_BUFFER, cap.vbo));
+ glsafe(::glVertexPointer(cap.buffer->vertices.position_size_floats(), GL_FLOAT, cap.buffer->vertices.vertex_size_bytes(), (const void*)cap.buffer->vertices.position_offset_size()));
+ glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
+ bool has_normals = cap.buffer->vertices.normal_size_floats() > 0;
+ if (has_normals) {
+ glsafe(::glNormalPointer(GL_FLOAT, cap.buffer->vertices.vertex_size_bytes(), (const void*)cap.buffer->vertices.normal_offset_size()));
+ glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
+ }
+
+ set_uniform_color(cap.color, *shader);
+
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cap.ibo));
+ glsafe(::glDrawElements(GL_TRIANGLES, (GLsizei)cap.indices_count(), GL_UNSIGNED_SHORT, nullptr));
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
+
+#if ENABLE_GCODE_VIEWER_STATISTICS
+ ++const_cast<Statistics*>(&m_statistics)->gl_triangles_calls_count;
+#endif // ENABLE_GCODE_VIEWER_STATISTICS
+
+ if (has_normals)
+ glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
+
+ glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
+ glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
+
+ shader->stop_using();
+ }
+ };
+
+ for (unsigned int i = 0; i < 2; ++i) {
+ if (m_sequential_range_caps[i].is_renderable())
+ render_sequential_range_cap(m_sequential_range_caps[i]);
+ }
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
}
#else
void GCodeViewer::render_toolpaths() const
@@ -3326,7 +3634,7 @@ void GCodeViewer::render_toolpaths() const
if (path.index_buffer_id == index_buffer_id) {
glsafe(::glMultiDrawElements(GL_POINTS, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_INT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS
- ++m_statistics.gl_multi_points_calls_count;
+ ++const_cast<Statistics*>(&m_statistics)->gl_multi_points_calls_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
}
}
@@ -3342,7 +3650,7 @@ void GCodeViewer::render_toolpaths() const
set_uniform_color(path.color, shader);
glsafe(::glMultiDrawElements(GL_LINES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_INT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS
- ++m_statistics.gl_multi_lines_calls_count;
+ ++const_cast<Statistics*>(&m_statistics)->gl_multi_lines_calls_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
}
}
@@ -3354,7 +3662,7 @@ void GCodeViewer::render_toolpaths() const
set_uniform_color(path.color, shader);
glsafe(::glMultiDrawElements(GL_TRIANGLES, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_INT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size()));
#if ENABLE_GCODE_VIEWER_STATISTICS
- ++m_statistics.gl_multi_triangles_calls_count;
+ ++const_cast<Statistics*>(&m_statistics)->gl_multi_triangles_calls_count;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
}
}
@@ -3719,7 +4027,8 @@ void GCodeViewer::render_legend() const
bool visible = is_visible(role);
append_item(EItemType::Rect, Extrusion_Role_Colors[static_cast<unsigned int>(role)], labels[i],
visible, times[i], percents[i], max_percent, offsets, [this, role, visible]() {
- m_extrusions.role_visibility_flags = visible ? m_extrusions.role_visibility_flags & ~(1 << role) : m_extrusions.role_visibility_flags | (1 << role);
+ Extrusions* extrusions = const_cast<Extrusions*>(&m_extrusions);
+ extrusions->role_visibility_flags = visible ? extrusions->role_visibility_flags & ~(1 << role) : extrusions->role_visibility_flags | (1 << role);
// update buffers' render paths
refresh_render_paths(false, false);
wxGetApp().plater()->update_preview_moves_slider();
@@ -4116,7 +4425,7 @@ void GCodeViewer::render_legend() const
}
if (show && m_time_statistics.modes[static_cast<size_t>(mode)].roles_times.size() > 0) {
if (imgui.button(label)) {
- m_time_estimate_mode = mode;
+ *const_cast<PrintEstimatedTimeStatistics::ETimeMode*>(&m_time_estimate_mode) = mode;
wxGetApp().plater()->get_current_canvas3D()->set_as_dirty();
wxGetApp().plater()->get_current_canvas3D()->request_extra_frame();
}
@@ -4196,6 +4505,9 @@ void GCodeViewer::render_statistics() const
ImGui::Separator();
add_time(std::string("Load:"), m_statistics.load_time);
+ add_time(std::string(" Load vertices:"), m_statistics.load_vertices);
+ add_time(std::string(" Smooth vertices:"), m_statistics.smooth_vertices);
+ add_time(std::string(" Load indices:"), m_statistics.load_indices);
add_time(std::string("Refresh:"), m_statistics.refresh_time);
add_time(std::string("Refresh paths:"), m_statistics.refresh_paths_time);
}
@@ -4204,6 +4516,9 @@ void GCodeViewer::render_statistics() const
add_counter(std::string("Multi GL_POINTS:"), m_statistics.gl_multi_points_calls_count);
add_counter(std::string("Multi GL_LINES:"), m_statistics.gl_multi_lines_calls_count);
add_counter(std::string("Multi GL_TRIANGLES:"), m_statistics.gl_multi_triangles_calls_count);
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ add_counter(std::string("GL_TRIANGLES:"), m_statistics.gl_triangles_calls_count);
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
}
if (ImGui::CollapsingHeader("CPU memory")) {
diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp
index a4663dc04..1d86cf55a 100644
--- a/src/slic3r/GUI/GCodeViewer.hpp
+++ b/src/slic3r/GUI/GCodeViewer.hpp
@@ -226,6 +226,15 @@ class GCodeViewer
unsigned int path_id;
std::vector<unsigned int> sizes;
std::vector<size_t> offsets; // use size_t because we need an unsigned int whose size matches pointer's size (used in the call glMultiDrawElements())
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ bool contains(size_t offset) const {
+ for (size_t i = 0; i < offsets.size(); ++i) {
+ if (offsets[i] <= offset && offset <= offsets[i] + static_cast<size_t>(sizes[i] * sizeof(IBufferType)))
+ return true;
+ }
+ return false;
+ }
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
};
struct RenderPathPropertyHash {
size_t operator() (const RenderPath &p) const {
@@ -297,29 +306,46 @@ class GCodeViewer
{
case ERenderPrimitiveType::Point: { return 1; }
case ERenderPrimitiveType::Line: { return 2; }
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ case ERenderPrimitiveType::Triangle: { return 30; } // 3 indices x 10 triangles
+#else
case ERenderPrimitiveType::Triangle: { return 42; } // 3 indices x 14 triangles
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
default: { return 0; }
}
}
#if ENABLE_SPLITTED_VERTEX_BUFFER
size_t indices_per_segment_size_bytes() const { return static_cast<size_t>(indices_per_segment() * sizeof(IBufferType)); }
#endif // ENABLE_SPLITTED_VERTEX_BUFFER
- unsigned int start_segment_vertex_offset() const { return 0; }
- unsigned int end_segment_vertex_offset() const {
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ unsigned int max_indices_per_segment() const {
switch (render_primitive_type)
{
- case ERenderPrimitiveType::Point: { return 0; }
- case ERenderPrimitiveType::Line: { return 1; }
- case ERenderPrimitiveType::Triangle: { return 36; } // 1st vertex of 13th triangle
+ case ERenderPrimitiveType::Point: { return 1; }
+ case ERenderPrimitiveType::Line: { return 2; }
+ case ERenderPrimitiveType::Triangle: { return 36; } // 3 indices x 12 triangles
default: { return 0; }
}
}
+ size_t max_indices_per_segment_size_bytes() const { return max_indices_per_segment() * sizeof(IBufferType); }
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
#if ENABLE_SPLITTED_VERTEX_BUFFER
bool has_data() const {
return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0;
}
#else
+ unsigned int start_segment_vertex_offset() const { return 0; }
+ unsigned int end_segment_vertex_offset() const {
+ switch (render_primitive_type)
+ {
+ case ERenderPrimitiveType::Point: { return 0; }
+ case ERenderPrimitiveType::Line: { return 1; }
+ case ERenderPrimitiveType::Triangle: { return 36; } // 1st vertex of 13th triangle
+ default: { return 0; }
+ }
+ }
+
bool has_data() const { return vertices.id != 0 && !indices.empty() && indices.front().id != 0; }
#endif // ENABLE_SPLITTED_VERTEX_BUFFER
};
@@ -439,18 +465,41 @@ class GCodeViewer
#endif // ENABLE_SPLITTED_VERTEX_BUFFER
};
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ // used to render the toolpath caps of the current sequential range
+ // (i.e. when sliding on the horizontal slider)
+ struct SequentialRangeCap
+ {
+ TBuffer* buffer{ nullptr };
+ unsigned int ibo{ 0 };
+ unsigned int vbo{ 0 };
+ Color color;
+
+ ~SequentialRangeCap();
+ bool is_renderable() const { return buffer != nullptr; }
+ void reset();
+ size_t indices_count() const { return 6; }
+ };
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+
#if ENABLE_GCODE_VIEWER_STATISTICS
struct Statistics
{
// time
int64_t results_time{ 0 };
int64_t load_time{ 0 };
+ int64_t load_vertices{ 0 };
+ int64_t smooth_vertices{ 0 };
+ int64_t load_indices{ 0 };
int64_t refresh_time{ 0 };
int64_t refresh_paths_time{ 0 };
// opengl calls
int64_t gl_multi_points_calls_count{ 0 };
int64_t gl_multi_lines_calls_count{ 0 };
int64_t gl_multi_triangles_calls_count{ 0 };
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ int64_t gl_triangles_calls_count{ 0 };
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
// memory
int64_t results_size{ 0 };
int64_t total_vertices_gpu_size{ 0 };
@@ -476,6 +525,9 @@ class GCodeViewer
void reset_times() {
results_time = 0;
load_time = 0;
+ load_vertices = 0;
+ smooth_vertices = 0;
+ load_indices = 0;
refresh_time = 0;
refresh_paths_time = 0;
}
@@ -484,6 +536,9 @@ class GCodeViewer
gl_multi_points_calls_count = 0;
gl_multi_lines_calls_count = 0;
gl_multi_triangles_calls_count = 0;
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ gl_triangles_calls_count = 0;
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
}
void reset_sizes() {
@@ -560,10 +615,10 @@ public:
};
private:
- mutable bool m_gl_data_initialized{ false };
+ bool m_gl_data_initialized{ false };
unsigned int m_last_result_id{ 0 };
size_t m_moves_count{ 0 };
- mutable std::vector<TBuffer> m_buffers{ static_cast<size_t>(EMoveType::Extrude) };
+ std::vector<TBuffer> m_buffers{ static_cast<size_t>(EMoveType::Extrude) };
// bounding box of toolpaths
BoundingBoxf3 m_paths_bounding_box;
// bounding box of toolpaths + marker tools
@@ -574,18 +629,21 @@ private:
std::vector<ExtrusionRole> m_roles;
size_t m_extruders_count;
std::vector<unsigned char> m_extruder_ids;
- mutable Extrusions m_extrusions;
- mutable SequentialView m_sequential_view;
+ Extrusions m_extrusions;
+ SequentialView m_sequential_view;
Shells m_shells;
EViewType m_view_type{ EViewType::FeatureType };
bool m_legend_enabled{ true };
PrintEstimatedTimeStatistics m_time_statistics;
- mutable PrintEstimatedTimeStatistics::ETimeMode m_time_estimate_mode{ PrintEstimatedTimeStatistics::ETimeMode::Normal };
+ PrintEstimatedTimeStatistics::ETimeMode m_time_estimate_mode{ PrintEstimatedTimeStatistics::ETimeMode::Normal };
#if ENABLE_GCODE_VIEWER_STATISTICS
- mutable Statistics m_statistics;
+ Statistics m_statistics;
#endif // ENABLE_GCODE_VIEWER_STATISTICS
- mutable std::array<float, 2> m_detected_point_sizes = { 0.0f, 0.0f };
+ std::array<float, 2> m_detected_point_sizes = { 0.0f, 0.0f };
GCodeProcessor::Result::SettingsIds m_settings_ids;
+#if ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
+ std::array<SequentialRangeCap, 2> m_sequential_range_caps;
+#endif // ENABLE_REDUCED_TOOLPATHS_SEGMENT_CAPS
public:
GCodeViewer();