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

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnrico Turri <enricoturri@seznam.cz>2019-08-27 17:05:38 +0300
committerEnrico Turri <enricoturri@seznam.cz>2019-08-27 17:05:38 +0300
commit97473439cf4d7261f5dcd9a2400f3f7dd9cb5047 (patch)
tree93dc2938fc6625664adb2ae362e36cf2c5f5c472 /src/slic3r/GUI/3DScene.cpp
parent80490550b520eda335dddbf96b2a1db9cd1d4366 (diff)
Export toolpaths to obj -> Reduced size of output
Diffstat (limited to 'src/slic3r/GUI/3DScene.cpp')
-rw-r--r--src/slic3r/GUI/3DScene.cpp180
1 files changed, 142 insertions, 38 deletions
diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp
index a3d1f0615..a0033b267 100644
--- a/src/slic3r/GUI/3DScene.cpp
+++ b/src/slic3r/GUI/3DScene.cpp
@@ -906,13 +906,14 @@ void GLVolumeCollection::export_toolpaths_to_obj(const char* filename) const
return;
// collect color information to generate materials
- std::set<std::array<float, 4>> colors;
+ typedef std::array<float, 4> Color;
+ std::set<Color> colors;
for (const GLVolume* volume : this->volumes)
{
if (!can_export_to_obj(*volume))
continue;
- std::array<float, 4> color;
+ Color color;
::memcpy((void*)color.data(), (const void*)volume->color, 4 * sizeof(float));
colors.insert(color);
}
@@ -930,8 +931,8 @@ void GLVolumeCollection::export_toolpaths_to_obj(const char* filename) const
fprintf(fp, "# Generated by %s based on Slic3r\n", SLIC3R_BUILD_ID);
unsigned int colors_count = 1;
- for (const std::array<float, 4>& color : colors)
- {
+ for (const Color& color : colors)
+ {
fprintf(fp, "\nnewmtl material_%d\n", colors_count++);
fprintf(fp, "Ka 1 1 1\n");
fprintf(fp, "Kd %f %f %f\n", color[0], color[1], color[2]);
@@ -952,6 +953,7 @@ void GLVolumeCollection::export_toolpaths_to_obj(const char* filename) const
fprintf(fp, "\nmtllib ./%s\n", mat_filename.filename().string().c_str());
unsigned int vertices_count = 0;
+ unsigned int normals_count = 0;
unsigned int volumes_count = 0;
for (const GLVolume* volume : this->volumes)
@@ -959,20 +961,20 @@ void GLVolumeCollection::export_toolpaths_to_obj(const char* filename) const
if (!can_export_to_obj(*volume))
continue;
- std::vector<float> vertices_and_normals_interleaved;
- std::vector<int> triangle_indices;
- std::vector<int> quad_indices;
+ std::vector<float> src_vertices_and_normals_interleaved;
+ std::vector<int> src_triangle_indices;
+ std::vector<int> src_quad_indices;
if (!volume->indexed_vertex_array.vertices_and_normals_interleaved.empty())
// data are in CPU memory
- vertices_and_normals_interleaved = volume->indexed_vertex_array.vertices_and_normals_interleaved;
+ src_vertices_and_normals_interleaved = volume->indexed_vertex_array.vertices_and_normals_interleaved;
else if ((volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id != 0) && (volume->indexed_vertex_array.vertices_and_normals_interleaved_size != 0))
{
// data are in GPU memory
- vertices_and_normals_interleaved = std::vector<float>(volume->indexed_vertex_array.vertices_and_normals_interleaved_size, 0.0f);
+ src_vertices_and_normals_interleaved = std::vector<float>(volume->indexed_vertex_array.vertices_and_normals_interleaved_size, 0.0f);
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, volume->indexed_vertex_array.vertices_and_normals_interleaved_VBO_id));
- glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, 0, vertices_and_normals_interleaved.size() * sizeof(float), vertices_and_normals_interleaved.data()));
+ glsafe(::glGetBufferSubData(GL_ARRAY_BUFFER, 0, src_vertices_and_normals_interleaved.size() * sizeof(float), src_vertices_and_normals_interleaved.data()));
glsafe(::glBindBuffer(GL_ARRAY_BUFFER, 0));
}
else
@@ -986,7 +988,7 @@ void GLVolumeCollection::export_toolpaths_to_obj(const char* filename) const
{
std::vector<int>::const_iterator it_begin = volume->indexed_vertex_array.triangle_indices.begin() + volume->tverts_range.first;
std::vector<int>::const_iterator it_end = volume->indexed_vertex_array.triangle_indices.begin() + volume->tverts_range.first + size;
- std::copy(it_begin, it_end, std::back_inserter(triangle_indices));
+ std::copy(it_begin, it_end, std::back_inserter(src_triangle_indices));
}
}
else if ((volume->indexed_vertex_array.triangle_indices_VBO_id != 0) && (volume->indexed_vertex_array.triangle_indices_size != 0))
@@ -995,10 +997,10 @@ void GLVolumeCollection::export_toolpaths_to_obj(const char* filename) const
size_t size = std::min(volume->indexed_vertex_array.triangle_indices_size, volume->tverts_range.second - volume->tverts_range.first);
if (size != 0)
{
- triangle_indices = std::vector<int>(size, 0);
+ src_triangle_indices = std::vector<int>(size, 0);
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, volume->indexed_vertex_array.triangle_indices_VBO_id));
- glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, volume->tverts_range.first * sizeof(int), size * sizeof(int), triangle_indices.data()));
+ glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, volume->tverts_range.first * sizeof(int), size * sizeof(int), src_triangle_indices.data()));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
}
@@ -1011,7 +1013,7 @@ void GLVolumeCollection::export_toolpaths_to_obj(const char* filename) const
{
std::vector<int>::const_iterator it_begin = volume->indexed_vertex_array.quad_indices.begin() + volume->qverts_range.first;
std::vector<int>::const_iterator it_end = volume->indexed_vertex_array.quad_indices.begin() + volume->qverts_range.first + size;
- std::copy(it_begin, it_end, std::back_inserter(quad_indices));
+ std::copy(it_begin, it_end, std::back_inserter(src_quad_indices));
}
}
else if ((volume->indexed_vertex_array.quad_indices_VBO_id != 0) && (volume->indexed_vertex_array.quad_indices_size != 0))
@@ -1020,56 +1022,158 @@ void GLVolumeCollection::export_toolpaths_to_obj(const char* filename) const
size_t size = std::min(volume->indexed_vertex_array.quad_indices_size, volume->qverts_range.second - volume->qverts_range.first);
if (size != 0)
{
- quad_indices = std::vector<int>(size, 0);
+ src_quad_indices = std::vector<int>(size, 0);
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, volume->indexed_vertex_array.quad_indices_VBO_id));
- glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, volume->qverts_range.first * sizeof(int), size * sizeof(int), quad_indices.data()));
+ glsafe(::glGetBufferSubData(GL_ELEMENT_ARRAY_BUFFER, volume->qverts_range.first * sizeof(int), size * sizeof(int), src_quad_indices.data()));
glsafe(::glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
}
}
- if (triangle_indices.empty() && quad_indices.empty())
+ if (src_triangle_indices.empty() && src_quad_indices.empty())
continue;
+ ++volumes_count;
+
+ // reduce output size by keeping only used vertices and normals
+
+ struct Vector
+ {
+ std::array<coord_t, 3> vector;
+
+ explicit Vector(float* ptr)
+ {
+ vector[0] = scale_(*(ptr + 0));
+ vector[1] = scale_(*(ptr + 1));
+ vector[2] = scale_(*(ptr + 2));
+ }
+ };
+ typedef std::vector<Vector> Vectors;
+
+ auto vector_less = [](const Vector& v1, const Vector& v2)->bool {
+ return v1.vector < v2.vector;
+ };
+
+ auto vector_equal = [](const Vector& v1, const Vector& v2)->bool {
+ return (v1.vector[0] == v2.vector[0]) && (v1.vector[1] == v2.vector[1]) && (v1.vector[2] == v2.vector[2]);
+ };
+
+ // copy used vertices and normals data
+ Vectors dst_normals;
+ Vectors dst_vertices;
+
+ unsigned int src_triangle_indices_size = (unsigned int)src_triangle_indices.size();
+ for (unsigned int i = 0; i < src_triangle_indices_size; ++i)
+ {
+ float* src_ptr = src_vertices_and_normals_interleaved.data() + src_triangle_indices[i] * 6;
+ dst_normals.emplace_back(src_ptr + 0);
+ dst_vertices.emplace_back(src_ptr + 3);
+ }
+
+ unsigned int src_quad_indices_size = (unsigned int)src_quad_indices.size();
+ for (unsigned int i = 0; i < src_quad_indices_size; ++i)
+ {
+ float* src_ptr = src_vertices_and_normals_interleaved.data() + src_quad_indices[i] * 6;
+ dst_normals.emplace_back(src_ptr + 0);
+ dst_vertices.emplace_back(src_ptr + 3);
+ }
+
+ // sort vertices and normals
+ std::sort(dst_normals.begin(), dst_normals.end(), vector_less);
+ std::sort(dst_vertices.begin(), dst_vertices.end(), vector_less);
+
+ // remove duplicated vertices and normals
+ dst_normals.erase(std::unique(dst_normals.begin(), dst_normals.end(), vector_equal), dst_normals.end());
+ dst_vertices.erase(std::unique(dst_vertices.begin(), dst_vertices.end(), vector_equal), dst_vertices.end());
+
+ // reindex triangles and quads
+ struct IndicesPair
+ {
+ int vertex;
+ int normal;
+ IndicesPair(int vertex, int normal) : vertex(vertex), normal(normal) {}
+ };
+ typedef std::vector<IndicesPair> Indices;
+
+ unsigned int src_vertices_count = (unsigned int)src_vertices_and_normals_interleaved.size() / 6;
+ std::vector<int> src_dst_vertex_indices_map(src_vertices_count, -1);
+ std::vector<int> src_dst_normal_indices_map(src_vertices_count, -1);
+
+ for (unsigned int i = 0; i < src_vertices_count; ++i)
+ {
+ float* src_ptr = src_vertices_and_normals_interleaved.data() + i * 6;
+ src_dst_normal_indices_map[i] = std::distance(dst_normals.begin(), std::lower_bound(dst_normals.begin(), dst_normals.end(), Vector(src_ptr + 0), vector_less));
+ src_dst_vertex_indices_map[i] = std::distance(dst_vertices.begin(), std::lower_bound(dst_vertices.begin(), dst_vertices.end(), Vector(src_ptr + 3), vector_less));
+ }
+
+ Indices dst_triangle_indices;
+ if (src_triangle_indices_size > 0)
+ dst_triangle_indices.reserve(src_triangle_indices_size);
+
+ for (unsigned int i = 0; i < src_triangle_indices_size; ++i)
+ {
+ int id = src_triangle_indices[i];
+ dst_triangle_indices.emplace_back(src_dst_vertex_indices_map[id], src_dst_normal_indices_map[id]);
+ }
+
+ Indices dst_quad_indices;
+ if (src_quad_indices_size > 0)
+ dst_quad_indices.reserve(src_quad_indices_size);
+
+ for (unsigned int i = 0; i < src_quad_indices_size; ++i)
+ {
+ int id = src_quad_indices[i];
+ dst_quad_indices.emplace_back(src_dst_vertex_indices_map[id], src_dst_normal_indices_map[id]);
+ }
+
+ // save to file
fprintf(fp, "\n# vertices volume %d\n", volumes_count);
- for (unsigned int i = 0; i < vertices_and_normals_interleaved.size(); i += 6)
+ for (const Vector& v : dst_vertices)
{
- fprintf(fp, "v %f %f %f\n", vertices_and_normals_interleaved[i + 3], vertices_and_normals_interleaved[i + 4], vertices_and_normals_interleaved[i + 5]);
+ fprintf(fp, "v %f %f %f\n", unscale<float>(v.vector[0]), unscale<float>(v.vector[1]), unscale<float>(v.vector[2]));
}
fprintf(fp, "\n# normals volume %d\n", volumes_count);
- for (unsigned int i = 0; i < vertices_and_normals_interleaved.size(); i += 6)
+ for (const Vector& n : dst_normals)
{
- fprintf(fp, "vn %f %f %f\n", vertices_and_normals_interleaved[i + 0], vertices_and_normals_interleaved[i + 1], vertices_and_normals_interleaved[i + 2]);
+ fprintf(fp, "vn %f %f %f\n", unscale<float>(n.vector[0]), unscale<float>(n.vector[1]), unscale<float>(n.vector[2]));
}
- std::array<float, 4> color;
+ Color color;
::memcpy((void*)color.data(), (const void*)volume->color, 4 * sizeof(float));
- colors.insert(color);
fprintf(fp, "\n# material volume %d\n", volumes_count);
fprintf(fp, "usemtl material_%lld\n", 1 + std::distance(colors.begin(), colors.find(color)));
- fprintf(fp, "\n# triangular facets volume %d\n", volumes_count);
- for (unsigned int i = 0; i < triangle_indices.size(); i += 3)
+ int base_vertex_id = vertices_count + 1;
+ int base_normal_id = normals_count + 1;
+
+ if (!dst_triangle_indices.empty())
{
- int id_v1 = vertices_count + 1 + triangle_indices[i + 0];
- int id_v2 = vertices_count + 1 + triangle_indices[i + 1];
- int id_v3 = vertices_count + 1 + triangle_indices[i + 2];
- fprintf(fp, "f %d//%d %d//%d %d//%d\n", id_v1, id_v1, id_v2, id_v2, id_v3, id_v3);
+ fprintf(fp, "\n# triangular facets volume %d\n", volumes_count);
+ for (unsigned int i = 0; i < (unsigned int)dst_triangle_indices.size(); i += 3)
+ {
+ fprintf(fp, "f %d//%d %d//%d %d//%d\n",
+ base_vertex_id + dst_triangle_indices[i + 0].vertex, base_normal_id + dst_triangle_indices[i + 0].normal,
+ base_vertex_id + dst_triangle_indices[i + 1].vertex, base_normal_id + dst_triangle_indices[i + 1].normal,
+ base_vertex_id + dst_triangle_indices[i + 2].vertex, base_normal_id + dst_triangle_indices[i + 2].normal);
+ }
}
- fprintf(fp, "\n# quadrangular facets volume %d\n", volumes_count);
- for (unsigned int i = 0; i < quad_indices.size(); i += 4)
+ if (!dst_quad_indices.empty())
{
- int id_v1 = vertices_count + 1 + quad_indices[i + 0];
- int id_v2 = vertices_count + 1 + quad_indices[i + 1];
- int id_v3 = vertices_count + 1 + quad_indices[i + 2];
- int id_v4 = vertices_count + 1 + quad_indices[i + 3];
- fprintf(fp, "f %d//%d %d//%d %d//%d %d//%d\n", id_v1, id_v1, id_v2, id_v2, id_v3, id_v3, id_v4, id_v4);
+ fprintf(fp, "\n# quadrangular facets volume %d\n", volumes_count);
+ for (unsigned int i = 0; i < (unsigned int)src_quad_indices.size(); i += 4)
+ {
+ fprintf(fp, "f %d//%d %d//%d %d//%d %d//%d\n",
+ base_vertex_id + dst_quad_indices[i + 0].vertex, base_normal_id + dst_quad_indices[i + 0].normal,
+ base_vertex_id + dst_quad_indices[i + 1].vertex, base_normal_id + dst_quad_indices[i + 1].normal,
+ base_vertex_id + dst_quad_indices[i + 2].vertex, base_normal_id + dst_quad_indices[i + 2].normal,
+ base_vertex_id + dst_quad_indices[i + 3].vertex, base_normal_id + dst_quad_indices[i + 3].normal);
+ }
}
- ++volumes_count;
- vertices_count += vertices_and_normals_interleaved.size() / 6;
+ vertices_count += (unsigned int)dst_vertices.size();
+ normals_count += (unsigned int)dst_normals.size();
}
fclose(fp);