From 420cdca5b55120f1364c645d1367b90e8a7e0e2e Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Wed, 13 Jan 2021 10:45:52 +0100 Subject: ENABLE_SPLITTED_VERTEX_BUFFER - fixed export of toolpaths to obj files --- src/slic3r/GUI/GCodeViewer.cpp | 119 +++++++++++++++++++++++++++++++++++------ src/slic3r/GUI/GCodeViewer.hpp | 9 +++- src/slic3r/GUI/GLCanvas3D.cpp | 4 ++ 3 files changed, 114 insertions(+), 18 deletions(-) diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index c67e1c7a2..882ac97ea 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -83,11 +83,11 @@ static float round_to_nearest(float value, unsigned int decimals) void GCodeViewer::VBuffer::reset() { // release gpu memory - if (!ids.empty()) { - glsafe(::glDeleteBuffers(static_cast(ids.size()), static_cast(ids.data()))); - ids.clear(); + if (!vbos.empty()) { + glsafe(::glDeleteBuffers(static_cast(vbos.size()), static_cast(vbos.data()))); + vbos.clear(); } - + sizes.clear(); count = 0; } #else @@ -358,7 +358,8 @@ const std::vector GCodeViewer::Range_Colors {{ GCodeViewer::GCodeViewer() { - // initializes non opengl data of TBuffers + // initializes non OpenGL data of TBuffers + // OpenGL data are initialized into render().init_gl_data() for (size_t i = 0; i < m_buffers.size(); ++i) { TBuffer& buffer = m_buffers[i]; switch (buffer_type(i)) @@ -633,6 +634,13 @@ void GCodeViewer::render() const #endif // ENABLE_GCODE_VIEWER_STATISTICS } +#if ENABLE_SPLITTED_VERTEX_BUFFER +bool GCodeViewer::can_export_toolpaths() const +{ + return has_data() && m_buffers[buffer_id(EMoveType::Extrude)].render_primitive_type == TBuffer::ERenderPrimitiveType::Triangle; +} +#endif // ENABLE_SPLITTED_VERTEX_BUFFER + void GCodeViewer::update_sequential_view_current(unsigned int first, unsigned int last) { auto is_visible = [this](unsigned int id) { @@ -747,8 +755,6 @@ void GCodeViewer::set_layers_z_range(const std::array& layers_z void GCodeViewer::export_toolpaths_to_obj(const char* filename) const { -#if !ENABLE_SPLITTED_VERTEX_BUFFER - if (filename == nullptr) return; @@ -758,15 +764,24 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const wxBusyCursor busy; // the data needed is contained into the Extrude TBuffer - const TBuffer& buffer = m_buffers[buffer_id(EMoveType::Extrude)]; - if (!buffer.has_data()) + const TBuffer& t_buffer = m_buffers[buffer_id(EMoveType::Extrude)]; + if (!t_buffer.has_data()) return; +#if ENABLE_SPLITTED_VERTEX_BUFFER + if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Triangle) + return; +#endif // ENABLE_SPLITTED_VERTEX_BUFFER + // collect color information to generate materials std::vector colors; - for (const RenderPath& path : buffer.render_paths) { + for (const RenderPath& path : t_buffer.render_paths) { colors.push_back(path.color); } +#if ENABLE_SPLITTED_VERTEX_BUFFER + std::sort(colors.begin(), colors.end()); + colors.erase(std::unique(colors.begin(), colors.end()), colors.end()); +#endif // ENABLE_SPLITTED_VERTEX_BUFFER // save materials file boost::filesystem::path mat_filename(filename); @@ -801,6 +816,78 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const fprintf(fp, "# Generated by %s based on Slic3r\n", SLIC3R_BUILD_ID); fprintf(fp, "\nmtllib ./%s\n", mat_filename.filename().string().c_str()); +#if ENABLE_SPLITTED_VERTEX_BUFFER + const size_t floats_per_vertex = t_buffer.vertices.vertex_size_floats(); + + std::vector out_vertices; + std::vector out_normals; + std::vector vertices_offsets; + vertices_offsets.push_back(0); + + // get vertices/normals data from vertex buffers on gpu + for (size_t i = 0; i < t_buffer.vertices.vbos.size(); ++i) { + const size_t floats_count = t_buffer.vertices.sizes[i] / sizeof(float); + VertexBuffer vertices(floats_count); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, t_buffer.vertices.vbos[i])); + glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, 0, static_cast(t_buffer.vertices.sizes[i]), static_cast(vertices.data()))); + glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); + const size_t vertices_count = floats_count / floats_per_vertex; + for (size_t j = 0; j < vertices_count; ++j) { + const size_t base = j * floats_per_vertex; + out_vertices.push_back({ vertices[base + 0], vertices[base + 1], vertices[base + 2] }); + out_normals.push_back({ vertices[base + 3], vertices[base + 4], vertices[base + 5] }); + } + vertices_offsets.push_back(vertices_offsets.back() + vertices_count); + } + + // save vertices to file + fprintf(fp, "\n# vertices\n"); + for (const Vec3f& v : out_vertices) { + fprintf(fp, "v %g %g %g\n", v[0], v[1], v[2]); + } + + // save normals to file + fprintf(fp, "\n# normals\n"); + for (const Vec3f& n : out_normals) { + fprintf(fp, "vn %g %g %g\n", n[0], n[1], n[2]); + } + + size_t i = 0; + for (const Color& color : colors) { + // save material triangles to file + fprintf(fp, "\nusemtl material_%zu\n", i + 1); + fprintf(fp, "# triangles material %zu\n", i + 1); + + for (const RenderPath& render_path : t_buffer.render_paths) { + if (render_path.color != color) + continue; + + const IBuffer& ibuffer = t_buffer.indices[render_path.index_buffer_id]; + const size_t vertices_offset = vertices_offsets[render_path.index_buffer_id]; + + // get indices data from index buffer on gpu + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibuffer.ibo)); + for (size_t j = 0; j < render_path.sizes.size(); ++j) { + const size_t triangles_count = render_path.sizes[j] / 3; + IndexBuffer indices(render_path.sizes[j]); + glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, static_cast(render_path.offsets[j]), + static_cast(render_path.sizes[j] * sizeof(unsigned int)), static_cast(indices.data()))); + + for (size_t k = 0; k < triangles_count; ++k) { + const size_t base = k * 3; + const size_t v1 = 1 + static_cast(indices[base + 0]) + vertices_offset; + const size_t v2 = 1 + static_cast(indices[base + 1]) + vertices_offset; + const size_t v3 = 1 + static_cast(indices[base + 2]) + vertices_offset; + if (v1 != v2) + // do not export dummy triangles + fprintf(fp, "f %zu//%zu %zu//%zu %zu//%zu\n", v1, v1, v2, v2, v3, v3); + } + } + glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)); + } + ++i; + } +#else // get vertices data from vertex buffer on gpu size_t floats_per_vertex = buffer.vertices.vertex_size_floats(); VertexBuffer vertices = VertexBuffer(buffer.vertices.count * floats_per_vertex); @@ -1041,10 +1128,9 @@ void GCodeViewer::export_toolpaths_to_obj(const char* filename) const ++ i; } +#endif // ENABLE_SPLITTED_VERTEX_BUFFER fclose(fp); - -#endif // !ENABLE_SPLITTED_VERTEX_BUFFER } #if ENABLE_SPLITTED_VERTEX_BUFFER @@ -1525,7 +1611,8 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) GLuint id = 0; glsafe(::glGenBuffers(1, &id)); - t_buffer.vertices.ids.push_back(static_cast(id)); + t_buffer.vertices.vbos.push_back(static_cast(id)); + t_buffer.vertices.sizes.push_back(size_bytes); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, id)); glsafe(::glBufferData(GL_ARRAY_BUFFER, size_bytes, v_buffer.data(), GL_STATIC_DRAW)); glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0)); @@ -1581,14 +1668,14 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) // ensure there is at least one index buffer if (i_multibuffer.empty()) { i_multibuffer.push_back(IndexBuffer()); - vbo_index_list.push_back(t_buffer.vertices.ids[curr_vertex_buffer.first]); + vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); } // if adding the indices for the current segment exceeds the threshold size of the current index buffer // create another index buffer if (i_multibuffer.back().size() * sizeof(unsigned int) >= IBUFFER_THRESHOLD_BYTES - t_buffer.indices_per_segment_size_bytes()) { i_multibuffer.push_back(IndexBuffer()); - vbo_index_list.push_back(t_buffer.vertices.ids[curr_vertex_buffer.first]); + vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); } // if adding the vertices for the current segment exceeds the threshold size of the current vertex buffer @@ -1598,7 +1685,7 @@ void GCodeViewer::load_toolpaths(const GCodeProcessor::Result& gcode_result) ++curr_vertex_buffer.first; curr_vertex_buffer.second = 0; - vbo_index_list.push_back(t_buffer.vertices.ids[curr_vertex_buffer.first]); + vbo_index_list.push_back(t_buffer.vertices.vbos[curr_vertex_buffer.first]); if (t_buffer.render_primitive_type != TBuffer::ERenderPrimitiveType::Point) { Path& last_path = t_buffer.paths.back(); diff --git a/src/slic3r/GUI/GCodeViewer.hpp b/src/slic3r/GUI/GCodeViewer.hpp index a334f08e0..6602bbcf8 100644 --- a/src/slic3r/GUI/GCodeViewer.hpp +++ b/src/slic3r/GUI/GCodeViewer.hpp @@ -59,7 +59,9 @@ class GCodeViewer EFormat format{ EFormat::Position }; #if ENABLE_SPLITTED_VERTEX_BUFFER // vbos id - std::vector ids; + std::vector vbos; + // sizes of the buffers, in bytes, used in export to obj + std::vector sizes; #else // vbo id unsigned int id{ 0 }; @@ -301,7 +303,7 @@ class GCodeViewer #if ENABLE_SPLITTED_VERTEX_BUFFER bool has_data() const { - return !vertices.ids.empty() && vertices.ids.front() != 0 && !indices.empty() && indices.front().ibo != 0; + return !vertices.vbos.empty() && vertices.vbos.front() != 0 && !indices.empty() && indices.front().ibo != 0; } #else bool has_data() const { return vertices.id != 0 && !indices.empty() && indices.front().id != 0; } @@ -588,6 +590,9 @@ public: void render() const; bool has_data() const { return !m_roles.empty(); } +#if ENABLE_SPLITTED_VERTEX_BUFFER + bool can_export_toolpaths() const; +#endif // ENABLE_SPLITTED_VERTEX_BUFFER const BoundingBoxf3& get_paths_bounding_box() const { return m_paths_bounding_box; } const BoundingBoxf3& get_max_bounding_box() const { return m_max_bounding_box; } diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 03d6b94ce..388db4a27 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3866,7 +3866,11 @@ void GLCanvas3D::update_tooltip_for_settings_item_in_main_toolbar() bool GLCanvas3D::has_toolpaths_to_export() const { +#if ENABLE_SPLITTED_VERTEX_BUFFER + return m_gcode_viewer.can_export_toolpaths(); +#else return m_gcode_viewer.has_data(); +#endif // ENABLE_SPLITTED_VERTEX_BUFFER } void GLCanvas3D::export_toolpaths_to_obj(const char* filename) const -- cgit v1.2.3