Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorenricoturri1966 <enricoturri@seznam.cz>2021-01-13 12:45:52 +0300
committerenricoturri1966 <enricoturri@seznam.cz>2021-04-12 15:09:11 +0300
commit420cdca5b55120f1364c645d1367b90e8a7e0e2e (patch)
tree4d1c8382517904f8037ab993e11990ea5a2667bd
parent2b7bd1452a736d282a4fc9961a944b787cf9d132 (diff)
ENABLE_SPLITTED_VERTEX_BUFFER - fixed export of toolpaths to obj files
-rw-r--r--src/slic3r/GUI/GCodeViewer.cpp119
-rw-r--r--src/slic3r/GUI/GCodeViewer.hpp9
-rw-r--r--src/slic3r/GUI/GLCanvas3D.cpp4
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<GLsizei>(ids.size()), static_cast<const GLuint*>(ids.data())));
- ids.clear();
+ if (!vbos.empty()) {
+ glsafe(::glDeleteBuffers(static_cast<GLsizei>(vbos.size()), static_cast<const GLuint*>(vbos.data())));
+ vbos.clear();
}
-
+ sizes.clear();
count = 0;
}
#else
@@ -358,7 +358,8 @@ const std::vector<GCodeViewer::Color> 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<unsigned int, 2>& 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<Color> 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<Vec3f> out_vertices;
+ std::vector<Vec3f> out_normals;
+ std::vector<size_t> 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<GLsizeiptr>(t_buffer.vertices.sizes[i]), static_cast<void*>(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<GLintptr>(render_path.offsets[j]),
+ static_cast<GLsizeiptr>(render_path.sizes[j] * sizeof(unsigned int)), static_cast<void*>(indices.data())));
+
+ for (size_t k = 0; k < triangles_count; ++k) {
+ const size_t base = k * 3;
+ const size_t v1 = 1 + static_cast<size_t>(indices[base + 0]) + vertices_offset;
+ const size_t v2 = 1 + static_cast<size_t>(indices[base + 1]) + vertices_offset;
+ const size_t v3 = 1 + static_cast<size_t>(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<unsigned int>(id));
+ t_buffer.vertices.vbos.push_back(static_cast<unsigned int>(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<unsigned int> ids;
+ std::vector<unsigned int> vbos;
+ // sizes of the buffers, in bytes, used in export to obj
+ std::vector<size_t> 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