GCodeViewer -> Toggle visibility of shells
This commit is contained in:
parent
bc05ab985c
commit
cc774dece7
13
resources/shaders/shells.fs
Normal file
13
resources/shaders/shells.fs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#version 110
|
||||||
|
|
||||||
|
const vec3 ZERO = vec3(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
|
uniform vec4 uniform_color;
|
||||||
|
|
||||||
|
// x = tainted, y = specular;
|
||||||
|
varying vec2 intensity;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_FragColor = vec4(vec3(intensity.y, intensity.y, intensity.y) + uniform_color.rgb * intensity.x, uniform_color.a);
|
||||||
|
}
|
42
resources/shaders/shells.vs
Normal file
42
resources/shaders/shells.vs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#version 110
|
||||||
|
|
||||||
|
#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.6985074, 0.1397015, 0.6985074);
|
||||||
|
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
|
||||||
|
|
||||||
|
#define INTENSITY_AMBIENT 0.3
|
||||||
|
|
||||||
|
// x = tainted, y = specular;
|
||||||
|
varying vec2 intensity;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// First transform the normal into camera space and normalize the result.
|
||||||
|
vec3 normal = normalize(gl_NormalMatrix * gl_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 = 0.0;
|
||||||
|
|
||||||
|
if (NdotL > 0.0)
|
||||||
|
{
|
||||||
|
vec3 position = (gl_ModelViewMatrix * gl_Vertex).xyz;
|
||||||
|
intensity.y += LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(position), reflect(-LIGHT_TOP_DIR, normal)), 0.0), LIGHT_TOP_SHININESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the same lighting calculation for the 2nd light source (no specular applied).
|
||||||
|
intensity.x += max(dot(normal, LIGHT_FRONT_DIR), 0.0) * LIGHT_FRONT_DIFFUSE;
|
||||||
|
|
||||||
|
gl_Position = ftransform();
|
||||||
|
}
|
@ -1,8 +1,11 @@
|
|||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
#include "GCodeViewer.hpp"
|
#include "GCodeViewer.hpp"
|
||||||
#include "3DScene.hpp"
|
|
||||||
|
|
||||||
#if ENABLE_GCODE_VIEWER
|
#if ENABLE_GCODE_VIEWER
|
||||||
|
#include "libslic3r/Print.hpp"
|
||||||
|
#include "GUI_App.hpp"
|
||||||
|
#include "PresetBundle.hpp"
|
||||||
|
#include "Camera.hpp"
|
||||||
|
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
@ -30,96 +33,21 @@ void GCodeViewer::Buffer::reset()
|
|||||||
|
|
||||||
// release cpu memory
|
// release cpu memory
|
||||||
data = std::vector<float>();
|
data = std::vector<float>();
|
||||||
|
data_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeViewer::generate(const GCodeProcessor::Result& gcode_result)
|
void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print& print, bool initialized)
|
||||||
{
|
{
|
||||||
if (m_last_result_id == gcode_result.id)
|
if (m_last_result_id == gcode_result.id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto start_time = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
m_last_result_id = gcode_result.id;
|
m_last_result_id = gcode_result.id;
|
||||||
|
|
||||||
// release gpu memory, if used
|
// release gpu memory, if used
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
// convert data
|
load_toolpaths(gcode_result);
|
||||||
size_t vertices_count = gcode_result.moves.size();
|
load_shells(print, initialized);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (curr.type == GCodeProcessor::EMoveType::Extrude)
|
|
||||||
m_layers_zs.emplace_back(curr.position[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(m_layers_zs.begin(), m_layers_zs.end());
|
|
||||||
|
|
||||||
// Replace intervals of layers with similar top positions with their average value.
|
|
||||||
int n = int(m_layers_zs.size());
|
|
||||||
int k = 0;
|
|
||||||
for (int i = 0; i < n;) {
|
|
||||||
int j = i + 1;
|
|
||||||
double zmax = m_layers_zs[i] + EPSILON;
|
|
||||||
for (; j < n && m_layers_zs[j] <= zmax; ++j);
|
|
||||||
m_layers_zs[k++] = (j > i + 1) ? (0.5 * (m_layers_zs[i] + m_layers_zs[j - 1])) : m_layers_zs[i];
|
|
||||||
i = j;
|
|
||||||
}
|
|
||||||
if (k < n)
|
|
||||||
m_layers_zs.erase(m_layers_zs.begin() + k, m_layers_zs.end());
|
|
||||||
|
|
||||||
// send data to gpu
|
|
||||||
for (Buffer& buffer : m_buffers)
|
|
||||||
{
|
|
||||||
if (buffer.data.size() > 0)
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto end_time = std::chrono::high_resolution_clock::now();
|
|
||||||
std::cout << "toolpaths generation time: " << std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count() << "ms \n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeViewer::reset()
|
void GCodeViewer::reset()
|
||||||
@ -129,106 +57,15 @@ void GCodeViewer::reset()
|
|||||||
buffer.reset();
|
buffer.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_shells.volumes.clear();
|
||||||
m_layers_zs = std::vector<double>();
|
m_layers_zs = std::vector<double>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GCodeViewer::render() const
|
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));
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||||
|
render_toolpaths();
|
||||||
for (unsigned char i = begin_id; i < end_id; ++i)
|
render_shells();
|
||||||
{
|
|
||||||
const Buffer& buffer = m_buffers[i];
|
|
||||||
if (buffer.vbo_id == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!buffer.visible)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (buffer.shader.is_initialized())
|
|
||||||
{
|
|
||||||
buffer.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::vertex_size_bytes(), (const void*)0));
|
|
||||||
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
|
||||||
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case GCodeProcessor::EMoveType::Tool_change:
|
|
||||||
{
|
|
||||||
std::array<float, 4> color = { 1.0f, 1.0f, 1.0f, 1.0f };
|
|
||||||
set_color(current_program_id, color);
|
|
||||||
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
|
||||||
glsafe(::glDrawArrays(GL_POINTS, 0, (GLsizei)buffer.data.size() / Buffer::vertex_size()));
|
|
||||||
glsafe(::glDisable(GL_PROGRAM_POINT_SIZE));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GCodeProcessor::EMoveType::Retract:
|
|
||||||
{
|
|
||||||
std::array<float, 4> color = { 1.0f, 0.0f, 1.0f, 1.0f };
|
|
||||||
set_color(current_program_id, color);
|
|
||||||
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
|
||||||
glsafe(::glDrawArrays(GL_POINTS, 0, (GLsizei)buffer.data.size() / Buffer::vertex_size()));
|
|
||||||
glsafe(::glDisable(GL_PROGRAM_POINT_SIZE));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case GCodeProcessor::EMoveType::Unretract:
|
|
||||||
{
|
|
||||||
std::array<float, 4> color = { 0.0f, 1.0f, 0.0f, 1.0f };
|
|
||||||
set_color(current_program_id, color);
|
|
||||||
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
|
||||||
glsafe(::glDrawArrays(GL_POINTS, 0, (GLsizei)buffer.data.size() / Buffer::vertex_size()));
|
|
||||||
glsafe(::glDisable(GL_PROGRAM_POINT_SIZE));
|
|
||||||
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::vertex_size()));
|
|
||||||
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::vertex_size()));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
|
|
||||||
|
|
||||||
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
|
||||||
buffer.shader.stop_using();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GCodeViewer::is_toolpath_visible(GCodeProcessor::EMoveType type) const
|
bool GCodeViewer::is_toolpath_visible(GCodeProcessor::EMoveType type) const
|
||||||
@ -300,9 +137,264 @@ bool GCodeViewer::init_shaders()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_shells.shader.init("shells.vs", "shells.fs"))
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Unable to initialize shells shader: please, check that the files shells.vs and shells.fs are available";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result)
|
||||||
|
{
|
||||||
|
auto start_time = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (curr.type == GCodeProcessor::EMoveType::Extrude)
|
||||||
|
m_layers_zs.emplace_back(curr.position[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(m_layers_zs.begin(), m_layers_zs.end());
|
||||||
|
|
||||||
|
// Replace intervals of layers with similar top positions with their average value.
|
||||||
|
int n = int(m_layers_zs.size());
|
||||||
|
int k = 0;
|
||||||
|
for (int i = 0; i < n;) {
|
||||||
|
int j = i + 1;
|
||||||
|
double zmax = m_layers_zs[i] + EPSILON;
|
||||||
|
for (; j < n && m_layers_zs[j] <= zmax; ++j);
|
||||||
|
m_layers_zs[k++] = (j > i + 1) ? (0.5 * (m_layers_zs[i] + m_layers_zs[j - 1])) : m_layers_zs[i];
|
||||||
|
i = j;
|
||||||
|
}
|
||||||
|
if (k < n)
|
||||||
|
m_layers_zs.erase(m_layers_zs.begin() + k, m_layers_zs.end());
|
||||||
|
|
||||||
|
// send data to gpu
|
||||||
|
for (Buffer& buffer : m_buffers)
|
||||||
|
{
|
||||||
|
buffer.data_size = buffer.data.size();
|
||||||
|
if (buffer.data_size > 0)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
buffer.data = std::vector<float>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto end_time = std::chrono::high_resolution_clock::now();
|
||||||
|
std::cout << "toolpaths generation time: " << std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count() << "ms \n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCodeViewer::load_shells(const Print& print, bool initialized)
|
||||||
|
{
|
||||||
|
if (print.objects().empty())
|
||||||
|
// no shells, return
|
||||||
|
return;
|
||||||
|
|
||||||
|
// adds objects' volumes
|
||||||
|
int object_id = 0;
|
||||||
|
for (const PrintObject* obj : print.objects())
|
||||||
|
{
|
||||||
|
const ModelObject* model_obj = obj->model_object();
|
||||||
|
|
||||||
|
std::vector<int> instance_ids(model_obj->instances.size());
|
||||||
|
for (int i = 0; i < (int)model_obj->instances.size(); ++i)
|
||||||
|
{
|
||||||
|
instance_ids[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_shells.volumes.load_object(model_obj, object_id, instance_ids, "object", initialized);
|
||||||
|
|
||||||
|
++object_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptFFF) {
|
||||||
|
// adds wipe tower's volume
|
||||||
|
double max_z = print.objects()[0]->model_object()->get_model()->bounding_box().max(2);
|
||||||
|
const PrintConfig& config = print.config();
|
||||||
|
size_t extruders_count = config.nozzle_diameter.size();
|
||||||
|
if ((extruders_count > 1) && config.wipe_tower && !config.complete_objects) {
|
||||||
|
|
||||||
|
const DynamicPrintConfig& print_config = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||||
|
double layer_height = print_config.opt_float("layer_height");
|
||||||
|
double first_layer_height = print_config.get_abs_value("first_layer_height", layer_height);
|
||||||
|
double nozzle_diameter = print.config().nozzle_diameter.values[0];
|
||||||
|
float depth = print.wipe_tower_data(extruders_count, first_layer_height, nozzle_diameter).depth;
|
||||||
|
float brim_width = print.wipe_tower_data(extruders_count, first_layer_height, nozzle_diameter).brim_width;
|
||||||
|
|
||||||
|
m_shells.volumes.load_wipe_tower_preview(1000, config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle,
|
||||||
|
!print.is_step_done(psWipeTower), brim_width, initialized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (GLVolume* volume : m_shells.volumes.volumes)
|
||||||
|
{
|
||||||
|
volume->zoom_to_volumes = false;
|
||||||
|
volume->color[3] = 0.25f;
|
||||||
|
volume->force_native_color = true;
|
||||||
|
volume->set_render_color();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCodeViewer::render_toolpaths() 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";
|
||||||
|
};
|
||||||
|
|
||||||
|
glsafe(::glCullFace(GL_BACK));
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
const Buffer& buffer = m_buffers[i];
|
||||||
|
if (buffer.vbo_id == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!buffer.visible)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (buffer.shader.is_initialized())
|
||||||
|
{
|
||||||
|
buffer.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::vertex_size_bytes(), (const void*)0));
|
||||||
|
glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case GCodeProcessor::EMoveType::Tool_change:
|
||||||
|
{
|
||||||
|
std::array<float, 4> color = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
|
set_color(current_program_id, color);
|
||||||
|
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
||||||
|
glsafe(::glDrawArrays(GL_POINTS, 0, (GLsizei)(buffer.data_size / Buffer::vertex_size())));
|
||||||
|
glsafe(::glDisable(GL_PROGRAM_POINT_SIZE));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GCodeProcessor::EMoveType::Retract:
|
||||||
|
{
|
||||||
|
std::array<float, 4> color = { 1.0f, 0.0f, 1.0f, 1.0f };
|
||||||
|
set_color(current_program_id, color);
|
||||||
|
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
||||||
|
glsafe(::glDrawArrays(GL_POINTS, 0, (GLsizei)(buffer.data_size / Buffer::vertex_size())));
|
||||||
|
glsafe(::glDisable(GL_PROGRAM_POINT_SIZE));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GCodeProcessor::EMoveType::Unretract:
|
||||||
|
{
|
||||||
|
std::array<float, 4> color = { 0.0f, 1.0f, 0.0f, 1.0f };
|
||||||
|
set_color(current_program_id, color);
|
||||||
|
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
||||||
|
glsafe(::glDrawArrays(GL_POINTS, 0, (GLsizei)(buffer.data_size / Buffer::vertex_size())));
|
||||||
|
glsafe(::glDisable(GL_PROGRAM_POINT_SIZE));
|
||||||
|
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::vertex_size())));
|
||||||
|
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::vertex_size())));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
|
||||||
|
|
||||||
|
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
||||||
|
buffer.shader.stop_using();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GCodeViewer::render_shells() const
|
||||||
|
{
|
||||||
|
if (!m_shells.visible || m_shells.volumes.empty() || !m_shells.shader.is_initialized())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// glsafe(::glDepthMask(GL_FALSE));
|
||||||
|
|
||||||
|
m_shells.shader.start_using();
|
||||||
|
m_shells.volumes.render(GLVolumeCollection::Transparent, true, wxGetApp().plater()->get_camera().get_view_matrix());
|
||||||
|
m_shells.shader.stop_using();
|
||||||
|
|
||||||
|
// glsafe(::glDepthMask(GL_TRUE));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
#if ENABLE_GCODE_VIEWER
|
#if ENABLE_GCODE_VIEWER
|
||||||
|
|
||||||
#include "GLShader.hpp"
|
#include "GLShader.hpp"
|
||||||
|
#include "3DScene.hpp"
|
||||||
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
#include "libslic3r/GCode/GCodeProcessor.hpp"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
class Print;
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
class GCodeViewer
|
class GCodeViewer
|
||||||
@ -18,26 +20,34 @@ class GCodeViewer
|
|||||||
unsigned int vbo_id{ 0 };
|
unsigned int vbo_id{ 0 };
|
||||||
Shader shader;
|
Shader shader;
|
||||||
std::vector<float> data;
|
std::vector<float> data;
|
||||||
|
size_t data_size{ 0 };
|
||||||
bool visible{ false };
|
bool visible{ false };
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
static size_t vertex_size() { return 3; }
|
static size_t vertex_size() { return 3; }
|
||||||
|
|
||||||
static size_t vertex_size_bytes() { return vertex_size() * sizeof(float); }
|
static size_t vertex_size_bytes() { return vertex_size() * sizeof(float); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Shells
|
||||||
|
{
|
||||||
|
GLVolumeCollection volumes;
|
||||||
|
bool visible{ false };
|
||||||
|
Shader shader;
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<Buffer> m_buffers{ static_cast<size_t>(GCodeProcessor::EMoveType::Extrude) };
|
std::vector<Buffer> m_buffers{ static_cast<size_t>(GCodeProcessor::EMoveType::Extrude) };
|
||||||
|
|
||||||
unsigned int m_last_result_id{ 0 };
|
unsigned int m_last_result_id{ 0 };
|
||||||
std::vector<double> m_layers_zs;
|
std::vector<double> m_layers_zs;
|
||||||
|
Shells m_shells;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GCodeViewer() = default;
|
GCodeViewer() = default;
|
||||||
~GCodeViewer() { reset(); }
|
~GCodeViewer() { reset(); }
|
||||||
|
|
||||||
bool init() { set_toolpath_visible(GCodeProcessor::EMoveType::Extrude, true); return init_shaders(); }
|
bool init() { set_toolpath_visible(GCodeProcessor::EMoveType::Extrude, true); return init_shaders(); }
|
||||||
void generate(const GCodeProcessor::Result& gcode_result);
|
void load(const GCodeProcessor::Result& gcode_result, const Print& print, bool initialized);
|
||||||
void reset();
|
void reset();
|
||||||
void render() const;
|
void render() const;
|
||||||
|
|
||||||
@ -46,8 +56,15 @@ public:
|
|||||||
bool is_toolpath_visible(GCodeProcessor::EMoveType type) const;
|
bool is_toolpath_visible(GCodeProcessor::EMoveType type) const;
|
||||||
void set_toolpath_visible(GCodeProcessor::EMoveType type, bool visible);
|
void set_toolpath_visible(GCodeProcessor::EMoveType type, bool visible);
|
||||||
|
|
||||||
|
bool are_shells_visible() const { return m_shells.visible; }
|
||||||
|
void set_shells_visible(bool visible) { m_shells.visible = visible; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool init_shaders();
|
bool init_shaders();
|
||||||
|
void load_toolpaths(const GCodeProcessor::Result& gcode_result);
|
||||||
|
void load_shells(const Print& print, bool initialized);
|
||||||
|
void render_toolpaths() const;
|
||||||
|
void render_shells() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
|
@ -2122,7 +2122,8 @@ void GLCanvas3D::render()
|
|||||||
|
|
||||||
_render_objects();
|
_render_objects();
|
||||||
#if ENABLE_GCODE_VIEWER
|
#if ENABLE_GCODE_VIEWER
|
||||||
_render_gcode();
|
if (!m_main_toolbar.is_enabled())
|
||||||
|
_render_gcode();
|
||||||
#endif // ENABLE_GCODE_VIEWER
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
_render_sla_slices();
|
_render_sla_slices();
|
||||||
_render_selection();
|
_render_selection();
|
||||||
@ -2318,6 +2319,11 @@ void GLCanvas3D::set_toolpath_visible(GCodeProcessor::EMoveType type, bool visib
|
|||||||
{
|
{
|
||||||
m_gcode_viewer.set_toolpath_visible(type, visible);
|
m_gcode_viewer.set_toolpath_visible(type, visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::set_shells_visible(bool visible)
|
||||||
|
{
|
||||||
|
m_gcode_viewer.set_shells_visible(visible);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
std::vector<double> GLCanvas3D::get_current_print_zs(bool active_only) const
|
std::vector<double> GLCanvas3D::get_current_print_zs(bool active_only) const
|
||||||
{
|
{
|
||||||
@ -2768,6 +2774,7 @@ static void reserve_new_volume_finalize_old_volume(GLVolume& vol_new, GLVolume&
|
|||||||
vol_old.finalize_geometry(gl_initialized);
|
vol_old.finalize_geometry(gl_initialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !ENABLE_GCODE_VIEWER
|
||||||
static void load_gcode_retractions(const GCodePreviewData::Retraction& retractions, GLCanvas3D::GCodePreviewVolumeIndex::EType extrusion_type, GLVolumeCollection &volumes, GLCanvas3D::GCodePreviewVolumeIndex &volume_index, bool gl_initialized)
|
static void load_gcode_retractions(const GCodePreviewData::Retraction& retractions, GLCanvas3D::GCodePreviewVolumeIndex::EType extrusion_type, GLVolumeCollection &volumes, GLCanvas3D::GCodePreviewVolumeIndex &volume_index, bool gl_initialized)
|
||||||
{
|
{
|
||||||
// nothing to render, return
|
// nothing to render, return
|
||||||
@ -2798,6 +2805,7 @@ static void load_gcode_retractions(const GCodePreviewData::Retraction& retractio
|
|||||||
}
|
}
|
||||||
volume->indexed_vertex_array.finalize_geometry(gl_initialized);
|
volume->indexed_vertex_array.finalize_geometry(gl_initialized);
|
||||||
}
|
}
|
||||||
|
#endif // !ENABLE_GCODE_VIEWER
|
||||||
|
|
||||||
#if ENABLE_GCODE_VIEWER
|
#if ENABLE_GCODE_VIEWER
|
||||||
void GLCanvas3D::load_gcode_preview_2(const GCodeProcessor::Result& gcode_result)
|
void GLCanvas3D::load_gcode_preview_2(const GCodeProcessor::Result& gcode_result)
|
||||||
@ -2817,11 +2825,12 @@ void GLCanvas3D::load_gcode_preview_2(const GCodeProcessor::Result& gcode_result
|
|||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_gcode_viewer.generate(gcode_result);
|
m_gcode_viewer.load(gcode_result , *this->fff_print(), m_initialized);
|
||||||
#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
#endif // ENABLE_GCODE_VIEWER_DEBUG_OUTPUT
|
||||||
}
|
}
|
||||||
#endif // ENABLE_GCODE_VIEWER
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
|
|
||||||
|
#if !ENABLE_GCODE_VIEWER
|
||||||
void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors)
|
void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors)
|
||||||
{
|
{
|
||||||
const Print *print = this->fff_print();
|
const Print *print = this->fff_print();
|
||||||
@ -2890,6 +2899,7 @@ void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const
|
|||||||
_generate_legend_texture(preview_data, tool_colors);
|
_generate_legend_texture(preview_data, tool_colors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // !ENABLE_GCODE_VIEWER
|
||||||
|
|
||||||
void GLCanvas3D::load_sla_preview()
|
void GLCanvas3D::load_sla_preview()
|
||||||
{
|
{
|
||||||
@ -6547,6 +6557,7 @@ static inline int hex_digit_to_int(const char c)
|
|||||||
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
|
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !ENABLE_GCODE_VIEWER
|
||||||
void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - start" << m_volumes.log_memory_info() << log_memory_info();
|
BOOST_LOG_TRIVIAL(debug) << "Loading G-code extrusion paths - start" << m_volumes.log_memory_info() << log_memory_info();
|
||||||
@ -6866,6 +6877,7 @@ void GLCanvas3D::_load_fff_shells()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // !ENABLE_GCODE_VIEWER
|
||||||
|
|
||||||
// While it looks like we can call
|
// While it looks like we can call
|
||||||
// this->reload_scene(true, true)
|
// this->reload_scene(true, true)
|
||||||
|
@ -642,6 +642,7 @@ public:
|
|||||||
#if ENABLE_GCODE_VIEWER
|
#if ENABLE_GCODE_VIEWER
|
||||||
const std::vector<double>& get_layers_zs() const;
|
const std::vector<double>& get_layers_zs() const;
|
||||||
void set_toolpath_visible(GCodeProcessor::EMoveType type, bool visible);
|
void set_toolpath_visible(GCodeProcessor::EMoveType type, bool visible);
|
||||||
|
void set_shells_visible(bool visible);
|
||||||
#else
|
#else
|
||||||
std::vector<double> get_current_print_zs(bool active_only) const;
|
std::vector<double> get_current_print_zs(bool active_only) const;
|
||||||
#endif // ENABLE_GCODE_VIEWER
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
@ -656,9 +657,9 @@ public:
|
|||||||
|
|
||||||
#if ENABLE_GCODE_VIEWER
|
#if ENABLE_GCODE_VIEWER
|
||||||
void load_gcode_preview_2(const GCodeProcessor::Result& gcode_result);
|
void load_gcode_preview_2(const GCodeProcessor::Result& gcode_result);
|
||||||
#endif // ENABLE_GCODE_VIEWER
|
#else
|
||||||
|
|
||||||
void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
|
void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
|
||||||
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
void load_sla_preview();
|
void load_sla_preview();
|
||||||
void load_preview(const std::vector<std::string>& str_tool_colors, const std::vector<CustomGCode::Item>& color_print_values);
|
void load_preview(const std::vector<std::string>& str_tool_colors, const std::vector<CustomGCode::Item>& color_print_values);
|
||||||
void bind_event_handlers();
|
void bind_event_handlers();
|
||||||
@ -833,12 +834,14 @@ private:
|
|||||||
// Create 3D thick extrusion lines for wipe tower extrusions
|
// Create 3D thick extrusion lines for wipe tower extrusions
|
||||||
void _load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors);
|
void _load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors);
|
||||||
|
|
||||||
|
#if !ENABLE_GCODE_VIEWER
|
||||||
// generates gcode extrusion paths geometry
|
// generates gcode extrusion paths geometry
|
||||||
void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||||
// generates gcode travel paths geometry
|
// generates gcode travel paths geometry
|
||||||
void _load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
void _load_gcode_travel_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||||
// generates objects and wipe tower geometry
|
// generates objects and wipe tower geometry
|
||||||
void _load_fff_shells();
|
void _load_fff_shells();
|
||||||
|
#endif // !ENABLE_GCODE_VIEWER
|
||||||
// Load SLA objects and support structures for objects, for which the slaposSliceSupports step has been finished.
|
// Load SLA objects and support structures for objects, for which the slaposSliceSupports step has been finished.
|
||||||
void _load_sla_shells();
|
void _load_sla_shells();
|
||||||
// sets gcode geometry visibility according to user selection
|
// sets gcode geometry visibility according to user selection
|
||||||
|
@ -650,7 +650,11 @@ void Preview::on_checkbox_unretractions(wxCommandEvent& evt)
|
|||||||
|
|
||||||
void Preview::on_checkbox_shells(wxCommandEvent& evt)
|
void Preview::on_checkbox_shells(wxCommandEvent& evt)
|
||||||
{
|
{
|
||||||
|
#if ENABLE_GCODE_VIEWER
|
||||||
|
m_canvas->set_shells_visible(m_checkbox_shells->IsChecked());
|
||||||
|
#else
|
||||||
m_gcode_preview_data->shell.is_visible = m_checkbox_shells->IsChecked();
|
m_gcode_preview_data->shell.is_visible = m_checkbox_shells->IsChecked();
|
||||||
|
#endif // ENABLE_GCODE_VIEWER
|
||||||
refresh_print();
|
refresh_print();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user