diff --git a/resources/shaders/extrusions.fs b/resources/shaders/extrusions.fs deleted file mode 100644 index 65db0667a..000000000 --- a/resources/shaders/extrusions.fs +++ /dev/null @@ -1,40 +0,0 @@ -#version 110 - -#define INTENSITY_AMBIENT 0.3 -#define INTENSITY_CORRECTION 0.6 - -// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) -const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); -#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) -#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) -#define LIGHT_TOP_SHININESS 20.0 - -// normalized values for (1./1.43, 0.2/1.43, 1./1.43) -const vec3 LIGHT_FRONT_DIR = vec3(0.0, 0.0, 1.0); -#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) - -uniform vec3 uniform_color; - -varying vec3 eye_position; -varying vec3 eye_normal; - -// x = tainted, y = specular; -vec2 intensity; - -void main() -{ - vec3 normal = normalize(eye_normal); - - // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. - // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. - float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); - - intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; - intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); - - // Perform the same lighting calculation for the 2nd light source (no specular applied). - NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); - intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; - - gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + uniform_color * intensity.x, 1.0); -} diff --git a/resources/shaders/extrusions.vs b/resources/shaders/extrusions.vs deleted file mode 100644 index 8980f3944..000000000 --- a/resources/shaders/extrusions.vs +++ /dev/null @@ -1,11 +0,0 @@ -#version 110 - -varying vec3 eye_position; -varying vec3 eye_normal; - -void main() -{ - eye_position = (gl_ModelViewMatrix * gl_Vertex).xyz; - eye_normal = gl_NormalMatrix * vec3(0.0, 0.0, 1.0); - gl_Position = ftransform(); -} diff --git a/resources/shaders/options_120_solid.fs b/resources/shaders/options_120_solid.fs index 4719ff96a..4480d7b14 100644 --- a/resources/shaders/options_120_solid.fs +++ b/resources/shaders/options_120_solid.fs @@ -84,6 +84,6 @@ void main() vec3 eye_on_sphere_position = eye_position_on_sphere(eye_position_from_fragment()); - gl_FragDepth = fragment_depth(eye_on_sphere_position); +// gl_FragDepth = fragment_depth(eye_on_sphere_position); gl_FragColor = on_sphere_color(eye_on_sphere_position); } diff --git a/resources/shaders/toolpaths.fs b/resources/shaders/toolpaths.fs new file mode 100644 index 000000000..13f60c0a8 --- /dev/null +++ b/resources/shaders/toolpaths.fs @@ -0,0 +1,31 @@ +#version 110 + +// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) +const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); +const vec3 LIGHT_FRONT_DIR = vec3(0.0, 0.0, 1.0); + +// x = ambient, y = top diffuse, z = front diffuse, w = global +uniform vec4 light_intensity; +uniform vec3 uniform_color; + +varying vec3 eye_position; +varying vec3 eye_normal; + +float intensity; + +void main() +{ + vec3 normal = normalize(eye_normal); + + // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. + // Since these two are normalized the cosine is the dot product. Take the abs value to light the lines no matter in which direction the normal points. + float NdotL = abs(dot(normal, LIGHT_TOP_DIR)); + + intensity = light_intensity.x + NdotL * light_intensity.y; + + // Perform the same lighting calculation for the 2nd light source. + NdotL = abs(dot(normal, LIGHT_FRONT_DIR)); + intensity += NdotL * light_intensity.z; + + gl_FragColor = vec4(uniform_color * light_intensity.w * intensity, 1.0); +} diff --git a/resources/shaders/toolpaths.vs b/resources/shaders/toolpaths.vs new file mode 100644 index 000000000..34d141bfe --- /dev/null +++ b/resources/shaders/toolpaths.vs @@ -0,0 +1,21 @@ +#version 110 + +varying vec3 eye_position; +varying vec3 eye_normal; + +vec3 world_normal() +{ + // the world normal is always parallel to the world XY plane + // the x component is stored into gl_Vertex.w + float x = gl_Vertex.w; + float y = sqrt(1.0 - x * x); + return vec3(x, y, 0.0); +} + +void main() +{ + vec4 world_position = vec4(gl_Vertex.xyz, 1.0); + gl_Position = gl_ModelViewProjectionMatrix * world_position; + eye_position = (gl_ModelViewMatrix * world_position).xyz; + eye_normal = gl_NormalMatrix * world_normal(); +} diff --git a/resources/shaders/travels.fs b/resources/shaders/travels.fs deleted file mode 100644 index 65db0667a..000000000 --- a/resources/shaders/travels.fs +++ /dev/null @@ -1,40 +0,0 @@ -#version 110 - -#define INTENSITY_AMBIENT 0.3 -#define INTENSITY_CORRECTION 0.6 - -// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31) -const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929); -#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION) -#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION) -#define LIGHT_TOP_SHININESS 20.0 - -// normalized values for (1./1.43, 0.2/1.43, 1./1.43) -const vec3 LIGHT_FRONT_DIR = vec3(0.0, 0.0, 1.0); -#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION) - -uniform vec3 uniform_color; - -varying vec3 eye_position; -varying vec3 eye_normal; - -// x = tainted, y = specular; -vec2 intensity; - -void main() -{ - vec3 normal = normalize(eye_normal); - - // Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex. - // Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range. - float NdotL = max(dot(normal, LIGHT_TOP_DIR), 0.0); - - intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE; - intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS); - - // Perform the same lighting calculation for the 2nd light source (no specular applied). - NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0); - intensity.x += NdotL * LIGHT_FRONT_DIFFUSE; - - gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + uniform_color * intensity.x, 1.0); -} diff --git a/resources/shaders/travels.vs b/resources/shaders/travels.vs deleted file mode 100644 index 8980f3944..000000000 --- a/resources/shaders/travels.vs +++ /dev/null @@ -1,11 +0,0 @@ -#version 110 - -varying vec3 eye_position; -varying vec3 eye_normal; - -void main() -{ - eye_position = (gl_ModelViewMatrix * gl_Vertex).xyz; - eye_normal = gl_NormalMatrix * vec3(0.0, 0.0, 1.0); - gl_Position = ftransform(); -} diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index d56164726..14f29b56b 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -7,6 +7,10 @@ #if ENABLE_GCODE_VIEWER +#if ENABLE_GCODE_VIEWER_STATISTICS +#include +#endif // ENABLE_GCODE_VIEWER_STATISTICS + static const float INCHES_TO_MM = 25.4f; static const float MMMIN_TO_MMSEC = 1.0f / 60.0f; @@ -89,9 +93,17 @@ void GCodeProcessor::reset() void GCodeProcessor::process_file(const std::string& filename) { +#if ENABLE_GCODE_VIEWER_STATISTICS + auto start_time = std::chrono::high_resolution_clock::now(); +#endif // ENABLE_GCODE_VIEWER_STATISTICS + m_result.id = ++s_result_id; m_result.moves.emplace_back(MoveVertex()); m_parser.parse_file(filename, [this](GCodeReader& reader, const GCodeReader::GCodeLine& line) { process_gcode_line(line); }); + +#if ENABLE_GCODE_VIEWER_STATISTICS + m_result.time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); +#endif // ENABLE_GCODE_VIEWER_STATISTICS } void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line) diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index bc4924584..3f596c9c2 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -106,7 +106,12 @@ namespace Slic3r { { unsigned int id; std::vector moves; +#if ENABLE_GCODE_VIEWER_STATISTICS + long long time{ 0 }; + void reset() { time = 0; moves = std::vector(); } +#else void reset() { moves = std::vector(); } +#endif // ENABLE_GCODE_VIEWER_STATISTICS }; private: diff --git a/src/libslic3r/Technologies.hpp b/src/libslic3r/Technologies.hpp index b04e78c4e..fb84efe5a 100644 --- a/src/libslic3r/Technologies.hpp +++ b/src/libslic3r/Technologies.hpp @@ -59,8 +59,8 @@ // Enable G-Code viewer #define ENABLE_GCODE_VIEWER (1 && ENABLE_2_3_0_ALPHA1) -#define ENABLE_GCODE_VIEWER_STATISTICS (0 && ENABLE_GCODE_VIEWER) -#define ENABLE_GCODE_VIEWER_SHADERS_EDITOR (0 && ENABLE_GCODE_VIEWER) +#define ENABLE_GCODE_VIEWER_STATISTICS (1 && ENABLE_GCODE_VIEWER) +#define ENABLE_GCODE_VIEWER_SHADERS_EDITOR (1 && ENABLE_GCODE_VIEWER) #define ENABLE_GCODE_VIEWER_AS_STATE (1 && ENABLE_GCODE_VIEWER) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index 05a8c20bb..6d6ba557e 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -64,12 +64,23 @@ std::vector> decode_colors(const std::vector & void GCodeViewer::VBuffer::reset() { // release gpu memory - if (vbo_id > 0) { - glsafe(::glDeleteBuffers(1, &vbo_id)); - vbo_id = 0; + if (id > 0) { + glsafe(::glDeleteBuffers(1, &id)); + id = 0; } - vertices_count = 0; + count = 0; +} + +void GCodeViewer::IBuffer::reset() +{ + // release gpu memory + if (id > 0) { + glsafe(::glDeleteBuffers(1, &id)); + id = 0; + } + + count = 0; } bool GCodeViewer::Path::matches(const GCodeProcessor::MoveVertex& move) const @@ -96,21 +107,18 @@ bool GCodeViewer::Path::matches(const GCodeProcessor::MoveVertex& move) const } } -void GCodeViewer::IBuffer::reset() +void GCodeViewer::TBuffer::reset() { // release gpu memory - if (ibo_id > 0) { - glsafe(::glDeleteBuffers(1, &ibo_id)); - ibo_id = 0; - } + vertices.reset(); + indices.reset(); // release cpu memory - indices_count = 0; paths = std::vector(); render_paths = std::vector(); } -void GCodeViewer::IBuffer::add_path(const GCodeProcessor::MoveVertex& move, unsigned int i_id, unsigned int s_id) +void GCodeViewer::TBuffer::add_path(const GCodeProcessor::MoveVertex& move, unsigned int i_id, unsigned int s_id) { Path::Endpoint endpoint = { i_id, s_id, move.position }; paths.push_back({ move.type, move.extrusion_role, endpoint, endpoint, move.delta_extruder, move.height, move.width, move.feedrate, move.fan_speed, move.volumetric_rate(), move.extruder_id, move.cp_color_id }); @@ -209,7 +217,7 @@ void GCodeViewer::SequentialView::Marker::render() const } const std::vector GCodeViewer::Extrusion_Role_Colors {{ - { 0.50f, 0.50f, 0.50f }, // erNone + { 0.75f, 0.75f, 0.75f }, // erNone { 1.00f, 1.00f, 0.40f }, // erPerimeter { 1.00f, 0.65f, 0.00f }, // erExternalPerimeter { 0.00f, 0.00f, 1.00f }, // erOverhangPerimeter @@ -257,6 +265,29 @@ const std::vector GCodeViewer::Range_Colors {{ bool GCodeViewer::init() { + for (size_t i = 0; i < m_buffers.size(); ++i) + { + switch (buffer_type(i)) + { + case GCodeProcessor::EMoveType::Tool_change: + case GCodeProcessor::EMoveType::Color_change: + case GCodeProcessor::EMoveType::Pause_Print: + case GCodeProcessor::EMoveType::Custom_GCode: + case GCodeProcessor::EMoveType::Retract: + case GCodeProcessor::EMoveType::Unretract: + { + m_buffers[i].vertices.format = VBuffer::EFormat::Position; + break; + } + case GCodeProcessor::EMoveType::Extrude: + case GCodeProcessor::EMoveType::Travel: + { + m_buffers[i].vertices.format = VBuffer::EFormat::PositionNormal; + break; + } + } + } + set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Extrude, true); m_sequential_view.marker.init(); init_shaders(); @@ -306,7 +337,7 @@ void GCodeViewer::refresh(const GCodeProcessor::Result& gcode_result, const std: auto start_time = std::chrono::high_resolution_clock::now(); #endif // ENABLE_GCODE_VIEWER_STATISTICS - if (m_vertices.vertices_count == 0) + if (m_vertices_count == 0) return; // update tool colors @@ -314,7 +345,7 @@ void GCodeViewer::refresh(const GCodeProcessor::Result& gcode_result, const std: // update ranges for coloring / legend m_extrusions.reset_ranges(); - for (size_t i = 0; i < m_vertices.vertices_count; ++i) { + for (size_t i = 0; i < m_vertices_count; ++i) { // skip first vertex if (i == 0) continue; @@ -342,19 +373,18 @@ void GCodeViewer::refresh(const GCodeProcessor::Result& gcode_result, const std: } } - // update buffers' render paths - refresh_render_paths(false, false); - #if ENABLE_GCODE_VIEWER_STATISTICS m_statistics.refresh_time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); #endif // ENABLE_GCODE_VIEWER_STATISTICS + + // update buffers' render paths + refresh_render_paths(false, false); } void GCodeViewer::reset() { - m_vertices.reset(); - - for (IBuffer& buffer : m_buffers) { + m_vertices_count = 0; + for (TBuffer& buffer : m_buffers) { buffer.reset(); } @@ -472,8 +502,8 @@ void GCodeViewer::init_shaders() case GCodeProcessor::EMoveType::Custom_GCode: { m_buffers[i].shader = is_glsl_120 ? "options_120_solid" : "options_110"; break; } case GCodeProcessor::EMoveType::Retract: { m_buffers[i].shader = is_glsl_120 ? "options_120_solid" : "options_110"; break; } case GCodeProcessor::EMoveType::Unretract: { m_buffers[i].shader = is_glsl_120 ? "options_120_solid" : "options_110"; break; } - case GCodeProcessor::EMoveType::Extrude: { m_buffers[i].shader = "extrusions"; break; } - case GCodeProcessor::EMoveType::Travel: { m_buffers[i].shader = "travels"; break; } + case GCodeProcessor::EMoveType::Extrude: { m_buffers[i].shader = "toolpaths"; break; } + case GCodeProcessor::EMoveType::Travel: { m_buffers[i].shader = "toolpaths"; break; } default: { break; } } } @@ -484,16 +514,15 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) #if ENABLE_GCODE_VIEWER_STATISTICS auto start_time = std::chrono::high_resolution_clock::now(); m_statistics.results_size = SLIC3R_STDVEC_MEMSIZE(gcode_result.moves, GCodeProcessor::MoveVertex); + m_statistics.results_time = gcode_result.time; #endif // ENABLE_GCODE_VIEWER_STATISTICS - // vertex data - m_vertices.vertices_count = gcode_result.moves.size(); - if (m_vertices.vertices_count == 0) + // vertices data + m_vertices_count = gcode_result.moves.size(); + if (m_vertices_count == 0) return; - // vertex data / bounding box -> extract from result - std::vector vertices_data(m_vertices.vertices_count * 3); - for (size_t i = 0; i < m_vertices.vertices_count; ++i) { + for (size_t i = 0; i < m_vertices_count; ++i) { const GCodeProcessor::MoveVertex& move = gcode_result.moves[i]; #if ENABLE_GCODE_VIEWER_AS_STATE if (wxGetApp().mainframe->get_mode() == MainFrame::EMode::GCodeViewer) @@ -506,29 +535,16 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) #if ENABLE_GCODE_VIEWER_AS_STATE } #endif // ENABLE_GCODE_VIEWER_AS_STATE - ::memcpy(static_cast(&vertices_data[i * 3]), static_cast(move.position.data()), 3 * sizeof(float)); } + // max bounding box m_max_bounding_box = m_paths_bounding_box; m_max_bounding_box.merge(m_paths_bounding_box.max + m_sequential_view.marker.get_bounding_box().size()[2] * Vec3d::UnitZ()); -#if ENABLE_GCODE_VIEWER_STATISTICS - m_statistics.vertices_size = SLIC3R_STDVEC_MEMSIZE(vertices_data, float); - m_statistics.vertices_gpu_size = vertices_data.size() * sizeof(float); -#endif // ENABLE_GCODE_VIEWER_STATISTICS - - // vertex data -> send to gpu - glsafe(::glGenBuffers(1, &m_vertices.vbo_id)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vertices.vbo_id)); - glsafe(::glBufferData(GL_ARRAY_BUFFER, vertices_data.size() * sizeof(float), vertices_data.data(), GL_STATIC_DRAW)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - - // vertex data -> no more needed, free ram - vertices_data = std::vector(); - - // indices data -> extract from result + // toolpaths data -> extract from result + std::vector> vertices(m_buffers.size()); std::vector> indices(m_buffers.size()); - for (size_t i = 0; i < m_vertices.vertices_count; ++i) { + for (size_t i = 0; i < m_vertices_count; ++i) { // skip first vertex if (i == 0) continue; @@ -537,7 +553,8 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) const GCodeProcessor::MoveVertex& curr = gcode_result.moves[i]; unsigned char id = buffer_id(curr.type); - IBuffer& buffer = m_buffers[id]; + TBuffer& buffer = m_buffers[id]; + std::vector& buffer_vertices = vertices[id]; std::vector& buffer_indices = indices[id]; switch (curr.type) @@ -549,54 +566,103 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) case GCodeProcessor::EMoveType::Retract: case GCodeProcessor::EMoveType::Unretract: { + for (int j = 0; j < 3; ++j) { + buffer_vertices.push_back(curr.position[j]); + } buffer.add_path(curr, static_cast(buffer_indices.size()), static_cast(i)); - buffer_indices.push_back(static_cast(i)); + buffer_indices.push_back(static_cast(buffer_indices.size())); break; } case GCodeProcessor::EMoveType::Extrude: case GCodeProcessor::EMoveType::Travel: { + // x component of the normal to the current segment (the normal is parallel to the XY plane) + float normal_x = (curr.position - prev.position).normalized()[1]; + if (prev.type != curr.type || !buffer.paths.back().matches(curr)) { - buffer.add_path(curr, static_cast(buffer_indices.size()), static_cast(i - 1)); + // add starting vertex position + for (int j = 0; j < 3; ++j) { + buffer_vertices.push_back(prev.position[j]); + } + // add starting vertex normal x component + buffer_vertices.push_back(normal_x); + // add starting index + buffer_indices.push_back(buffer_indices.size()); + buffer.add_path(curr, static_cast(buffer_indices.size() - 1), static_cast(i - 1)); Path& last_path = buffer.paths.back(); last_path.first.position = prev.position; - buffer_indices.push_back(static_cast(i - 1)); } - - buffer.paths.back().last = { static_cast(buffer_indices.size()), static_cast(i), curr.position }; - buffer_indices.push_back(static_cast(i)); + + Path& last_path = buffer.paths.back(); + if (last_path.first.i_id != last_path.last.i_id) + { + // add previous vertex position + for (int j = 0; j < 3; ++j) { + buffer_vertices.push_back(prev.position[j]); + } + // add previous vertex normal x component + buffer_vertices.push_back(normal_x); + // add previous index + buffer_indices.push_back(buffer_indices.size()); + } + + // add current vertex position + for (int j = 0; j < 3; ++j) { + buffer_vertices.push_back(curr.position[j]); + } + // add current vertex normal x component + buffer_vertices.push_back(normal_x); + // add current index + buffer_indices.push_back(buffer_indices.size()); + last_path.last = { static_cast(buffer_indices.size() - 1), static_cast(i), curr.position }; break; } default: { break; } } } + // toolpaths data -> send data to gpu + for (size_t i = 0; i < m_buffers.size(); ++i) { + TBuffer& buffer = m_buffers[i]; + + // vertices + const std::vector& buffer_vertices = vertices[i]; + buffer.vertices.count = buffer_vertices.size() / buffer.vertices.vertex_size_floats(); #if ENABLE_GCODE_VIEWER_STATISTICS - for (IBuffer& buffer : m_buffers) { - m_statistics.paths_size += SLIC3R_STDVEC_MEMSIZE(buffer.paths, Path); - } + m_statistics.vertices_gpu_size = buffer_vertices.size() * sizeof(float); #endif // ENABLE_GCODE_VIEWER_STATISTICS - // indices data -> send data to gpu - for (size_t i = 0; i < m_buffers.size(); ++i) { - IBuffer& buffer = m_buffers[i]; + glsafe(::glGenBuffers(1, &buffer.vertices.id)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.vertices.id)); + glsafe(::glBufferData(GL_ARRAY_BUFFER, buffer_vertices.size() * sizeof(float), buffer_vertices.data(), GL_STATIC_DRAW)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + + // indices const std::vector& buffer_indices = indices[i]; - buffer.indices_count = buffer_indices.size(); + buffer.indices.count = buffer_indices.size(); #if ENABLE_GCODE_VIEWER_STATISTICS m_statistics.indices_size += SLIC3R_STDVEC_MEMSIZE(buffer_indices, unsigned int); - m_statistics.indices_gpu_size += buffer.indices_count * sizeof(unsigned int); + m_statistics.indices_gpu_size += buffer.indices.count * sizeof(unsigned int); #endif // ENABLE_GCODE_VIEWER_STATISTICS - if (buffer.indices_count > 0) { - glsafe(::glGenBuffers(1, &buffer.ibo_id)); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.ibo_id)); - glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer.indices_count * sizeof(unsigned int), buffer_indices.data(), GL_STATIC_DRAW)); + if (buffer.indices.count > 0) { + glsafe(::glGenBuffers(1, &buffer.indices.id)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.indices.id)); + glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, buffer.indices.count * sizeof(unsigned int), buffer_indices.data(), GL_STATIC_DRAW)); glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); } } +#if ENABLE_GCODE_VIEWER_STATISTICS + for (const TBuffer& buffer : m_buffers) { + m_statistics.paths_size += SLIC3R_STDVEC_MEMSIZE(buffer.paths, Path); + } + m_statistics.travel_segments_count = indices[buffer_id(GCodeProcessor::EMoveType::Travel)].size() / 2; + m_statistics.extrude_segments_count = indices[buffer_id(GCodeProcessor::EMoveType::Extrude)].size() / 2; +#endif // ENABLE_GCODE_VIEWER_STATISTICS + // layers zs / roles / extruder ids / cp color ids -> extract from result - for (size_t i = 0; i < m_vertices.vertices_count; ++i) { + for (size_t i = 0; i < m_vertices_count; ++i) { const GCodeProcessor::MoveVertex& move = gcode_result.moves[i]; if (move.type == GCodeProcessor::EMoveType::Extrude) m_layers_zs.emplace_back(static_cast(move.position[2])); @@ -728,18 +794,18 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool m_statistics.render_paths_size = 0; #endif // ENABLE_GCODE_VIEWER_STATISTICS - m_sequential_view.endpoints.first = m_vertices.vertices_count; + m_sequential_view.endpoints.first = m_vertices_count; m_sequential_view.endpoints.last = 0; if (!keep_sequential_current_first) m_sequential_view.current.first = 0; if (!keep_sequential_current_last) - m_sequential_view.current.last = m_vertices.vertices_count; + m_sequential_view.current.last = m_vertices_count; // first pass: collect visible paths and update sequential view data - std::vector> paths; - for (IBuffer& buffer : m_buffers) { + std::vector> paths; + for (TBuffer& buffer : m_buffers) { // reset render paths - buffer.render_paths = std::vector(); + buffer.render_paths.clear(); if (!buffer.visible) continue; @@ -767,23 +833,43 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool // update current sequential position m_sequential_view.current.first = 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; m_sequential_view.current.last = keep_sequential_current_last ? std::clamp(m_sequential_view.current.last, m_sequential_view.endpoints.first, m_sequential_view.endpoints.last) : m_sequential_view.endpoints.last; - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vertices.vbo_id)); - size_t v_size = VBuffer::vertex_size_bytes(); - glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(m_sequential_view.current.last * v_size), static_cast(v_size), static_cast(m_sequential_view.current_position.data()))); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); - // second pass: filter paths by sequential data + // get the world position from gpu + bool found = false; + for (const TBuffer& buffer : m_buffers) { + // searches the path containing the current position + for (const Path& path : buffer.paths) { + if (path.first.s_id <= m_sequential_view.current.last && m_sequential_view.current.last <= path.last.s_id) { + size_t offset = m_sequential_view.current.last - path.first.s_id; + if (offset > 0 && (path.type == GCodeProcessor::EMoveType::Travel || path.type == GCodeProcessor::EMoveType::Extrude)) + offset = 1 + 2 * (offset - 1); + + offset += path.first.i_id; + + // gets the position from the vertices buffer on gpu + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.vertices.id)); + glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, static_cast(offset * buffer.vertices.vertex_size_bytes()), static_cast(3 * sizeof(float)), static_cast(m_sequential_view.current_position.data()))); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + found = true; + break; + } + } + if (found) + break; + } + + // second pass: filter paths by sequential data and collect them by color for (auto&& [buffer, id] : paths) { const Path& path = buffer->paths[id]; - if ((m_sequential_view.current.last <= path.first.s_id) || (path.last.s_id <= m_sequential_view.current.first)) + if (m_sequential_view.current.last <= path.first.s_id || path.last.s_id <= m_sequential_view.current.first) continue; Color color; switch (path.type) { case GCodeProcessor::EMoveType::Extrude: { color = extrusion_color(path); break; } - case GCodeProcessor::EMoveType::Travel: { color = (m_view_type == EViewType::Feedrate || m_view_type == EViewType::Tool || m_view_type == EViewType::ColorPrint) ? extrusion_color(path) : travel_color(path); break; } - default: { color = { 0.0f, 0.0f, 0.0f }; break; } + case GCodeProcessor::EMoveType::Travel: { color = (m_view_type == EViewType::Feedrate || m_view_type == EViewType::Tool || m_view_type == EViewType::ColorPrint) ? extrusion_color(path) : travel_color(path); break; } + default: { color = { 0.0f, 0.0f, 0.0f }; break; } } auto it = std::find_if(buffer->render_paths.begin(), buffer->render_paths.end(), [color](const RenderPath& path) { return path.color == color; }); @@ -792,7 +878,11 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool it->color = color; } - it->sizes.push_back(std::min(m_sequential_view.current.last, path.last.s_id) - std::max(m_sequential_view.current.first, path.first.s_id) + 1); + unsigned int size = std::min(m_sequential_view.current.last, path.last.s_id) - std::max(m_sequential_view.current.first, path.first.s_id) + 1; + if (path.type == GCodeProcessor::EMoveType::Extrude || path.type == GCodeProcessor::EMoveType::Travel) + size = 2 * (size - 1); + + it->sizes.push_back(size); unsigned int delta_1st = 0; if ((path.first.s_id < m_sequential_view.current.first) && (m_sequential_view.current.first <= path.last.s_id)) delta_1st = m_sequential_view.current.first - path.first.s_id; @@ -801,14 +891,13 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool } #if ENABLE_GCODE_VIEWER_STATISTICS - for (const IBuffer& buffer : m_buffers) { + for (const TBuffer& buffer : m_buffers) { m_statistics.render_paths_size += SLIC3R_STDVEC_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); } } - m_statistics.refresh_paths_time = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start_time).count(); #endif // ENABLE_GCODE_VIEWER_STATISTICS } @@ -816,9 +905,9 @@ void GCodeViewer::refresh_render_paths(bool keep_sequential_current_first, bool void GCodeViewer::render_toolpaths() const { #if ENABLE_GCODE_VIEWER_SHADERS_EDITOR - float point_size = m_shaders_editor.point_size; + float point_size = m_shaders_editor.points.point_size; #else - float point_size = 1.0f; + float point_size = 0.8f; #endif // ENABLE_GCODE_VIEWER_SHADERS_EDITOR const Camera& camera = wxGetApp().plater()->get_camera(); double zoom = camera.get_zoom(); @@ -828,12 +917,12 @@ void GCodeViewer::render_toolpaths() const Transform3d inv_proj = camera.get_projection_matrix().inverse(); - auto render_as_points = [this, zoom, inv_proj, viewport, point_size, near_plane_height](const IBuffer& buffer, EOptionsColors color_id, GLShaderProgram& shader) { + auto render_as_points = [this, zoom, inv_proj, viewport, point_size, near_plane_height](const TBuffer& buffer, EOptionsColors color_id, GLShaderProgram& shader) { shader.set_uniform("uniform_color", Options_Colors[static_cast(color_id)]); shader.set_uniform("zoom", zoom); #if ENABLE_GCODE_VIEWER_SHADERS_EDITOR - shader.set_uniform("percent_outline_radius", 0.01f * static_cast(m_shaders_editor.percent_outline)); - shader.set_uniform("percent_center_radius", 0.01f * static_cast(m_shaders_editor.percent_center)); + shader.set_uniform("percent_outline_radius", 0.01f * static_cast(m_shaders_editor.points.percent_outline)); + shader.set_uniform("percent_center_radius", 0.01f * static_cast(m_shaders_editor.points.percent_center)); #else shader.set_uniform("percent_outline_radius", 0.15f); shader.set_uniform("percent_center_radius", 0.15f); @@ -852,16 +941,16 @@ void GCodeViewer::render_toolpaths() const ++m_statistics.gl_multi_points_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS } - + glsafe(::glDisable(GL_POINT_SPRITE)); glsafe(::glDisable(GL_VERTEX_PROGRAM_POINT_SIZE)); }; - auto render_as_lines = [this](const IBuffer& buffer, GLShaderProgram& shader) { + auto render_as_lines = [this](const TBuffer& buffer, GLShaderProgram& shader) { for (const RenderPath& path : buffer.render_paths) { shader.set_uniform("uniform_color", path.color); - glsafe(::glMultiDrawElements(GL_LINE_STRIP, (const GLsizei*)path.sizes.data(), GL_UNSIGNED_INT, (const void* const*)path.offsets.data(), (GLsizei)path.sizes.size())); + 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_line_strip_calls_count; #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -878,27 +967,25 @@ void GCodeViewer::render_toolpaths() const unsigned char begin_id = buffer_id(GCodeProcessor::EMoveType::Retract); unsigned char end_id = buffer_id(GCodeProcessor::EMoveType::Count); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vertices.vbo_id)); - glsafe(::glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, VBuffer::vertex_size_bytes(), (const void*)0)); - glsafe(::glEnableVertexAttribArray(0)); - for (unsigned char i = begin_id; i < end_id; ++i) { - const IBuffer& buffer = m_buffers[i]; - if (buffer.ibo_id == 0) - continue; - + const TBuffer& buffer = m_buffers[i]; if (!buffer.visible) continue; + if (buffer.vertices.id == 0 || buffer.indices.id == 0) + continue; + GLShaderProgram* shader = wxGetApp().get_shader(buffer.shader.c_str()); if (shader != nullptr) { shader->start_using(); - GCodeProcessor::EMoveType type = buffer_type(i); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.vertices.id)); + glsafe(::glVertexAttribPointer(0, buffer.vertices.vertex_size_floats(), GL_FLOAT, GL_FALSE, buffer.vertices.vertex_size_bytes(), (const void*)0)); + glsafe(::glEnableVertexAttribArray(0)); - glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.ibo_id)); + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.indices.id)); - switch (type) + switch (buffer_type(i)) { case GCodeProcessor::EMoveType::Tool_change: { render_as_points(buffer, EOptionsColors::ToolChanges, *shader); break; } case GCodeProcessor::EMoveType::Color_change: { render_as_points(buffer, EOptionsColors::ColorChanges, *shader); break; } @@ -907,16 +994,33 @@ void GCodeViewer::render_toolpaths() const case GCodeProcessor::EMoveType::Retract: { render_as_points(buffer, EOptionsColors::Retractions, *shader); break; } case GCodeProcessor::EMoveType::Unretract: { render_as_points(buffer, EOptionsColors::Unretractions, *shader); break; } case GCodeProcessor::EMoveType::Extrude: - case GCodeProcessor::EMoveType::Travel: { render_as_lines(buffer, *shader); break; } + case GCodeProcessor::EMoveType::Travel: + { + std::array light_intensity; +#if ENABLE_GCODE_VIEWER_SHADERS_EDITOR + light_intensity[0] = m_shaders_editor.lines.lights.ambient; + light_intensity[1] = m_shaders_editor.lines.lights.top_diffuse; + light_intensity[2] = m_shaders_editor.lines.lights.front_diffuse; + light_intensity[3] = m_shaders_editor.lines.lights.global; +#else + light_intensity[0] = 0.25f; + light_intensity[1] = 0.7f; + light_intensity[2] = 0.75f; + light_intensity[3] = 0.75f; +#endif // ENABLE_GCODE_VIEWER_SHADERS_EDITOR + shader->set_uniform("light_intensity", light_intensity); + render_as_lines(buffer, *shader); break; + } } glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + + glsafe(::glDisableVertexAttribArray(0)); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + shader->stop_using(); } } - - glsafe(::glDisableVertexAttribArray(0)); - glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); } void GCodeViewer::render_shells() const @@ -985,13 +1089,13 @@ void GCodeViewer::render_legend() const { #if ENABLE_GCODE_VIEWER_SHADERS_EDITOR ImVec2 center(0.5f * (pos.x + pos.x + icon_size), 0.5f * (pos.y + pos.y + icon_size)); - if (m_shaders_editor.shader_version == 1) { + if (m_shaders_editor.points.shader_version == 1) { draw_list->AddCircleFilled(center, 0.5f * icon_size, ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16); - float radius = 0.5f * icon_size * (1.0f - 0.01f * static_cast(m_shaders_editor.percent_outline)); + float radius = 0.5f * icon_size * (1.0f - 0.01f * static_cast(m_shaders_editor.points.percent_outline)); draw_list->AddCircleFilled(center, radius, ImGui::GetColorU32({ color[0], color[1], color[2], 1.0f }), 16); - if (m_shaders_editor.percent_center > 0) { - radius = 0.5f * icon_size * 0.01f * static_cast(m_shaders_editor.percent_center); + if (m_shaders_editor.points.percent_center > 0) { + radius = 0.5f * icon_size * 0.01f * static_cast(m_shaders_editor.points.percent_center); draw_list->AddCircleFilled(center, radius, ImGui::GetColorU32({ 0.5f * color[0], 0.5f * color[1], 0.5f * color[2], 1.0f }), 16); } } @@ -1284,10 +1388,10 @@ void GCodeViewer::render_legend() const }; auto add_option = [this, add_item](GCodeProcessor::EMoveType move_type, EOptionsColors color, const std::string& text) { - const IBuffer& buffer = m_buffers[buffer_id(move_type)]; - if (buffer.visible && buffer.indices_count > 0) + const TBuffer& buffer = m_buffers[buffer_id(move_type)]; + if (buffer.visible && buffer.indices.count > 0) #if ENABLE_GCODE_VIEWER_SHADERS_EDITOR - add_item((m_shaders_editor.shader_version == 0) ? EItemType::Rect : EItemType::Circle, Options_Colors[static_cast(color)], text); + add_item((m_shaders_editor.points.shader_version == 0) ? EItemType::Rect : EItemType::Circle, Options_Colors[static_cast(color)], text); #else add_item((buffer.shader == "options_110") ? EItemType::Rect : EItemType::Circle, Options_Colors[static_cast(color)], text); #endif // ENABLE_GCODE_VIEWER_SHADERS_EDITOR @@ -1320,14 +1424,22 @@ void GCodeViewer::render_legend() const void GCodeViewer::render_statistics() const { static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f); - static const float offset = 250.0f; + static const float offset = 230.0f; ImGuiWrapper& imgui = *wxGetApp().imgui(); imgui.set_next_window_pos(0.5f * wxGetApp().plater()->get_current_canvas3D()->get_canvas_size().get_width(), 0.0f, ImGuiCond_Once, 0.5f, 0.0f); - imgui.begin(std::string("Statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); + imgui.begin(std::string("GCodeViewer Statistics"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize); ImGui::BringWindowToDisplayFront(ImGui::GetCurrentWindow()); + ImGui::PushStyleColor(ImGuiCol_Text, ORANGE); + imgui.text(std::string("GCodeProcessor time:")); + ImGui::PopStyleColor(); + ImGui::SameLine(offset); + imgui.text(std::to_string(m_statistics.results_time) + " ms"); + + ImGui::Separator(); + ImGui::PushStyleColor(ImGuiCol_Text, ORANGE); imgui.text(std::string("Load time:")); ImGui::PopStyleColor(); @@ -1370,12 +1482,6 @@ void GCodeViewer::render_statistics() const ImGui::Separator(); - ImGui::PushStyleColor(ImGuiCol_Text, ORANGE); - imgui.text(std::string("Vertices CPU:")); - ImGui::PopStyleColor(); - ImGui::SameLine(offset); - imgui.text(std::to_string(m_statistics.vertices_size) + " bytes"); - ImGui::PushStyleColor(ImGuiCol_Text, ORANGE); imgui.text(std::string("Indices CPU:")); ImGui::PopStyleColor(); @@ -1408,6 +1514,20 @@ void GCodeViewer::render_statistics() const ImGui::SameLine(offset); imgui.text(std::to_string(m_statistics.indices_gpu_size) + " bytes"); + ImGui::Separator(); + + ImGui::PushStyleColor(ImGuiCol_Text, ORANGE); + imgui.text(std::string("Travel segments:")); + ImGui::PopStyleColor(); + ImGui::SameLine(offset); + imgui.text(std::to_string(m_statistics.travel_segments_count)); + + ImGui::PushStyleColor(ImGuiCol_Text, ORANGE); + imgui.text(std::string("Extrude segments:")); + ImGui::PopStyleColor(); + ImGui::SameLine(offset); + imgui.text(std::to_string(m_statistics.extrude_segments_count)); + imgui.end(); } #endif // ENABLE_GCODE_VIEWER_STATISTICS @@ -1429,34 +1549,58 @@ void GCodeViewer::render_shaders_editor() const Size cnv_size = wxGetApp().plater()->get_current_canvas3D()->get_canvas_size(); imgui.set_next_window_pos(static_cast(cnv_size.get_width()), 0.5f * static_cast(cnv_size.get_height()), ImGuiCond_Once, 1.0f, 0.5f); + imgui.begin(std::string("Shaders editor (DEV only)"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize); - ImGui::RadioButton("glsl version 1.10 (low end PCs)", &m_shaders_editor.shader_version, 0); - ImGui::RadioButton("glsl version 1.20 flat (billboards)", &m_shaders_editor.shader_version, 1); - ImGui::RadioButton("glsl version 1.20 solid (spheres default)", &m_shaders_editor.shader_version, 2); + if (ImGui::CollapsingHeader("Points", ImGuiTreeNodeFlags_DefaultOpen)) { + if (ImGui::TreeNode("GLSL version")) { + ImGui::RadioButton("1.10 (low end PCs)", &m_shaders_editor.points.shader_version, 0); + ImGui::RadioButton("1.20 flat (billboards)", &m_shaders_editor.points.shader_version, 1); + ImGui::RadioButton("1.20 solid (spheres default)", &m_shaders_editor.points.shader_version, 2); + ImGui::TreePop(); + } - switch (m_shaders_editor.shader_version) - { - case 0: { set_shader("options_110"); break; } - case 1: { set_shader("options_120_flat"); break; } - case 2: { set_shader("options_120_solid"); break; } + switch (m_shaders_editor.points.shader_version) + { + case 0: { set_shader("options_110"); break; } + case 1: { set_shader("options_120_flat"); break; } + case 2: { set_shader("options_120_solid"); break; } + } + + if (ImGui::TreeNode("Options")) { + ImGui::SliderFloat("point size", &m_shaders_editor.points.point_size, 0.5f, 3.0f, "%.2f"); + if (m_shaders_editor.points.shader_version == 1) { + ImGui::SliderInt("% outline", &m_shaders_editor.points.percent_outline, 0, 50); + ImGui::SliderInt("% center", &m_shaders_editor.points.percent_center, 0, 50); + } + ImGui::TreePop(); + } } - if (ImGui::CollapsingHeader("Options", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::SliderFloat("point size", &m_shaders_editor.point_size, 0.5f, 3.0f, "%.1f"); - if (m_shaders_editor.shader_version == 1) { - ImGui::SliderInt("percent outline", &m_shaders_editor.percent_outline, 0, 50); - ImGui::SliderInt("percent center", &m_shaders_editor.percent_center, 0, 50); + if (ImGui::CollapsingHeader("Lines", ImGuiTreeNodeFlags_DefaultOpen)) { + if (ImGui::TreeNode("Lights")) { + ImGui::SliderFloat("ambient", &m_shaders_editor.lines.lights.ambient, 0.0f, 1.0f, "%.2f"); + ImGui::SliderFloat("top diffuse", &m_shaders_editor.lines.lights.top_diffuse, 0.0f, 1.0f, "%.2f"); + ImGui::SliderFloat("front diffuse", &m_shaders_editor.lines.lights.front_diffuse, 0.0f, 1.0f, "%.2f"); + ImGui::SliderFloat("global", &m_shaders_editor.lines.lights.global, 0.0f, 1.0f, "%.2f"); + ImGui::TreePop(); } } + ImGui::SetWindowSize(ImVec2(std::max(ImGui::GetWindowWidth(), 600.0f), -1.0f), ImGuiCond_Always); + if (ImGui::GetWindowPos().x + ImGui::GetWindowWidth() > static_cast(cnv_size.get_width())) { + ImGui::SetWindowPos(ImVec2(static_cast(cnv_size.get_width()) - ImGui::GetWindowWidth(), ImGui::GetWindowPos().y), ImGuiCond_Always); + wxGetApp().plater()->get_current_canvas3D()->set_as_dirty(); + wxGetApp().plater()->get_current_canvas3D()->request_extra_frame(); + } + imgui.end(); } #endif // ENABLE_GCODE_VIEWER_SHADERS_EDITOR bool GCodeViewer::is_travel_in_z_range(size_t id) const { - const IBuffer& buffer = m_buffers[buffer_id(GCodeProcessor::EMoveType::Travel)]; + const TBuffer& buffer = m_buffers[buffer_id(GCodeProcessor::EMoveType::Travel)]; if (id >= buffer.paths.size()) return false; diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index 5c6086305..5cddeaa75 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -33,18 +33,47 @@ class GCodeViewer CustomGCodes }; - // buffer containing vertices data + // vbo buffer containing vertices data for a specific toolpath type struct VBuffer { - unsigned int vbo_id{ 0 }; - size_t vertices_count{ 0 }; + enum class EFormat : unsigned char + { + Position, + PositionNormal + }; - size_t data_size_bytes() { return vertices_count * vertex_size_bytes(); } + EFormat format{ EFormat::Position }; + // vbo id + unsigned int id{ 0 }; + // count of vertices, updated after data are sent to gpu + size_t count{ 0 }; + + size_t data_size_bytes() const { return count * vertex_size_bytes(); } + size_t vertex_size_floats() const + { + switch (format) + { + // vertex format: 3 floats -> position.x|position.y|position.z + case EFormat::Position: { return 3; } + // vertex format: 4 floats -> position.x|position.y|position.z|normal.x + case EFormat::PositionNormal: { return 4; } + default: { return 0; } + } + } + size_t vertex_size_bytes() const { return vertex_size_floats() * sizeof(float); } void reset(); + }; - static size_t vertex_size_floats() { return 3; } - static size_t vertex_size_bytes() { return vertex_size_floats() * sizeof(float); } + // ibo buffer containing indices data for a specific toolpath type + struct IBuffer + { + // ibo id + unsigned int id{ 0 }; + // count of indices, updated after data are sent to gpu + size_t count{ 0 }; + + void reset(); }; // Used to identify different toolpath sub-types inside a IBuffer @@ -52,9 +81,9 @@ class GCodeViewer { struct Endpoint { - // index into the buffer indices ibo + // index into the indices buffer unsigned int i_id{ 0u }; - // sequential id (same as index into the vertices vbo) + // sequential id unsigned int s_id{ 0u }; Vec3f position{ Vec3f::Zero() }; }; @@ -83,11 +112,12 @@ class GCodeViewer std::vector offsets; // use size_t because we need the pointer's size (used in the call glMultiDrawElements()) }; - // buffer containing indices data and shader for a specific toolpath type - struct IBuffer + // buffer containing data for rendering a specific toolpath type + struct TBuffer { - unsigned int ibo_id{ 0 }; - size_t indices_count{ 0 }; + VBuffer vertices; + IBuffer indices; + std::string shader; std::vector paths; std::vector render_paths; @@ -161,6 +191,7 @@ class GCodeViewer struct Statistics { // times + long long results_time{ 0 }; long long load_time{ 0 }; long long refresh_time{ 0 }; long long refresh_paths_time{ 0 }; @@ -169,20 +200,24 @@ class GCodeViewer long long gl_multi_line_strip_calls_count{ 0 }; // memory long long results_size{ 0 }; - long long vertices_size{ 0 }; long long vertices_gpu_size{ 0 }; long long indices_size{ 0 }; long long indices_gpu_size{ 0 }; long long paths_size{ 0 }; long long render_paths_size{ 0 }; + // others + long long travel_segments_count{ 0 }; + long long extrude_segments_count{ 0 }; void reset_all() { reset_times(); reset_opengl(); reset_sizes(); + reset_counters(); } void reset_times() { + results_time = 0; load_time = 0; refresh_time = 0; refresh_paths_time = 0; @@ -195,23 +230,46 @@ class GCodeViewer void reset_sizes() { results_size = 0; - vertices_size = 0; vertices_gpu_size = 0; indices_size = 0; indices_gpu_size = 0; - paths_size = 0; + paths_size = 0; render_paths_size = 0; } + + void reset_counters() { + travel_segments_count = 0; + extrude_segments_count = 0; + } }; #endif // ENABLE_GCODE_VIEWER_STATISTICS #if ENABLE_GCODE_VIEWER_SHADERS_EDITOR struct ShadersEditor { - int shader_version{ 2 }; - float point_size{ 1.0f }; - int percent_outline{ 0 }; - int percent_center{ 33 }; + struct Points + { + int shader_version{ 2 }; + float point_size{ 0.8f }; + int percent_outline{ 0 }; + int percent_center{ 33 }; + }; + + struct Lines + { + struct Lights + { + float ambient{ 0.25f }; + float top_diffuse{ 0.7f }; + float front_diffuse{ 0.75f }; + float global{ 0.75f }; + }; + + Lights lights; + }; + + Points points; + Lines lines; }; #endif // ENABLE_GCODE_VIEWER_SHADERS_EDITOR @@ -268,8 +326,8 @@ public: private: unsigned int m_last_result_id{ 0 }; - VBuffer m_vertices; - mutable std::vector m_buffers{ static_cast(GCodeProcessor::EMoveType::Extrude) }; + size_t m_vertices_count{ 0 }; + mutable std::vector m_buffers{ static_cast(GCodeProcessor::EMoveType::Extrude) }; // bounding box of toolpaths BoundingBoxf3 m_paths_bounding_box; // bounding box of toolpaths + marker tools diff --git a/src/slic3r/GUI/GLShadersManager.cpp b/src/slic3r/GUI/GLShadersManager.cpp index 4bebf7b98..cb47d7961 100644 --- a/src/slic3r/GUI/GLShadersManager.cpp +++ b/src/slic3r/GUI/GLShadersManager.cpp @@ -35,15 +35,12 @@ std::pair GLShadersManager::init() valid &= append_shader("printbed", { "printbed.vs", "printbed.fs" }); // used to render options in gcode preview valid &= append_shader("options_110", { "options_110.vs", "options_110.fs" }); - if (GUI::wxGetApp().is_glsl_version_greater_or_equal_to(1, 20)) - { + if (GUI::wxGetApp().is_glsl_version_greater_or_equal_to(1, 20)) { valid &= append_shader("options_120_flat", { "options_120_flat.vs", "options_120_flat.fs" }); valid &= append_shader("options_120_solid", { "options_120_solid.vs", "options_120_solid.fs" }); } - // used to render extrusion paths in gcode preview - valid &= append_shader("extrusions", { "extrusions.vs", "extrusions.fs" }); - // used to render travel paths in gcode preview - valid &= append_shader("travels", { "travels.vs", "travels.fs" }); + // used to render extrusion and travel paths in gcode preview + valid &= append_shader("toolpaths", { "toolpaths.vs", "toolpaths.fs" }); // used to render objects in 3d editor valid &= append_shader("gouraud", { "gouraud.vs", "gouraud.fs" }); // used to render variable layers heights in 3d editor