diff options
author | Enrico Turri <enricoturri@seznam.cz> | 2019-08-27 17:05:38 +0300 |
---|---|---|
committer | Enrico Turri <enricoturri@seznam.cz> | 2019-08-27 17:05:38 +0300 |
commit | 97473439cf4d7261f5dcd9a2400f3f7dd9cb5047 (patch) | |
tree | 93dc2938fc6625664adb2ae362e36cf2c5f5c472 /src/slic3r/GUI/3DScene.cpp | |
parent | 80490550b520eda335dddbf96b2a1db9cd1d4366 (diff) |
Export toolpaths to obj -> Reduced size of output
Diffstat (limited to 'src/slic3r/GUI/3DScene.cpp')
-rw-r--r-- | src/slic3r/GUI/3DScene.cpp | 180 |
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); |