Added class GCodeViewer -> basic render of gcode toolpaths using dedicated shaders
This commit is contained in:
parent
4df141815b
commit
c3eb65c461
18 changed files with 652 additions and 13 deletions
45
resources/shaders/extrusions.fs
Normal file
45
resources/shaders/extrusions.fs
Normal file
|
@ -0,0 +1,45 @@
|
|||
#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 vec4 uniform_color;
|
||||
|
||||
varying vec3 eye_position;
|
||||
varying vec3 eye_normal;
|
||||
//varying float world_normal_z;
|
||||
|
||||
// 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;
|
||||
|
||||
// // darkens fragments whose normal points downward
|
||||
// if (world_normal_z < 0.0)
|
||||
// intensity.x *= (1.0 + world_normal_z * (1.0 - INTENSITY_AMBIENT));
|
||||
|
||||
gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + uniform_color.rgb * intensity.x, uniform_color.a);
|
||||
}
|
15
resources/shaders/extrusions.vs
Normal file
15
resources/shaders/extrusions.vs
Normal file
|
@ -0,0 +1,15 @@
|
|||
#version 110
|
||||
|
||||
varying vec3 eye_position;
|
||||
varying vec3 eye_normal;
|
||||
//// world z component of the normal used to darken the lower side of the toolpaths
|
||||
//varying float world_normal_z;
|
||||
|
||||
void main()
|
||||
{
|
||||
eye_position = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||
eye_normal = gl_NormalMatrix * vec3(0.0, 0.0, 1.0);
|
||||
// eye_normal = gl_NormalMatrix * gl_Normal;
|
||||
// world_normal_z = gl_Normal.z;
|
||||
gl_Position = ftransform();
|
||||
}
|
45
resources/shaders/retractions.fs
Normal file
45
resources/shaders/retractions.fs
Normal file
|
@ -0,0 +1,45 @@
|
|||
#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 vec4 uniform_color;
|
||||
|
||||
varying vec3 eye_position;
|
||||
varying vec3 eye_normal;
|
||||
//varying float world_normal_z;
|
||||
|
||||
// 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;
|
||||
|
||||
// // darkens fragments whose normal points downward
|
||||
// if (world_normal_z < 0.0)
|
||||
// intensity.x *= (1.0 + world_normal_z * (1.0 - INTENSITY_AMBIENT));
|
||||
|
||||
gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + uniform_color.rgb * intensity.x, uniform_color.a);
|
||||
}
|
15
resources/shaders/retractions.vs
Normal file
15
resources/shaders/retractions.vs
Normal file
|
@ -0,0 +1,15 @@
|
|||
#version 110
|
||||
|
||||
varying vec3 eye_position;
|
||||
varying vec3 eye_normal;
|
||||
//// world z component of the normal used to darken the lower side of the toolpaths
|
||||
//varying float world_normal_z;
|
||||
|
||||
void main()
|
||||
{
|
||||
eye_position = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||
eye_normal = gl_NormalMatrix * vec3(0.0, 0.0, 1.0);
|
||||
// eye_normal = gl_NormalMatrix * gl_Normal;
|
||||
// world_normal_z = gl_Normal.z;
|
||||
gl_Position = ftransform();
|
||||
}
|
45
resources/shaders/toolchanges.fs
Normal file
45
resources/shaders/toolchanges.fs
Normal file
|
@ -0,0 +1,45 @@
|
|||
#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 vec4 uniform_color;
|
||||
|
||||
varying vec3 eye_position;
|
||||
varying vec3 eye_normal;
|
||||
//varying float world_normal_z;
|
||||
|
||||
// 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;
|
||||
|
||||
// // darkens fragments whose normal points downward
|
||||
// if (world_normal_z < 0.0)
|
||||
// intensity.x *= (1.0 + world_normal_z * (1.0 - INTENSITY_AMBIENT));
|
||||
|
||||
gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + uniform_color.rgb * intensity.x, uniform_color.a);
|
||||
}
|
15
resources/shaders/toolchanges.vs
Normal file
15
resources/shaders/toolchanges.vs
Normal file
|
@ -0,0 +1,15 @@
|
|||
#version 110
|
||||
|
||||
varying vec3 eye_position;
|
||||
varying vec3 eye_normal;
|
||||
//// world z component of the normal used to darken the lower side of the toolpaths
|
||||
//varying float world_normal_z;
|
||||
|
||||
void main()
|
||||
{
|
||||
eye_position = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||
eye_normal = gl_NormalMatrix * vec3(0.0, 0.0, 1.0);
|
||||
// eye_normal = gl_NormalMatrix * gl_Normal;
|
||||
// world_normal_z = gl_Normal.z;
|
||||
gl_Position = ftransform();
|
||||
}
|
45
resources/shaders/travels.fs
Normal file
45
resources/shaders/travels.fs
Normal file
|
@ -0,0 +1,45 @@
|
|||
#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 vec4 uniform_color;
|
||||
|
||||
varying vec3 eye_position;
|
||||
varying vec3 eye_normal;
|
||||
//varying float world_normal_z;
|
||||
|
||||
// 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;
|
||||
|
||||
// // darkens fragments whose normal points downward
|
||||
// if (world_normal_z < 0.0)
|
||||
// intensity.x *= (1.0 + world_normal_z * (1.0 - INTENSITY_AMBIENT));
|
||||
|
||||
gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + uniform_color.rgb * intensity.x, uniform_color.a);
|
||||
}
|
15
resources/shaders/travels.vs
Normal file
15
resources/shaders/travels.vs
Normal file
|
@ -0,0 +1,15 @@
|
|||
#version 110
|
||||
|
||||
varying vec3 eye_position;
|
||||
varying vec3 eye_normal;
|
||||
//// world z component of the normal used to darken the lower side of the toolpaths
|
||||
//varying float world_normal_z;
|
||||
|
||||
void main()
|
||||
{
|
||||
eye_position = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||
eye_normal = gl_NormalMatrix * vec3(0.0, 0.0, 1.0);
|
||||
// eye_normal = gl_NormalMatrix * gl_Normal;
|
||||
// world_normal_z = gl_Normal.z;
|
||||
gl_Position = ftransform();
|
||||
}
|
45
resources/shaders/unretractions.fs
Normal file
45
resources/shaders/unretractions.fs
Normal file
|
@ -0,0 +1,45 @@
|
|||
#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 vec4 uniform_color;
|
||||
|
||||
varying vec3 eye_position;
|
||||
varying vec3 eye_normal;
|
||||
//varying float world_normal_z;
|
||||
|
||||
// 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;
|
||||
|
||||
// // darkens fragments whose normal points downward
|
||||
// if (world_normal_z < 0.0)
|
||||
// intensity.x *= (1.0 + world_normal_z * (1.0 - INTENSITY_AMBIENT));
|
||||
|
||||
gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + uniform_color.rgb * intensity.x, uniform_color.a);
|
||||
}
|
15
resources/shaders/unretractions.vs
Normal file
15
resources/shaders/unretractions.vs
Normal file
|
@ -0,0 +1,15 @@
|
|||
#version 110
|
||||
|
||||
varying vec3 eye_position;
|
||||
varying vec3 eye_normal;
|
||||
//// world z component of the normal used to darken the lower side of the toolpaths
|
||||
//varying float world_normal_z;
|
||||
|
||||
void main()
|
||||
{
|
||||
eye_position = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||
eye_normal = gl_NormalMatrix * vec3(0.0, 0.0, 1.0);
|
||||
// eye_normal = gl_NormalMatrix * gl_Normal;
|
||||
// world_normal_z = gl_Normal.z;
|
||||
gl_Position = ftransform();
|
||||
}
|
|
@ -38,6 +38,8 @@ void GCodeProcessor::CpColor::reset()
|
|||
current = 0;
|
||||
}
|
||||
|
||||
unsigned int GCodeProcessor::Result::id = 0;
|
||||
|
||||
void GCodeProcessor::apply_config(const PrintConfig& config)
|
||||
{
|
||||
m_parser.apply_config(config);
|
||||
|
|
|
@ -39,17 +39,6 @@ namespace Slic3r {
|
|||
Relative
|
||||
};
|
||||
|
||||
enum class EMoveType : unsigned char
|
||||
{
|
||||
Noop,
|
||||
Retract,
|
||||
Unretract,
|
||||
Tool_change,
|
||||
Travel,
|
||||
Extrude,
|
||||
Num_Types
|
||||
};
|
||||
|
||||
struct CachedPosition
|
||||
{
|
||||
AxisCoords position; // mm
|
||||
|
@ -67,6 +56,17 @@ namespace Slic3r {
|
|||
};
|
||||
|
||||
public:
|
||||
enum class EMoveType : unsigned char
|
||||
{
|
||||
Noop,
|
||||
Retract,
|
||||
Unretract,
|
||||
Tool_change,
|
||||
Travel,
|
||||
Extrude,
|
||||
Count
|
||||
};
|
||||
|
||||
struct MoveVertex
|
||||
{
|
||||
EMoveType type{ EMoveType::Noop };
|
||||
|
@ -98,8 +98,9 @@ namespace Slic3r {
|
|||
|
||||
struct Result
|
||||
{
|
||||
static unsigned int id;
|
||||
std::vector<MoveVertex> moves;
|
||||
void reset() { moves = std::vector<MoveVertex>(); }
|
||||
void reset() { ++id; moves = std::vector<MoveVertex>(); }
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -56,6 +56,8 @@ set(SLIC3R_GUI_SOURCES
|
|||
GUI/GLTexture.cpp
|
||||
GUI/GLToolbar.hpp
|
||||
GUI/GLToolbar.cpp
|
||||
GUI/GCodeViewer.hpp
|
||||
GUI/GCodeViewer.cpp
|
||||
GUI/Preferences.cpp
|
||||
GUI/Preferences.hpp
|
||||
GUI/Preset.cpp
|
||||
|
|
242
src/slic3r/GUI/GCodeViewer.cpp
Normal file
242
src/slic3r/GUI/GCodeViewer.cpp
Normal file
|
@ -0,0 +1,242 @@
|
|||
#include "libslic3r/libslic3r.h"
|
||||
#include "GCodeViewer.hpp"
|
||||
#include "3DScene.hpp"
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <boost/log/trivial.hpp>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
static unsigned char buffer_id(GCodeProcessor::EMoveType type) {
|
||||
return static_cast<unsigned char>(type) - static_cast<unsigned char>(GCodeProcessor::EMoveType::Retract);
|
||||
}
|
||||
|
||||
static GCodeProcessor::EMoveType buffer_type(unsigned char id) {
|
||||
return static_cast<GCodeProcessor::EMoveType>(static_cast<unsigned char>(GCodeProcessor::EMoveType::Retract) + id);
|
||||
}
|
||||
|
||||
void GCodeViewer::generate(const GCodeProcessor::Result& gcode_result)
|
||||
{
|
||||
if (m_last_result_id == gcode_result.id)
|
||||
return;
|
||||
|
||||
m_last_result_id = gcode_result.id;
|
||||
|
||||
// release gpu memory, if used
|
||||
reset_buffers();
|
||||
|
||||
// convert data
|
||||
size_t vertices_count = gcode_result.moves.size();
|
||||
for (size_t i = 0; i < vertices_count; ++i)
|
||||
{
|
||||
// skip first vertex
|
||||
if (i == 0)
|
||||
continue;
|
||||
|
||||
const GCodeProcessor::MoveVertex& prev = gcode_result.moves[i - 1];
|
||||
const GCodeProcessor::MoveVertex& curr = gcode_result.moves[i];
|
||||
|
||||
Buffer& buffer = m_buffers[buffer_id(curr.type)];
|
||||
|
||||
switch (curr.type)
|
||||
{
|
||||
case GCodeProcessor::EMoveType::Tool_change:
|
||||
case GCodeProcessor::EMoveType::Retract:
|
||||
case GCodeProcessor::EMoveType::Unretract:
|
||||
{
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
buffer.data.insert(buffer.data.end(), curr.position[j]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GCodeProcessor::EMoveType::Extrude:
|
||||
case GCodeProcessor::EMoveType::Travel:
|
||||
{
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
buffer.data.insert(buffer.data.end(), prev.position[j]);
|
||||
}
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
buffer.data.insert(buffer.data.end(), curr.position[j]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// send data to gpu
|
||||
for (Buffer& buffer : m_buffers)
|
||||
{
|
||||
glsafe(::glGenBuffers(1, &buffer.vbo_id));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.vbo_id));
|
||||
glsafe(::glBufferData(GL_ARRAY_BUFFER, buffer.data.size() * sizeof(float), buffer.data.data(), GL_STATIC_DRAW));
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeViewer::render() const
|
||||
{
|
||||
auto set_color = [](GLint current_program_id, const std::array<float, 4>& color) {
|
||||
if (current_program_id > 0)
|
||||
{
|
||||
GLint color_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "uniform_color") : -1;
|
||||
if (color_id >= 0)
|
||||
{
|
||||
glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)color.data()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(error) << "Unable to find uniform_color uniform";
|
||||
};
|
||||
|
||||
unsigned char begin_id = buffer_id(GCodeProcessor::EMoveType::Retract);
|
||||
unsigned char end_id = buffer_id(GCodeProcessor::EMoveType::Count);
|
||||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
for (unsigned char i = begin_id; i < end_id; ++i)
|
||||
{
|
||||
const Buffer& buffer = m_buffers[i];
|
||||
if (buffer.vbo_id == 0)
|
||||
continue;
|
||||
|
||||
const Shader& shader = m_shaders[i];
|
||||
if (shader.is_initialized())
|
||||
{
|
||||
shader.start_using();
|
||||
|
||||
GLint current_program_id;
|
||||
glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id));
|
||||
|
||||
GCodeProcessor::EMoveType type = buffer_type(i);
|
||||
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, buffer.vbo_id));
|
||||
glsafe(::glVertexPointer(3, GL_FLOAT, Buffer::stride(type), (const void*)0));
|
||||
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GCodeProcessor::EMoveType::Tool_change:
|
||||
case GCodeProcessor::EMoveType::Retract:
|
||||
case GCodeProcessor::EMoveType::Unretract:
|
||||
{
|
||||
std::array<float, 4> color = { 0.0f, 1.0f, 0.0f, 1.0f };
|
||||
set_color(current_program_id, color);
|
||||
glsafe(::glDrawArrays(GL_POINTS, 0, (GLsizei)buffer.data.size() / Buffer::record_size(type)));
|
||||
break;
|
||||
}
|
||||
case GCodeProcessor::EMoveType::Extrude:
|
||||
{
|
||||
std::array<float, 4> color = { 1.0f, 0.0f, 0.0f, 1.0f };
|
||||
set_color(current_program_id, color);
|
||||
glsafe(::glDrawArrays(GL_LINES, 0, (GLsizei)buffer.data.size() / Buffer::record_size(type)));
|
||||
break;
|
||||
}
|
||||
case GCodeProcessor::EMoveType::Travel:
|
||||
{
|
||||
std::array<float, 4> color = { 1.0f, 1.0f, 0.0f, 1.0f };
|
||||
set_color(current_program_id, color);
|
||||
glsafe(::glDrawArrays(GL_LINES, 0, (GLsizei)buffer.data.size() / Buffer::record_size(type)));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
|
||||
|
||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
shader.stop_using();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GCodeViewer::init_shaders()
|
||||
{
|
||||
unsigned char begin_id = buffer_id(GCodeProcessor::EMoveType::Retract);
|
||||
unsigned char end_id = buffer_id(GCodeProcessor::EMoveType::Count);
|
||||
|
||||
for (unsigned char i = begin_id; i < end_id; ++i)
|
||||
{
|
||||
Shader& shader = m_shaders[i];
|
||||
std::string vertex_shader_src;
|
||||
std::string fragment_shader_src;
|
||||
GCodeProcessor::EMoveType type = buffer_type(i);
|
||||
switch (type)
|
||||
{
|
||||
case GCodeProcessor::EMoveType::Tool_change:
|
||||
{
|
||||
vertex_shader_src = "toolchanges.vs";
|
||||
fragment_shader_src = "toolchanges.fs";
|
||||
break;
|
||||
}
|
||||
case GCodeProcessor::EMoveType::Retract:
|
||||
{
|
||||
vertex_shader_src = "retractions.vs";
|
||||
fragment_shader_src = "retractions.fs";
|
||||
break;
|
||||
}
|
||||
case GCodeProcessor::EMoveType::Unretract:
|
||||
{
|
||||
vertex_shader_src = "unretractions.vs";
|
||||
fragment_shader_src = "unretractions.fs";
|
||||
break;
|
||||
}
|
||||
case GCodeProcessor::EMoveType::Extrude:
|
||||
{
|
||||
vertex_shader_src = "extrusions.vs";
|
||||
fragment_shader_src = "extrusions.fs";
|
||||
break;
|
||||
}
|
||||
case GCodeProcessor::EMoveType::Travel:
|
||||
{
|
||||
vertex_shader_src = "travels.vs";
|
||||
fragment_shader_src = "travels.fs";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!shader.init(vertex_shader_src, fragment_shader_src))
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << "Unable to initialize toolpaths shader: please, check that the files " << vertex_shader_src << " and " << fragment_shader_src << " are available";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GCodeViewer::reset_buffers()
|
||||
{
|
||||
for (Buffer& buffer : m_buffers)
|
||||
{
|
||||
// release gpu memory
|
||||
if (buffer.vbo_id > 0)
|
||||
glsafe(::glDeleteBuffers(1, &buffer.vbo_id));
|
||||
|
||||
// release cpu memory
|
||||
buffer.data = std::vector<float>();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // ENABLE_GCODE_VIEWER
|
63
src/slic3r/GUI/GCodeViewer.hpp
Normal file
63
src/slic3r/GUI/GCodeViewer.hpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
#ifndef slic3r_GCodeViewer_hpp_
|
||||
#define slic3r_GCodeViewer_hpp_
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
|
||||
#include "GLShader.hpp"
|
||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
||||
class GCodeViewer
|
||||
{
|
||||
struct Buffer
|
||||
{
|
||||
unsigned int vbo_id{ 0 };
|
||||
std::vector<float> data;
|
||||
|
||||
static size_t stride(GCodeProcessor::EMoveType type)
|
||||
{
|
||||
return 3 * sizeof(float);
|
||||
}
|
||||
|
||||
static size_t record_size(GCodeProcessor::EMoveType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case GCodeProcessor::EMoveType::Tool_change:
|
||||
case GCodeProcessor::EMoveType::Retract:
|
||||
case GCodeProcessor::EMoveType::Unretract: { return 3; }
|
||||
case GCodeProcessor::EMoveType::Extrude:
|
||||
case GCodeProcessor::EMoveType::Travel: { return 6; }
|
||||
default: { return 0; }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<Buffer> m_buffers{ static_cast<size_t>(GCodeProcessor::EMoveType::Extrude) };
|
||||
std::vector<Shader> m_shaders{ static_cast<size_t>(GCodeProcessor::EMoveType::Extrude) };
|
||||
unsigned int m_last_result_id{ 0 };
|
||||
|
||||
public:
|
||||
GCodeViewer() = default;
|
||||
~GCodeViewer() { reset_buffers(); }
|
||||
|
||||
bool init() { return init_shaders(); }
|
||||
void generate(const GCodeProcessor::Result& gcode_result);
|
||||
void render() const;
|
||||
|
||||
private:
|
||||
bool init_shaders();
|
||||
void reset_buffers();
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#endif // slic3r_GCodeViewer_hpp_
|
||||
|
|
@ -1678,6 +1678,14 @@ bool GLCanvas3D::init()
|
|||
return false;
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
if (!m_main_toolbar.is_enabled())
|
||||
{
|
||||
if (!m_gcode_viewer.init())
|
||||
return false;
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
// on linux the gl context is not valid until the canvas is not shown on screen
|
||||
// we defer the geometry finalization of volumes until the first call to render()
|
||||
m_volumes.finalize_geometry(true);
|
||||
|
@ -2109,6 +2117,9 @@ void GLCanvas3D::render()
|
|||
_render_background();
|
||||
|
||||
_render_objects();
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
_render_gcode();
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
_render_sla_slices();
|
||||
_render_selection();
|
||||
#if ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
|
@ -2783,6 +2794,8 @@ void GLCanvas3D::load_gcode_preview_2(const GCodeProcessor::Result& gcode_result
|
|||
out << v.to_string() << "\n";
|
||||
}
|
||||
out.close();
|
||||
|
||||
m_gcode_viewer.generate(gcode_result);
|
||||
#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
@ -5440,6 +5453,13 @@ void GLCanvas3D::_render_objects() const
|
|||
m_camera_clipping_plane = ClippingPlane::ClipsNothing();
|
||||
}
|
||||
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void GLCanvas3D::_render_gcode() const
|
||||
{
|
||||
m_gcode_viewer.render();
|
||||
}
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
void GLCanvas3D::_render_selection() const
|
||||
{
|
||||
float scale_factor = 1.0;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#endif // !ENABLE_NON_STATIC_CANVAS_MANAGER
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||
#include "GCodeViewer.hpp"
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
#include <float.h>
|
||||
|
@ -468,6 +469,10 @@ private:
|
|||
bool m_extra_frame_requested;
|
||||
|
||||
mutable GLVolumeCollection m_volumes;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
GCodeViewer m_gcode_viewer;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
|
||||
Selection m_selection;
|
||||
const DynamicPrintConfig* m_config;
|
||||
Model* m_model;
|
||||
|
@ -764,6 +769,9 @@ private:
|
|||
void _render_background() const;
|
||||
void _render_bed(float theta, bool show_axes) const;
|
||||
void _render_objects() const;
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
void _render_gcode() const;
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
void _render_selection() const;
|
||||
#if ENABLE_RENDER_SELECTION_CENTER
|
||||
void _render_selection_center() const;
|
||||
|
|
|
@ -946,9 +946,10 @@ void Preview::load_print_as_fff(bool keep_z_range)
|
|||
m_canvas->set_selected_extruder(0);
|
||||
if (gcode_preview_data_valid) {
|
||||
// Load the real G-code preview.
|
||||
m_canvas->load_gcode_preview(*m_gcode_preview_data, colors);
|
||||
#if ENABLE_GCODE_VIEWER
|
||||
m_canvas->load_gcode_preview_2(*m_gcode_result);
|
||||
#else
|
||||
m_canvas->load_gcode_preview(*m_gcode_preview_data, colors);
|
||||
#endif // ENABLE_GCODE_VIEWER
|
||||
m_loaded = true;
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue