|
@@ -3,6 +3,8 @@
|
|
|
|
|
|
#if ENABLE_GCODE_VIEWER
|
|
|
#include "libslic3r/Print.hpp"
|
|
|
+#include "libslic3r/TriangleMesh.hpp"
|
|
|
+#include "libslic3r/Geometry.hpp"
|
|
|
#include "GUI_App.hpp"
|
|
|
#include "PresetBundle.hpp"
|
|
|
#include "Camera.hpp"
|
|
@@ -146,20 +148,160 @@ GCodeViewer::Color GCodeViewer::Extrusions::Range::get_color_at(float value) con
|
|
|
|
|
|
void GCodeViewer::SequentialView::Marker::init()
|
|
|
{
|
|
|
- if (m_initialized)
|
|
|
- return;
|
|
|
+ Pointf3s vertices;
|
|
|
+ std::vector<Vec3i> triangles;
|
|
|
+
|
|
|
+ // arrow tip
|
|
|
+ vertices.emplace_back(0.0, 0.0, 0.0);
|
|
|
+ vertices.emplace_back(0.5, -0.5, 1.0);
|
|
|
+ vertices.emplace_back(0.5, 0.5, 1.0);
|
|
|
+ vertices.emplace_back(-0.5, 0.5, 1.0);
|
|
|
+ vertices.emplace_back(-0.5, -0.5, 1.0);
|
|
|
+
|
|
|
+ triangles.emplace_back(0, 1, 4);
|
|
|
+ triangles.emplace_back(0, 2, 1);
|
|
|
+ triangles.emplace_back(0, 3, 2);
|
|
|
+ triangles.emplace_back(0, 4, 3);
|
|
|
+ triangles.emplace_back(1, 2, 4);
|
|
|
+ triangles.emplace_back(2, 3, 4);
|
|
|
+
|
|
|
+ // arrow stem
|
|
|
+ vertices.emplace_back(0.25, -0.25, 1.0);
|
|
|
+ vertices.emplace_back(0.25, 0.25, 1.0);
|
|
|
+ vertices.emplace_back(-0.25, 0.25, 1.0);
|
|
|
+ vertices.emplace_back(-0.25, -0.25, 1.0);
|
|
|
+ vertices.emplace_back(0.25, -0.25, 3.0);
|
|
|
+ vertices.emplace_back(0.25, 0.25, 3.0);
|
|
|
+ vertices.emplace_back(-0.25, 0.25, 3.0);
|
|
|
+ vertices.emplace_back(-0.25, -0.25, 3.0);
|
|
|
+
|
|
|
+ triangles.emplace_back(5, 9, 8);
|
|
|
+ triangles.emplace_back(8, 9, 12);
|
|
|
+ triangles.emplace_back(6, 10, 5);
|
|
|
+ triangles.emplace_back(5, 10, 9);
|
|
|
+ triangles.emplace_back(7, 11, 6);
|
|
|
+ triangles.emplace_back(6, 11, 10);
|
|
|
+ triangles.emplace_back(8, 12, 7);
|
|
|
+ triangles.emplace_back(7, 12, 11);
|
|
|
+ triangles.emplace_back(9, 10, 12);
|
|
|
+ triangles.emplace_back(12, 10, 11);
|
|
|
+
|
|
|
+ TriangleMesh mesh(vertices, triangles);
|
|
|
+ mesh.require_shared_vertices();
|
|
|
+
|
|
|
+ init_from_mesh(mesh);
|
|
|
+}
|
|
|
+
|
|
|
+bool GCodeViewer::SequentialView::Marker::init_from_mesh(const TriangleMesh& mesh)
|
|
|
+{
|
|
|
+ auto get_normal = [](const std::array<stl_vertex, 3>& triangle) {
|
|
|
+ return (triangle[1] - triangle[0]).cross(triangle[2] - triangle[0]).normalized();
|
|
|
+ };
|
|
|
+
|
|
|
+ reset();
|
|
|
|
|
|
+ // vertex data -> load from mesh
|
|
|
+ std::vector<float> vertices(6 * mesh.its.vertices.size());
|
|
|
+ for (size_t i = 0; i < mesh.its.vertices.size(); ++i) {
|
|
|
+ ::memcpy(static_cast<void*>(&vertices[i * 6]), static_cast<const void*>(mesh.its.vertices[i].data()), 3 * sizeof(float));
|
|
|
+ }
|
|
|
+
|
|
|
+ // indices/normals data -> load from mesh
|
|
|
+ std::vector<unsigned int> indices(3 * mesh.its.indices.size());
|
|
|
+ for (size_t i = 0; i < mesh.its.indices.size(); ++i) {
|
|
|
+ const stl_triangle_vertex_indices& triangle = mesh.its.indices[i];
|
|
|
+ for (size_t j = 0; j < 3; ++j) {
|
|
|
+ indices[i * 3 + j] = static_cast<unsigned int>(triangle[j]);
|
|
|
+ }
|
|
|
+ Vec3f normal = get_normal({ mesh.its.vertices[triangle[0]], mesh.its.vertices[triangle[1]], mesh.its.vertices[triangle[2]] });
|
|
|
+ ::memcpy(static_cast<void*>(&vertices[3 + static_cast<size_t>(triangle[0]) * 6]), static_cast<const void*>(normal.data()), 3 * sizeof(float));
|
|
|
+ ::memcpy(static_cast<void*>(&vertices[3 + static_cast<size_t>(triangle[1]) * 6]), static_cast<const void*>(normal.data()), 3 * sizeof(float));
|
|
|
+ ::memcpy(static_cast<void*>(&vertices[3 + static_cast<size_t>(triangle[2]) * 6]), static_cast<const void*>(normal.data()), 3 * sizeof(float));
|
|
|
+ }
|
|
|
+
|
|
|
+ m_indices_count = static_cast<unsigned int>(indices.size());
|
|
|
+
|
|
|
+ // vertex data -> send to gpu
|
|
|
+ glsafe(::glGenBuffers(1, &m_vbo_id));
|
|
|
+ glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id));
|
|
|
+ glsafe(::glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW));
|
|
|
+ glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
|
|
+
|
|
|
+ // indices data -> send to gpu
|
|
|
+ glsafe(::glGenBuffers(1, &m_ibo_id));
|
|
|
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo_id));
|
|
|
+ glsafe(::glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW));
|
|
|
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
|
|
+
|
|
|
+ return init_shader();
|
|
|
}
|
|
|
|
|
|
void GCodeViewer::SequentialView::Marker::render() const
|
|
|
{
|
|
|
- if (!m_initialized)
|
|
|
+ if (!m_visible || !m_shader.is_initialized())
|
|
|
return;
|
|
|
|
|
|
+ glsafe(::glEnable(GL_BLEND));
|
|
|
+ glsafe(::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
|
|
+
|
|
|
+ m_shader.start_using();
|
|
|
+ GLint color_id = ::glGetUniformLocation(m_shader.get_shader_program_id(), "uniform_color");
|
|
|
+ if (color_id >= 0)
|
|
|
+ glsafe(::glUniform4fv(color_id, 1, (const GLfloat*)m_color.data()));
|
|
|
+
|
|
|
+ glsafe(::glBindBuffer(GL_ARRAY_BUFFER, m_vbo_id));
|
|
|
+ glsafe(::glVertexPointer(3, GL_FLOAT, 6 * sizeof(float), (const void*)0));
|
|
|
+ glsafe(::glNormalPointer(GL_FLOAT, 6 * sizeof(float), (const void*)(3 * sizeof(float))));
|
|
|
+
|
|
|
+ glsafe(::glEnableClientState(GL_VERTEX_ARRAY));
|
|
|
+ glsafe(::glEnableClientState(GL_NORMAL_ARRAY));
|
|
|
+
|
|
|
+ glsafe(::glPushMatrix());
|
|
|
+ glsafe(::glMultMatrixf(m_world_transform.data()));
|
|
|
+
|
|
|
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo_id));
|
|
|
+ glsafe(::glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(m_indices_count), GL_UNSIGNED_INT, (const void*)0));
|
|
|
+ glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
|
|
|
+
|
|
|
+ glsafe(::glPopMatrix());
|
|
|
+
|
|
|
+ glsafe(::glDisableClientState(GL_NORMAL_ARRAY));
|
|
|
+ glsafe(::glDisableClientState(GL_VERTEX_ARRAY));
|
|
|
+
|
|
|
+ glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
|
|
|
+
|
|
|
+ m_shader.stop_using();
|
|
|
|
|
|
+ glsafe(::glDisable(GL_BLEND));
|
|
|
}
|
|
|
|
|
|
-const std::vector<GCodeViewer::Color> GCodeViewer::Extrusion_Role_Colors{ {
|
|
|
+void GCodeViewer::SequentialView::Marker::reset()
|
|
|
+{
|
|
|
+ // release gpu memory
|
|
|
+ if (m_ibo_id > 0) {
|
|
|
+ glsafe(::glDeleteBuffers(1, &m_ibo_id));
|
|
|
+ m_ibo_id = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (m_vbo_id > 0) {
|
|
|
+ glsafe(::glDeleteBuffers(1, &m_vbo_id));
|
|
|
+ m_vbo_id = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ m_indices_count = 0;
|
|
|
+}
|
|
|
+
|
|
|
+bool GCodeViewer::SequentialView::Marker::init_shader()
|
|
|
+{
|
|
|
+ if (!m_shader.init("gouraud_light.vs", "gouraud_light.fs")) {
|
|
|
+ BOOST_LOG_TRIVIAL(error) << "Unable to initialize gouraud_light shader: please, check that the files gouraud_light.vs and gouraud_light.fs are available";
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+const std::vector<GCodeViewer::Color> GCodeViewer::Extrusion_Role_Colors {{
|
|
|
{ 0.50f, 0.50f, 0.50f }, // erNone
|
|
|
{ 1.00f, 1.00f, 0.40f }, // erPerimeter
|
|
|
{ 1.00f, 0.65f, 0.00f }, // erExternalPerimeter
|
|
@@ -178,13 +320,13 @@ const std::vector<GCodeViewer::Color> GCodeViewer::Extrusion_Role_Colors{ {
|
|
|
{ 0.00f, 0.00f, 0.00f } // erMixed
|
|
|
}};
|
|
|
|
|
|
-const std::vector<GCodeViewer::Color> GCodeViewer::Travel_Colors{ {
|
|
|
+const std::vector<GCodeViewer::Color> GCodeViewer::Travel_Colors {{
|
|
|
{ 0.0f, 0.0f, 0.5f }, // Move
|
|
|
{ 0.0f, 0.5f, 0.0f }, // Extrude
|
|
|
{ 0.5f, 0.0f, 0.0f } // Retract
|
|
|
}};
|
|
|
|
|
|
-const std::vector<GCodeViewer::Color> GCodeViewer::Range_Colors{ {
|
|
|
+const std::vector<GCodeViewer::Color> GCodeViewer::Range_Colors {{
|
|
|
{ 0.043f, 0.173f, 0.478f }, // bluish
|
|
|
{ 0.075f, 0.349f, 0.522f },
|
|
|
{ 0.110f, 0.533f, 0.569f },
|
|
@@ -292,10 +434,13 @@ void GCodeViewer::render() const
|
|
|
m_statistics.reset_opengl();
|
|
|
#endif // ENABLE_GCODE_VIEWER_STATISTICS
|
|
|
|
|
|
+ if (m_roles.empty())
|
|
|
+ return;
|
|
|
+
|
|
|
glsafe(::glEnable(GL_DEPTH_TEST));
|
|
|
render_toolpaths();
|
|
|
- if (m_sequential_view.marker.visible)
|
|
|
- m_sequential_view.marker.render();
|
|
|
+ m_sequential_view.marker.set_world_transform(Geometry::assemble_transform(m_sequential_view.current_position.cast<double>() + 0.5 * Vec3d::UnitZ(), { 0.0, 0.0, 0.0 }, { 4.0, 4.0, 4.0 }, { 1.0, 1.0, 1.0 }).cast<float>());
|
|
|
+ m_sequential_view.marker.render();
|
|
|
render_shells();
|
|
|
render_legend();
|
|
|
render_sequential_bar();
|
|
@@ -332,7 +477,8 @@ unsigned int GCodeViewer::get_options_visibility_flags() const
|
|
|
flags = set_flag(flags, 5, is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Pause_Print));
|
|
|
flags = set_flag(flags, 6, is_toolpath_move_type_visible(GCodeProcessor::EMoveType::Custom_GCode));
|
|
|
flags = set_flag(flags, 7, m_shells.visible);
|
|
|
- flags = set_flag(flags, 8, is_legend_enabled());
|
|
|
+ flags = set_flag(flags, 8, m_sequential_view.marker.is_visible());
|
|
|
+ flags = set_flag(flags, 9, is_legend_enabled());
|
|
|
return flags;
|
|
|
}
|
|
|
|
|
@@ -350,7 +496,8 @@ void GCodeViewer::set_options_visibility_from_flags(unsigned int flags)
|
|
|
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Pause_Print, is_flag_set(5));
|
|
|
set_toolpath_move_type_visible(GCodeProcessor::EMoveType::Custom_GCode, is_flag_set(6));
|
|
|
m_shells.visible = is_flag_set(7);
|
|
|
- enable_legend(is_flag_set(8));
|
|
|
+ m_sequential_view.marker.set_visible(is_flag_set(8));
|
|
|
+ enable_legend(is_flag_set(9));
|
|
|
}
|
|
|
|
|
|
bool GCodeViewer::init_shaders()
|
|
@@ -706,7 +853,7 @@ void GCodeViewer::render_toolpaths() const
|
|
|
{
|
|
|
auto set_color = [](GLint current_program_id, const Color& color) {
|
|
|
if (current_program_id > 0) {
|
|
|
- GLint color_id = (current_program_id > 0) ? ::glGetUniformLocation(current_program_id, "uniform_color") : -1;
|
|
|
+ GLint color_id = ::glGetUniformLocation(current_program_id, "uniform_color");
|
|
|
if (color_id >= 0) {
|
|
|
glsafe(::glUniform3fv(color_id, 1, (const GLfloat*)color.data()));
|
|
|
return;
|
|
@@ -737,10 +884,7 @@ void GCodeViewer::render_toolpaths() const
|
|
|
GCodeProcessor::EMoveType type = buffer_type(i);
|
|
|
|
|
|
buffer.shader.start_using();
|
|
|
-
|
|
|
- GLint current_program_id;
|
|
|
- glsafe(::glGetIntegerv(GL_CURRENT_PROGRAM, ¤t_program_id));
|
|
|
-
|
|
|
+
|
|
|
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer.ibo_id));
|
|
|
|
|
|
switch (type)
|
|
@@ -748,7 +892,7 @@ void GCodeViewer::render_toolpaths() const
|
|
|
case GCodeProcessor::EMoveType::Tool_change:
|
|
|
{
|
|
|
Color color = { 1.0f, 1.0f, 1.0f };
|
|
|
- set_color(current_program_id, color);
|
|
|
+ set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), color);
|
|
|
for (const RenderPath& path : buffer.render_paths)
|
|
|
{
|
|
|
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
|
@@ -764,7 +908,7 @@ void GCodeViewer::render_toolpaths() const
|
|
|
case GCodeProcessor::EMoveType::Color_change:
|
|
|
{
|
|
|
Color color = { 1.0f, 0.0f, 0.0f };
|
|
|
- set_color(current_program_id, color);
|
|
|
+ set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), color);
|
|
|
for (const RenderPath& path : buffer.render_paths)
|
|
|
{
|
|
|
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
|
@@ -780,7 +924,7 @@ void GCodeViewer::render_toolpaths() const
|
|
|
case GCodeProcessor::EMoveType::Pause_Print:
|
|
|
{
|
|
|
Color color = { 0.0f, 1.0f, 0.0f };
|
|
|
- set_color(current_program_id, color);
|
|
|
+ set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), color);
|
|
|
for (const RenderPath& path : buffer.render_paths)
|
|
|
{
|
|
|
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
|
@@ -796,7 +940,7 @@ void GCodeViewer::render_toolpaths() const
|
|
|
case GCodeProcessor::EMoveType::Custom_GCode:
|
|
|
{
|
|
|
Color color = { 0.0f, 0.0f, 1.0f };
|
|
|
- set_color(current_program_id, color);
|
|
|
+ set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), color);
|
|
|
for (const RenderPath& path : buffer.render_paths)
|
|
|
{
|
|
|
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
|
@@ -812,7 +956,7 @@ void GCodeViewer::render_toolpaths() const
|
|
|
case GCodeProcessor::EMoveType::Retract:
|
|
|
{
|
|
|
Color color = { 1.0f, 0.0f, 1.0f };
|
|
|
- set_color(current_program_id, color);
|
|
|
+ set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), color);
|
|
|
for (const RenderPath& path : buffer.render_paths)
|
|
|
{
|
|
|
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
|
@@ -828,7 +972,7 @@ void GCodeViewer::render_toolpaths() const
|
|
|
case GCodeProcessor::EMoveType::Unretract:
|
|
|
{
|
|
|
Color color = { 0.0f, 1.0f, 1.0f };
|
|
|
- set_color(current_program_id, color);
|
|
|
+ set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), color);
|
|
|
for (const RenderPath& path : buffer.render_paths)
|
|
|
{
|
|
|
glsafe(::glEnable(GL_PROGRAM_POINT_SIZE));
|
|
@@ -845,7 +989,7 @@ void GCodeViewer::render_toolpaths() const
|
|
|
{
|
|
|
for (const RenderPath& path : buffer.render_paths)
|
|
|
{
|
|
|
- set_color(current_program_id, path.color);
|
|
|
+ set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), 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()));
|
|
|
#if ENABLE_GCODE_VIEWER_STATISTICS
|
|
|
++m_statistics.gl_multi_line_strip_calls_count;
|
|
@@ -858,7 +1002,7 @@ void GCodeViewer::render_toolpaths() const
|
|
|
{
|
|
|
for (const RenderPath& path : buffer.render_paths)
|
|
|
{
|
|
|
- set_color(current_program_id, path.color);
|
|
|
+ set_color(static_cast<GLint>(buffer.shader.get_shader_program_id()), 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()));
|
|
|
#if ENABLE_GCODE_VIEWER_STATISTICS
|
|
|
++m_statistics.gl_multi_line_strip_calls_count;
|
|
@@ -897,7 +1041,7 @@ void GCodeViewer::render_legend() const
|
|
|
static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
|
|
|
static const ImU32 ICON_BORDER_COLOR = ImGui::GetColorU32(ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
|
|
|
|
|
- if (!m_legend_enabled || m_roles.empty())
|
|
|
+ if (!m_legend_enabled)
|
|
|
return;
|
|
|
|
|
|
ImGuiWrapper& imgui = *wxGetApp().imgui();
|
|
@@ -1130,9 +1274,6 @@ void GCodeViewer::render_sequential_bar() const
|
|
|
refresh_render_paths(true);
|
|
|
};
|
|
|
|
|
|
- if (m_roles.empty())
|
|
|
- return;
|
|
|
-
|
|
|
if (m_sequential_view.last <= m_sequential_view.first)
|
|
|
return;
|
|
|
|
|
@@ -1204,9 +1345,6 @@ void GCodeViewer::render_sequential_bar() const
|
|
|
ImGui::SameLine();
|
|
|
imgui.text(std::to_string(i_max));
|
|
|
|
|
|
- ImGui::Separator();
|
|
|
- ImGui::Checkbox(I18N::translate_utf8(L("Show marker")).c_str(), &m_sequential_view.marker.visible);
|
|
|
-
|
|
|
imgui.end();
|
|
|
ImGui::PopStyleVar();
|
|
|
}
|
|
@@ -1217,9 +1355,6 @@ void GCodeViewer::render_statistics() const
|
|
|
static const ImVec4 ORANGE(1.0f, 0.49f, 0.22f, 1.0f);
|
|
|
static const float offset = 250.0f;
|
|
|
|
|
|
- if (m_roles.empty())
|
|
|
- return;
|
|
|
-
|
|
|
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);
|