mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	GCodeViewer -> Pass vertex normal to shaders for toolpaths
This commit is contained in:
		
							parent
							
								
									d41781f674
								
							
						
					
					
						commit
						69de5c8c9f
					
				
					 13 changed files with 431 additions and 265 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										31
									
								
								resources/shaders/toolpaths.fs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								resources/shaders/toolpaths.fs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										21
									
								
								resources/shaders/toolpaths.vs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								resources/shaders/toolpaths.vs
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -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();    
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -7,6 +7,10 @@
 | 
			
		|||
 | 
			
		||||
#if ENABLE_GCODE_VIEWER
 | 
			
		||||
 | 
			
		||||
#if ENABLE_GCODE_VIEWER_STATISTICS
 | 
			
		||||
#include <chrono>
 | 
			
		||||
#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::milliseconds>(std::chrono::high_resolution_clock::now() - start_time).count();
 | 
			
		||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GCodeProcessor::process_gcode_line(const GCodeReader::GCodeLine& line)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,7 +106,12 @@ namespace Slic3r {
 | 
			
		|||
        {
 | 
			
		||||
            unsigned int id;
 | 
			
		||||
            std::vector<MoveVertex> moves;
 | 
			
		||||
#if ENABLE_GCODE_VIEWER_STATISTICS
 | 
			
		||||
            long long time{ 0 };
 | 
			
		||||
            void reset() { time = 0; moves = std::vector<MoveVertex>(); }
 | 
			
		||||
#else
 | 
			
		||||
            void reset() { moves = std::vector<MoveVertex>(); }
 | 
			
		||||
#endif // ENABLE_GCODE_VIEWER_STATISTICS
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,12 +64,23 @@ std::vector<std::array<float, 3>> decode_colors(const std::vector<std::string> &
 | 
			
		|||
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<Path>();
 | 
			
		||||
    render_paths = std::vector<RenderPath>();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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::Color> 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::Color> 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::milliseconds>(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<float> 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<void*>(&vertices_data[i * 3]), static_cast<const void*>(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<float>();
 | 
			
		||||
 | 
			
		||||
    // indices data -> extract from result
 | 
			
		||||
    // toolpaths data -> extract from result
 | 
			
		||||
    std::vector<std::vector<float>> vertices(m_buffers.size());
 | 
			
		||||
    std::vector<std::vector<unsigned int>> 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<float>& buffer_vertices = vertices[id];
 | 
			
		||||
        std::vector<unsigned int>& 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<unsigned int>(buffer_indices.size()), static_cast<unsigned int>(i));
 | 
			
		||||
            buffer_indices.push_back(static_cast<unsigned int>(i));
 | 
			
		||||
            buffer_indices.push_back(static_cast<unsigned int>(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<unsigned int>(buffer_indices.size()), static_cast<unsigned int>(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<unsigned int>(buffer_indices.size() - 1), static_cast<unsigned int>(i - 1));
 | 
			
		||||
                Path& last_path = buffer.paths.back();
 | 
			
		||||
                last_path.first.position = prev.position;
 | 
			
		||||
                buffer_indices.push_back(static_cast<unsigned int>(i - 1));
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            buffer.paths.back().last = { static_cast<unsigned int>(buffer_indices.size()), static_cast<unsigned int>(i), curr.position };
 | 
			
		||||
            buffer_indices.push_back(static_cast<unsigned int>(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<unsigned int>(buffer_indices.size() - 1), static_cast<unsigned int>(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<float>& 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<unsigned int>& 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<double>(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<std::pair<IBuffer*, size_t>> paths;
 | 
			
		||||
    for (IBuffer& buffer : m_buffers) {
 | 
			
		||||
    std::vector<std::pair<TBuffer*, size_t>> paths;
 | 
			
		||||
    for (TBuffer& buffer : m_buffers) {
 | 
			
		||||
        // reset render paths
 | 
			
		||||
        buffer.render_paths = std::vector<RenderPath>();
 | 
			
		||||
        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<GLintptr>(m_sequential_view.current.last * v_size), static_cast<GLsizeiptr>(v_size), static_cast<void*>(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<GLintptr>(offset * buffer.vertices.vertex_size_bytes()), static_cast<GLsizeiptr>(3 * sizeof(float)), static_cast<void*>(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::milliseconds>(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<unsigned int>(color_id)]);
 | 
			
		||||
        shader.set_uniform("zoom", zoom);
 | 
			
		||||
#if ENABLE_GCODE_VIEWER_SHADERS_EDITOR
 | 
			
		||||
        shader.set_uniform("percent_outline_radius", 0.01f * static_cast<float>(m_shaders_editor.percent_outline));
 | 
			
		||||
        shader.set_uniform("percent_center_radius", 0.01f * static_cast<float>(m_shaders_editor.percent_center));
 | 
			
		||||
        shader.set_uniform("percent_outline_radius", 0.01f * static_cast<float>(m_shaders_editor.points.percent_outline));
 | 
			
		||||
        shader.set_uniform("percent_center_radius", 0.01f * static_cast<float>(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<float, 4> 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<float>(m_shaders_editor.percent_outline));
 | 
			
		||||
                float radius = 0.5f * icon_size * (1.0f - 0.01f * static_cast<float>(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<float>(m_shaders_editor.percent_center);
 | 
			
		||||
                if (m_shaders_editor.points.percent_center > 0) {
 | 
			
		||||
                    radius = 0.5f * icon_size * 0.01f * static_cast<float>(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<unsigned int>(color)], text);
 | 
			
		||||
            add_item((m_shaders_editor.points.shader_version == 0) ? EItemType::Rect : EItemType::Circle, Options_Colors[static_cast<unsigned int>(color)], text);
 | 
			
		||||
#else
 | 
			
		||||
            add_item((buffer.shader == "options_110") ? EItemType::Rect : EItemType::Circle, Options_Colors[static_cast<unsigned int>(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<float>(cnv_size.get_width()), 0.5f * static_cast<float>(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<float>(cnv_size.get_width())) {
 | 
			
		||||
        ImGui::SetWindowPos(ImVec2(static_cast<float>(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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<size_t> 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<Path> paths;
 | 
			
		||||
        std::vector<RenderPath> 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<IBuffer> m_buffers{ static_cast<size_t>(GCodeProcessor::EMoveType::Extrude) };
 | 
			
		||||
    size_t m_vertices_count{ 0 };
 | 
			
		||||
    mutable std::vector<TBuffer> m_buffers{ static_cast<size_t>(GCodeProcessor::EMoveType::Extrude) };
 | 
			
		||||
    // bounding box of toolpaths
 | 
			
		||||
    BoundingBoxf3 m_paths_bounding_box;
 | 
			
		||||
    // bounding box of toolpaths + marker tools
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,15 +35,12 @@ std::pair<bool, std::string> 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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue