diff --git a/src/libvgcode/include/Viewer.hpp b/src/libvgcode/include/Viewer.hpp index a5aebe5640..e2f3214d56 100644 --- a/src/libvgcode/include/Viewer.hpp +++ b/src/libvgcode/include/Viewer.hpp @@ -24,9 +24,24 @@ public: Viewer& operator = (const Viewer& other) = delete; Viewer& operator = (Viewer&& other) = delete; + // + // Initialize the viewer. + // This method must be called after a valid OpenGL context has been already created + // and before to call any other method of the viewer. + // void init(); + // + // Release the resources used by the viewer. + // This method must be called before releasing the OpenGL context if the viewer + // destructor is called after releasing the OpenGL context. + // + void shutdown(); void reset(); void load(GCodeInputData&& gcode_data); + // + // Render the toolpaths according to the current settings, + // using the given camera matrices. + // void render(const Mat4x4& view_matrix, const Mat4x4& projection_matrix); EViewType get_view_type() const; diff --git a/src/libvgcode/src/CogMarker.cpp b/src/libvgcode/src/CogMarker.cpp index 489a680da8..19852cf378 100644 --- a/src/libvgcode/src/CogMarker.cpp +++ b/src/libvgcode/src/CogMarker.cpp @@ -14,16 +14,6 @@ namespace libvgcode { -CogMarker::~CogMarker() -{ - if (m_ibo_id != 0) - glsafe(glDeleteBuffers(1, &m_ibo_id)); - if (m_vbo_id != 0) - glsafe(glDeleteBuffers(1, &m_vbo_id)); - if (m_vao_id != 0) - glsafe(glDeleteVertexArrays(1, &m_vao_id)); -} - // Geometry: // sphere with 'resolution' sides, centered at (0.0, 0.0, 0.0) and radius equal to 'radius' void CogMarker::init(uint8_t resolution, float radius) @@ -122,6 +112,22 @@ void CogMarker::init(uint8_t resolution, float radius) glsafe(glBindVertexArray(curr_vertex_array)); } +void CogMarker::shutdown() +{ + 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; + } + if (m_vao_id != 0) { + glsafe(glDeleteVertexArrays(1, &m_vao_id)); + m_vao_id = 0; + } +} + void CogMarker::render() { if (m_vao_id == 0 || m_vbo_id == 0 || m_ibo_id == 0 || m_indices_count == 0) diff --git a/src/libvgcode/src/CogMarker.hpp b/src/libvgcode/src/CogMarker.hpp index 38a6d87f12..b7c9a19a09 100644 --- a/src/libvgcode/src/CogMarker.hpp +++ b/src/libvgcode/src/CogMarker.hpp @@ -15,16 +15,20 @@ class CogMarker { public: CogMarker() = default; - ~CogMarker(); + ~CogMarker() { shutdown(); } CogMarker(const CogMarker& other) = delete; CogMarker(CogMarker&& other) = delete; CogMarker& operator = (const CogMarker& other) = delete; CogMarker& operator = (CogMarker&& other) = delete; // - // Initialize geometry on gpu + // Initialize gpu buffers. // void init(uint8_t resolution, float radius); + // + // Release gpu buffers. + // + void shutdown(); void render(); // @@ -50,6 +54,9 @@ private: Vec3 m_total_position{ 0.0f, 0.0f, 0.0f }; uint16_t m_indices_count{ 0 }; + // + // gpu buffers ids. + // unsigned int m_vao_id{ 0 }; unsigned int m_vbo_id{ 0 }; unsigned int m_ibo_id{ 0 }; diff --git a/src/libvgcode/src/OptionTemplate.cpp b/src/libvgcode/src/OptionTemplate.cpp index 3c9b54373e..31e9e4670a 100644 --- a/src/libvgcode/src/OptionTemplate.cpp +++ b/src/libvgcode/src/OptionTemplate.cpp @@ -12,18 +12,6 @@ namespace libvgcode { -OptionTemplate::~OptionTemplate() -{ - if (m_bottom_vbo_id != 0) - glsafe(glDeleteBuffers(1, &m_bottom_vbo_id)); - if (m_bottom_vao_id != 0) - glsafe(glDeleteVertexArrays(1, &m_bottom_vao_id)); - if (m_top_vbo_id != 0) - glsafe(glDeleteBuffers(1, &m_top_vbo_id)); - if (m_top_vao_id != 0) - glsafe(glDeleteVertexArrays(1, &m_top_vao_id)); -} - // Geometry: // diamond with 'resolution' sides, centered at (0.0, 0.0, 0.0) // height and width of the diamond are equal to 1.0 @@ -95,6 +83,26 @@ void OptionTemplate::init(uint8_t resolution) glsafe(glBindVertexArray(curr_vertex_array)); } +void OptionTemplate::shutdown() +{ + if (m_bottom_vbo_id != 0) { + glsafe(glDeleteBuffers(1, &m_bottom_vbo_id)); + m_bottom_vbo_id = 0; + } + if (m_bottom_vao_id != 0) { + glsafe(glDeleteVertexArrays(1, &m_bottom_vao_id)); + m_bottom_vao_id = 0; + } + if (m_top_vbo_id != 0) { + glsafe(glDeleteBuffers(1, &m_top_vbo_id)); + m_top_vbo_id = 0; + } + if (m_top_vao_id != 0) { + glsafe(glDeleteVertexArrays(1, &m_top_vao_id)); + m_top_vao_id = 0; + } +} + void OptionTemplate::render(size_t count) { if (m_top_vao_id == 0 || m_top_vbo_id == 0 || m_bottom_vao_id == 0 || m_bottom_vbo_id == 0 || count == 0) diff --git a/src/libvgcode/src/OptionTemplate.hpp b/src/libvgcode/src/OptionTemplate.hpp index ebb2b2ca50..fbdf332e37 100644 --- a/src/libvgcode/src/OptionTemplate.hpp +++ b/src/libvgcode/src/OptionTemplate.hpp @@ -14,18 +14,28 @@ class OptionTemplate { public: OptionTemplate() = default; - ~OptionTemplate(); + ~OptionTemplate() { shutdown(); } OptionTemplate(const OptionTemplate& other) = delete; OptionTemplate(OptionTemplate&& other) = delete; OptionTemplate& operator = (const OptionTemplate& other) = delete; OptionTemplate& operator = (OptionTemplate&& other) = delete; + // + // Initialize gpu buffers. + // void init(uint8_t resolution); + // + // Release gpu buffers. + // + void shutdown(); void render(size_t count); private: uint8_t m_resolution{ 0 }; uint8_t m_vertices_count{ 0 }; + // + // gpu buffers ids. + // unsigned int m_top_vao_id{ 0 }; unsigned int m_top_vbo_id{ 0 }; unsigned int m_bottom_vao_id{ 0 }; diff --git a/src/libvgcode/src/SegmentTemplate.cpp b/src/libvgcode/src/SegmentTemplate.cpp index 34a9f54d07..7c80812705 100644 --- a/src/libvgcode/src/SegmentTemplate.cpp +++ b/src/libvgcode/src/SegmentTemplate.cpp @@ -26,15 +26,6 @@ static constexpr const std::array VERTEX_DATA = { 5, 7, 6, // back spike }; -SegmentTemplate::~SegmentTemplate() -{ - if (m_vbo_id != 0) - glsafe(glDeleteBuffers(1, &m_vbo_id)); - - if (m_vao_id != 0) - glsafe(glDeleteVertexArrays(1, &m_vao_id)); -} - void SegmentTemplate::init() { if (m_vao_id != 0) @@ -58,6 +49,18 @@ void SegmentTemplate::init() glsafe(glBindVertexArray(curr_vertex_array)); } +void SegmentTemplate::shutdown() +{ + if (m_vbo_id != 0) { + glsafe(glDeleteBuffers(1, &m_vbo_id)); + m_vbo_id = 0; + } + if (m_vao_id != 0) { + glsafe(glDeleteVertexArrays(1, &m_vao_id)); + m_vao_id = 0; + } +} + void SegmentTemplate::render(size_t count) { if (m_vao_id == 0 || m_vbo_id == 0 || count == 0) diff --git a/src/libvgcode/src/SegmentTemplate.hpp b/src/libvgcode/src/SegmentTemplate.hpp index 868cb9f394..bf540bade5 100644 --- a/src/libvgcode/src/SegmentTemplate.hpp +++ b/src/libvgcode/src/SegmentTemplate.hpp @@ -13,16 +13,26 @@ class SegmentTemplate { public: SegmentTemplate() = default; - ~SegmentTemplate(); + ~SegmentTemplate() { shutdown(); } SegmentTemplate(const SegmentTemplate& other) = delete; SegmentTemplate(SegmentTemplate&& other) = delete; SegmentTemplate& operator = (const SegmentTemplate& other) = delete; SegmentTemplate& operator = (SegmentTemplate&& other) = delete; + // + // Initialize gpu buffers. + // void init(); + // + // Release gpu buffers. + // + void shutdown(); void render(size_t count); private: + // + // gpu buffers ids. + // unsigned int m_vao_id{ 0 }; unsigned int m_vbo_id{ 0 }; }; diff --git a/src/libvgcode/src/ToolMarker.cpp b/src/libvgcode/src/ToolMarker.cpp index 59e3ef3c34..15713a2115 100644 --- a/src/libvgcode/src/ToolMarker.cpp +++ b/src/libvgcode/src/ToolMarker.cpp @@ -12,16 +12,6 @@ namespace libvgcode { -ToolMarker::~ToolMarker() -{ - if (m_ibo_id != 0) - glsafe(glDeleteBuffers(1, &m_ibo_id)); - if (m_vbo_id != 0) - glsafe(glDeleteBuffers(1, &m_vbo_id)); - if (m_vao_id != 0) - glsafe(glDeleteVertexArrays(1, &m_vao_id)); -} - // Geometry: // Arrow with cylindrical stem and conical tip, with the given dimensions and resolution // The origin of the arrow is at the tip of the conical section @@ -142,6 +132,22 @@ void ToolMarker::init(uint16_t resolution, float tip_radius, float tip_height, f glsafe(glBindVertexArray(curr_vertex_array)); } +void ToolMarker::shutdown() +{ + 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; + } + if (m_vao_id != 0) { + glsafe(glDeleteVertexArrays(1, &m_vao_id)); + m_vao_id = 0; + } +} + void ToolMarker::render() { if (m_vao_id == 0 || m_vbo_id == 0 || m_ibo_id == 0) diff --git a/src/libvgcode/src/ToolMarker.hpp b/src/libvgcode/src/ToolMarker.hpp index b21ef89ba7..dd59c8cb8d 100644 --- a/src/libvgcode/src/ToolMarker.hpp +++ b/src/libvgcode/src/ToolMarker.hpp @@ -16,13 +16,20 @@ class ToolMarker { public: ToolMarker() = default; - ~ToolMarker(); + ~ToolMarker() { shutdown(); } ToolMarker(const ToolMarker& other) = delete; ToolMarker(ToolMarker&& other) = delete; ToolMarker& operator = (const ToolMarker& other) = delete; ToolMarker& operator = (ToolMarker&& other) = delete; + // + // Initialize gpu buffers. + // void init(uint16_t resolution, float tip_radius, float tip_height, float stem_radius, float stem_height); + // + // Release gpu buffers. + // + void shutdown(); void render(); bool is_enabled() const { return m_enabled; } @@ -48,6 +55,9 @@ private: float m_alpha{ 0.5f }; uint16_t m_indices_count{ 0 }; + // + // gpu buffers ids. + // unsigned int m_vao_id{ 0 }; unsigned int m_vbo_id{ 0 }; unsigned int m_ibo_id{ 0 }; diff --git a/src/libvgcode/src/Viewer.cpp b/src/libvgcode/src/Viewer.cpp index 4b66beeebd..cb216bf648 100644 --- a/src/libvgcode/src/Viewer.cpp +++ b/src/libvgcode/src/Viewer.cpp @@ -22,6 +22,11 @@ void Viewer::init() m_impl->init(); } +void Viewer::shutdown() +{ + m_impl->shutdown(); +} + void Viewer::reset() { m_impl->reset(); diff --git a/src/libvgcode/src/ViewerImpl.cpp b/src/libvgcode/src/ViewerImpl.cpp index 2cce460042..721f1f5493 100644 --- a/src/libvgcode/src/ViewerImpl.cpp +++ b/src/libvgcode/src/ViewerImpl.cpp @@ -316,15 +316,6 @@ const std::map ViewerImpl::DEFAULT_OPTIONS_COLORS{ { { EOptionType::CustomGCodes, { 226, 210, 67 } } } }; -ViewerImpl::~ViewerImpl() -{ - reset(); - if (m_options_shader_id != 0) - glsafe(glDeleteProgram(m_options_shader_id)); - if (m_segments_shader_id != 0) - glsafe(glDeleteProgram(m_segments_shader_id)); -} - void ViewerImpl::init() { if (m_initialized) @@ -414,6 +405,26 @@ void ViewerImpl::init() m_initialized = true; } +void ViewerImpl::shutdown() +{ + reset(); +#if ENABLE_COG_AND_TOOL_MARKERS + m_tool_marker.shutdown(); + m_cog_marker.shutdown(); +#endif // ENABLE_COG_AND_TOOL_MARKERS + m_option_template.shutdown(); + m_segment_template.shutdown(); + if (m_options_shader_id != 0) { + glsafe(glDeleteProgram(m_options_shader_id)); + m_options_shader_id = 0; + } + if (m_segments_shader_id != 0) { + glsafe(glDeleteProgram(m_segments_shader_id)); + m_segments_shader_id = 0; + } + m_initialized = false; +} + void ViewerImpl::reset() { m_layers.reset(); @@ -593,6 +604,9 @@ void ViewerImpl::load(GCodeInputData&& gcode_data) void ViewerImpl::update_enabled_entities() { + if (m_vertices.empty()) + return; + std::vector enabled_segments; std::vector enabled_options; Interval range = m_view_range.get_visible(); @@ -687,6 +701,20 @@ static float encode_color(const Color& color) { void ViewerImpl::update_colors() { + if (m_colors_buf_id == 0) + return; + + if (!m_used_extruders_ids.empty()) { + // ensure that the number of defined tool colors matches the max id of the used extruders + const size_t max_used_extruder_id = 1 + static_cast(m_used_extruders_ids.back()); + const size_t tool_colors_size = m_tool_colors.size(); + if (m_tool_colors.size() < max_used_extruder_id) { + for (size_t i = 0; i < max_used_extruder_id - tool_colors_size; ++i) { + m_tool_colors.emplace_back(DUMMY_COLOR); + } + } + } + update_color_ranges(); const size_t top_layer_id = m_settings.top_layer_only_view_range ? m_layers.get_view_range()[1] : 0; diff --git a/src/libvgcode/src/ViewerImpl.hpp b/src/libvgcode/src/ViewerImpl.hpp index def9a0272e..4f0458fe96 100644 --- a/src/libvgcode/src/ViewerImpl.hpp +++ b/src/libvgcode/src/ViewerImpl.hpp @@ -27,19 +27,23 @@ class ViewerImpl { public: ViewerImpl() = default; - ~ViewerImpl(); + ~ViewerImpl() { shutdown(); } ViewerImpl(const ViewerImpl& other) = delete; ViewerImpl(ViewerImpl&& other) = delete; ViewerImpl& operator = (const ViewerImpl& other) = delete; ViewerImpl& operator = (ViewerImpl&& other) = delete; // - // Initialize shaders, uniform indices and segment geometry + // Initialize shaders, uniform indices and segment geometry. // void init(); + // + // Release the resources used by the viewer. + // + void shutdown(); // - // Reset all caches and free gpu memory + // Reset all caches and free gpu memory. // void reset();