Browse Source

GCodeViewer -> Prototype for tool marker

enricoturri1966 4 years ago
parent
commit
c02a77d942

+ 11 - 0
resources/shaders/gouraud_light.fs

@@ -0,0 +1,11 @@
+#version 110
+
+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);
+}

+ 38 - 0
resources/shaders/gouraud_light.vs

@@ -0,0 +1,38 @@
+#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;
+    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).
+    NdotL = max(dot(normal, LIGHT_FRONT_DIR), 0.0);
+    intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
+
+    gl_Position = ftransform();
+}

+ 168 - 33
src/slic3r/GUI/GCodeViewer.cpp

@@ -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, &current_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);

+ 25 - 8
src/slic3r/GUI/GCodeViewer.hpp

@@ -9,7 +9,10 @@
 #include <float.h>
 
 namespace Slic3r {
+
 class Print;
+class TriangleMesh;
+
 namespace GUI {
 
 class GCodeViewer
@@ -73,8 +76,8 @@ class GCodeViewer
     struct IBuffer
     {
         unsigned int ibo_id{ 0 };
-        Shader shader;
         size_t indices_count{ 0 };
+        Shader shader;
         std::vector<Path> paths;
         std::vector<RenderPath> render_paths;
         bool visible{ false };
@@ -147,19 +150,33 @@ class GCodeViewer
 
     struct SequentialView
     {
-        struct Marker
+        class Marker
         {
-        private:
-            bool m_initialized{ false };
+            unsigned int m_vbo_id{ 0 };
+            unsigned int m_ibo_id{ 0 };
+            size_t m_indices_count{ 0 };
+            Transform3f m_world_transform;
+            std::array<float, 4> m_color{ 1.0f, 1.0f, 1.0f, 1.0f };
+            bool m_visible{ false };
+            Shader m_shader;
 
         public:
-            unsigned int vbo_id{ 0 };
-            unsigned int ibo_id{ 0 };
-            bool visible{ false };
-            Shader shader;
+            ~Marker() { reset(); }
 
             void init();
+            bool init_from_mesh(const TriangleMesh& mesh);
+
+            void set_world_transform(const Transform3f& transform) { m_world_transform = transform; }
+
+            void set_color(const std::array<float, 4>& color) { m_color = color; }
+
+            bool is_visible() const { return m_visible; }
+            void set_visible(bool visible) { m_visible = visible; }
             void render() const;
+            void reset();
+
+        private:
+            bool init_shader();
         };
 
         unsigned int first{ 0 };

+ 2 - 1
src/slic3r/GUI/GUI_Preview.cpp

@@ -298,8 +298,9 @@ bool Preview::init(wxWindow* parent, Model* model)
         _L("Pause prints") + "|0|" +
         _L("Custom GCodes") + "|0|" +
         _L("Shells") + "|0|" +
+        _L("Tool marker") + "|1|" +
         _L("Legend") + "|1"
-    );
+);
     Slic3r::GUI::create_combochecklist(m_combochecklist_options, GUI::into_u8(_L("Options")), options_items);
 #else
     m_checkbox_travel = new wxCheckBox(this, wxID_ANY, _(L("Travel")));