From f9bdde560374eda13d89863973594103e0cc6814 Mon Sep 17 00:00:00 2001 From: Filip Sykala Date: Tue, 2 Nov 2021 14:23:49 +0100 Subject: [PATCH] Remove SimplifyMesh --- src/libslic3r/CMakeLists.txt | 3 - src/libslic3r/QuadricEdgeCollapse.cpp | 40 +- src/libslic3r/SLA/Hollowing.cpp | 7 +- src/libslic3r/SimplifyMesh.cpp | 66 --- src/libslic3r/SimplifyMesh.hpp | 23 - src/libslic3r/SimplifyMeshImpl.hpp | 670 -------------------------- tests/libslic3r/CMakeLists.txt | 1 - tests/libslic3r/test_meshboolean.cpp | 1 - tests/libslic3r/test_meshsimplify.cpp | 11 - 9 files changed, 43 insertions(+), 779 deletions(-) delete mode 100644 src/libslic3r/SimplifyMesh.cpp delete mode 100644 src/libslic3r/SimplifyMesh.hpp delete mode 100644 src/libslic3r/SimplifyMeshImpl.hpp delete mode 100644 tests/libslic3r/test_meshsimplify.cpp diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 4ffde3d5b..5ad589289 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -232,9 +232,6 @@ add_library(libslic3r STATIC MinAreaBoundingBox.cpp miniz_extension.hpp miniz_extension.cpp - SimplifyMesh.hpp - SimplifyMeshImpl.hpp - SimplifyMesh.cpp MarchingSquares.hpp Execution/Execution.hpp Execution/ExecutionSeq.hpp diff --git a/src/libslic3r/QuadricEdgeCollapse.cpp b/src/libslic3r/QuadricEdgeCollapse.cpp index 7efe15bb2..48a72e6d8 100644 --- a/src/libslic3r/QuadricEdgeCollapse.cpp +++ b/src/libslic3r/QuadricEdgeCollapse.cpp @@ -2,7 +2,6 @@ #include #include #include "MutablePriorityQueue.hpp" -#include "SimplifyMeshImpl.hpp" #include using namespace Slic3r; @@ -13,10 +12,47 @@ using namespace Slic3r; // only private namespace not neccessary be in .hpp namespace QuadricEdgeCollapse { + // SymetricMatrix + class SymMat { + using T = double; + static const constexpr size_t N = 10; + T m[N]; + public: + explicit SymMat(ArithmeticOnly c = T()) { std::fill(m, m + N, c); } + + // Make plane + SymMat(T a, T b, T c, T d) + { + m[0] = a * a; m[1] = a * b; m[2] = a * c; m[3] = a * d; + m[4] = b * b; m[5] = b * c; m[6] = b * d; + m[7] = c * c; m[8] = c * d; + m[9] = d * d; + } + + T operator[](int c) const { return m[c]; } + + // Determinant + T det(int a11, int a12, int a13, + int a21, int a22, int a23, + int a31, int a32, int a33) const + { + T det = m[a11] * m[a22] * m[a33] + m[a13] * m[a21] * m[a32] + + m[a12] * m[a23] * m[a31] - m[a13] * m[a22] * m[a31] - + m[a11] * m[a23] * m[a32] - m[a12] * m[a21] * m[a33]; + + return det; + } + + const SymMat &operator+=(const SymMat &n) + { + for (size_t i = 0; i < N; ++i) m[i] += n[i]; + return *this; + } + }; + using Vertices = std::vector; using Triangle = stl_triangle_vertex_indices; using Indices = std::vector; - using SymMat = SimplifyMesh::implementation::SymetricMatrix; using ThrowOnCancel = std::function; using StatusFn = std::function; // smallest error caused by edges, identify smallest edge in triangle diff --git a/src/libslic3r/SLA/Hollowing.cpp b/src/libslic3r/SLA/Hollowing.cpp index 9cac7f63b..b0d33a0ca 100644 --- a/src/libslic3r/SLA/Hollowing.cpp +++ b/src/libslic3r/SLA/Hollowing.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include @@ -132,7 +132,10 @@ InteriorPtr generate_interior(const TriangleMesh & mesh, // flip normals back... swap_normals(interior->mesh); - Slic3r::simplify_mesh(interior->mesh); + + // simplify mesh lossless + float loss_less_max_error = 2*std::numeric_limits::epsilon(); + its_quadric_edge_collapse(interior->mesh, 0U, &loss_less_max_error); its_compactify_vertices(interior->mesh); its_merge_vertices(interior->mesh); diff --git a/src/libslic3r/SimplifyMesh.cpp b/src/libslic3r/SimplifyMesh.cpp deleted file mode 100644 index d30ecfec5..000000000 --- a/src/libslic3r/SimplifyMesh.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include "SimplifyMesh.hpp" -#include "SimplifyMeshImpl.hpp" - -namespace SimplifyMesh { - -template<> struct vertex_traits { - using coord_type = float; - using compute_type = double; - - static inline float x(const stl_vertex &v) { return v.x(); } - static inline float& x(stl_vertex &v) { return v.x(); } - - static inline float y(const stl_vertex &v) { return v.y(); } - static inline float& y(stl_vertex &v) { return v.y(); } - - static inline float z(const stl_vertex &v) { return v.z(); } - static inline float& z(stl_vertex &v) { return v.z(); } -}; - -template<> struct mesh_traits { - using vertex_t = stl_vertex; - static size_t face_count(const indexed_triangle_set &m) - { - return m.indices.size(); - } - static size_t vertex_count(const indexed_triangle_set &m) - { - return m.vertices.size(); - } - static vertex_t vertex(const indexed_triangle_set &m, size_t idx) - { - return m.vertices[idx]; - } - static void vertex(indexed_triangle_set &m, size_t idx, const vertex_t &v) - { - m.vertices[idx] = v; - } - static Index3 triangle(const indexed_triangle_set &m, size_t idx) - { - std::array t; - for (size_t i = 0; i < 3; ++i) t[i] = size_t(m.indices[idx](int(i))); - return t; - } - static void triangle(indexed_triangle_set &m, size_t fidx, const Index3 &t) - { - auto &face = m.indices[fidx]; - face(0) = int(t[0]); face(1) = int(t[1]); face(2) = int(t[2]); - } - static void update(indexed_triangle_set &m, size_t vc, size_t fc) - { - m.vertices.resize(vc); - m.indices.resize(fc); - } -}; - -} // namespace SimplifyMesh - -namespace Slic3r { - -void simplify_mesh(indexed_triangle_set &m) -{ - SimplifyMesh::implementation::SimplifiableMesh sm{&m}; - sm.simplify_mesh_lossless(); -} - -} diff --git a/src/libslic3r/SimplifyMesh.hpp b/src/libslic3r/SimplifyMesh.hpp deleted file mode 100644 index 23eb343d1..000000000 --- a/src/libslic3r/SimplifyMesh.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef MESHSIMPLIFY_HPP -#define MESHSIMPLIFY_HPP - -#include - -#include - -namespace Slic3r { - -void simplify_mesh(indexed_triangle_set &); - -// TODO: (but this can be done with IGL as well) -// void simplify_mesh(indexed_triangle_set &, int face_count, float agressiveness = 0.5f); - -template void simplify_mesh(TriangleMesh &m, Args &&...a) -{ - simplify_mesh(m.its, std::forward(a)...); - m = TriangleMesh{ std::move(m.its) }; -} - -} // namespace Slic3r - -#endif // MESHSIMPLIFY_H diff --git a/src/libslic3r/SimplifyMeshImpl.hpp b/src/libslic3r/SimplifyMeshImpl.hpp deleted file mode 100644 index d143b6d87..000000000 --- a/src/libslic3r/SimplifyMeshImpl.hpp +++ /dev/null @@ -1,670 +0,0 @@ -// /////////////////////////////////////////// -// -// Mesh Simplification Tutorial -// -// (C) by Sven Forstmann in 2014 -// -// License : MIT -// http://opensource.org/licenses/MIT -// -// https://github.com/sp4cerat/Fast-Quadric-Mesh-Simplification -// -// 5/2016: Chris Rorden created minimal version for OSX/Linux/Windows compile -// https://github.com/sp4cerat/Fast-Quadric-Mesh-Simplification/ -// -// libslic3r refactor by tamasmeszaros - -#ifndef SIMPLIFYMESHIMPL_HPP -#define SIMPLIFYMESHIMPL_HPP - -#include -#include -#include -#include -#include - -#ifndef NDEBUG -#include -#include -#endif - -namespace SimplifyMesh { - -using Bary = std::array; -using Index3 = std::array; - -template struct vertex_traits { - using coord_type = typename Vertex::coord_type; - using compute_type = coord_type; - - static coord_type x(const Vertex &v); - static coord_type& x(Vertex &v); - - static coord_type y(const Vertex &v); - static coord_type& y(Vertex &v); - - static coord_type z(const Vertex &v); - static coord_type& z(Vertex &v); -}; - -template struct mesh_traits { - using vertex_t = typename Mesh::vertex_t; - - static size_t face_count(const Mesh &m); - static size_t vertex_count(const Mesh &m); - static vertex_t vertex(const Mesh &m, size_t vertex_idx); - static void vertex(Mesh &m, size_t vertex_idx, const vertex_t &v); - static Index3 triangle(const Mesh &m, size_t face_idx); - static void triangle(Mesh &m, size_t face_idx, const Index3 &t); - static void update(Mesh &m, size_t vertex_count, size_t face_count); -}; - -namespace implementation { - -// A shorter C++14 style form of the enable_if metafunction -template -using enable_if_t = typename std::enable_if::type; - -// Meta predicates for floating, integer and generic arithmetic types -template -using FloatingOnly = enable_if_t::value, O>; - -template -using IntegerOnly = enable_if_t::value, O>; - -template -using ArithmeticOnly = enable_if_t::value, O>; - -template< class T > -struct remove_cvref { - using type = typename std::remove_cv< - typename std::remove_reference::type>::type; -}; - -template< class T > -using remove_cvref_t = typename remove_cvref::type; - -template FloatingOnly is_approx(T val, T ref) { return std::abs(val - ref) < 1e-8; } -template IntegerOnly is_approx(T val, T ref) { val == ref; } - -template class SymetricMatrix { - static const constexpr size_t N = 10; -public: - - explicit SymetricMatrix(ArithmeticOnly c = T()) { std::fill(m, m + N, c); } - - // Make plane - SymetricMatrix(T a, T b, T c, T d) - { - m[0] = a * a; m[1] = a * b; m[2] = a * c; m[3] = a * d; - m[4] = b * b; m[5] = b * c; m[6] = b * d; - m[7] = c * c; m[8] = c * d; - m[9] = d * d; - } - - T operator[](int c) const { return m[c]; } - - // Determinant - T det(int a11, int a12, int a13, - int a21, int a22, int a23, - int a31, int a32, int a33) const - { - T det = m[a11] * m[a22] * m[a33] + m[a13] * m[a21] * m[a32] + - m[a12] * m[a23] * m[a31] - m[a13] * m[a22] * m[a31] - - m[a11] * m[a23] * m[a32] - m[a12] * m[a21] * m[a33]; - - return det; - } - - const SymetricMatrix& operator+=(const SymetricMatrix& n) - { - for (size_t i = 0; i < N; ++i) m[i] += n[i]; - return *this; - } - - SymetricMatrix operator+(const SymetricMatrix& n) - { - SymetricMatrix self = *this; - return self += n; - } - - T m[N]; -}; - -template using TCoord = typename vertex_traits>::coord_type; -template using TCompute = typename vertex_traits>::compute_type; -template inline TCoord x(const V &v) { return vertex_traits>::x(v); } -template inline TCoord y(const V &v) { return vertex_traits>::y(v); } -template inline TCoord z(const V &v) { return vertex_traits>::z(v); } -template inline TCoord& x(V &v) { return vertex_traits>::x(v); } -template inline TCoord& y(V &v) { return vertex_traits>::y(v); } -template inline TCoord& z(V &v) { return vertex_traits>::z(v); } -template using TVertex = typename mesh_traits>::vertex_t; -template using TMeshCoord = TCoord>; - -template TCompute dot(const Vertex &v1, const Vertex &v2) -{ - return TCompute(x(v1)) * x(v2) + - TCompute(y(v1)) * y(v2) + - TCompute(z(v1)) * z(v2); -} - -template Vertex cross(const Vertex &a, const Vertex &b) -{ - return Vertex{y(a) * z(b) - z(a) * y(b), - z(a) * x(b) - x(a) * z(b), - x(a) * y(b) - y(a) * x(b)}; -} - -template TCompute lengthsq(const Vertex &v) -{ - return TCompute(x(v)) * x(v) + TCompute(y(v)) * y(v) + - TCompute(z(v)) * z(v); -} - -template void normalize(Vertex &v) -{ - double square = std::sqrt(lengthsq(v)); - x(v) /= square; y(v) /= square; z(v) /= square; -} - -using Bary = std::array; - -template -Bary barycentric(const Vertex &p, const Vertex &a, const Vertex &b, const Vertex &c) -{ - Vertex v0 = (b - a); - Vertex v1 = (c - a); - Vertex v2 = (p - a); - - double d00 = dot(v0, v0); - double d01 = dot(v0, v1); - double d11 = dot(v1, v1); - double d20 = dot(v2, v0); - double d21 = dot(v2, v1); - double denom = d00 * d11 - d01 * d01; - double v = (d11 * d20 - d01 * d21) / denom; - double w = (d00 * d21 - d01 * d20) / denom; - double u = 1.0 - v - w; - - return {u, v, w}; -} - -template class SimplifiableMesh { - Mesh *m_mesh; - - using Vertex = TVertex; - using Coord = TMeshCoord; - using HiPrecison = TCompute>; - using SymMat = SymetricMatrix; - - struct FaceInfo { - size_t idx; - double err[4] = {0.}; - bool deleted = false, dirty = false; - Vertex n; - explicit FaceInfo(size_t id): idx(id) {} - }; - - struct VertexInfo { - size_t idx; - size_t tstart = 0, tcount = 0; - bool border = false; - SymMat q; - explicit VertexInfo(size_t id): idx(id) {} - }; - - struct Ref { size_t face; size_t vertex; }; - - std::vector m_refs; - std::vector m_faceinfo; - std::vector m_vertexinfo; - - void compact_faces(); - void compact(); - - size_t mesh_vcount() const { return mesh_traits::vertex_count(*m_mesh); } - size_t mesh_facecount() const { return mesh_traits::face_count(*m_mesh); } - - size_t vcount() const { return m_vertexinfo.size(); } - - inline Vertex read_vertex(size_t vi) const - { - return mesh_traits::vertex(*m_mesh, vi); - } - - inline Vertex read_vertex(const VertexInfo &vinf) const - { - return read_vertex(vinf.idx); - } - - inline void write_vertex(size_t idx, const Vertex &v) const - { - mesh_traits::vertex(*m_mesh, idx, v); - } - - inline void write_vertex(const VertexInfo &vinf, const Vertex &v) const - { - write_vertex(vinf.idx, v); - } - - inline Index3 read_triangle(size_t fi) const - { - return mesh_traits::triangle(*m_mesh, fi); - } - - inline Index3 read_triangle(const FaceInfo &finf) const - { - return read_triangle(finf.idx); - } - - inline void write_triangle(size_t idx, const Index3 &t) - { - return mesh_traits::triangle(*m_mesh, idx, t); - } - - inline void write_triangle(const FaceInfo &finf, const Index3 &t) - { - return write_triangle(finf.idx, t); - } - - inline std::array triangle_vertices(const Index3 &f) const - { - std::array p; - for (size_t i = 0; i < 3; ++i) p[i] = read_vertex(f[i]); - return p; - } - - // Error between vertex and Quadric - static double vertex_error(const SymMat &q, const Vertex &v) - { - Coord _x = x(v) , _y = y(v), _z = z(v); - return q[0] * _x * _x + 2 * q[1] * _x * _y + 2 * q[2] * _x * _z + - 2 * q[3] * _x + q[4] * _y * _y + 2 * q[5] * _y * _z + - 2 * q[6] * _y + q[7] * _z * _z + 2 * q[8] * _z + q[9]; - } - - // Error for one edge - double calculate_error(size_t id_v1, size_t id_v2, Vertex &p_result); - - void calculate_error(FaceInfo &fi) - { - Vertex p; - Index3 t = read_triangle(fi); - for (size_t j = 0; j < 3; ++j) - fi.err[j] = calculate_error(t[j], t[(j + 1) % 3], p); - - fi.err[3] = std::min(fi.err[0], std::min(fi.err[1], fi.err[2])); - } - - void update_mesh(int iteration); - - // Update triangle connections and edge error after a edge is collapsed - void update_triangles(size_t i, VertexInfo &vi, std::vector &deleted, int &deleted_triangles); - - // Check if a triangle flips when this edge is removed - bool flipped(const Vertex &p, size_t i0, size_t i1, VertexInfo &v0, VertexInfo &v1, std::vector &deleted); - -public: - - explicit SimplifiableMesh(Mesh *m) : m_mesh{m} - { - static_assert( - std::is_arithmetic::value, - "Coordinate type of mesh has to be an arithmetic type!"); - - m_faceinfo.reserve(mesh_traits::face_count(*m)); - m_vertexinfo.reserve(mesh_traits::vertex_count(*m)); - for (size_t i = 0; i < mesh_facecount(); ++i) m_faceinfo.emplace_back(i); - for (size_t i = 0; i < mesh_vcount(); ++i) m_vertexinfo.emplace_back(i); - - } - - template void simplify_mesh_lossless(ProgressFn &&fn); - void simplify_mesh_lossless() { simplify_mesh_lossless([](int){}); } -}; - -template void SimplifiableMesh::compact_faces() -{ - auto it = std::remove_if(m_faceinfo.begin(), m_faceinfo.end(), - [](const FaceInfo &inf) { return inf.deleted; }); - - m_faceinfo.erase(it, m_faceinfo.end()); -} - -template void SimplifiableMesh::compact() -{ - for (auto &vi : m_vertexinfo) vi.tcount = 0; - - compact_faces(); - - for (FaceInfo &fi : m_faceinfo) - for (size_t vidx : read_triangle(fi)) m_vertexinfo[vidx].tcount = 1; - - size_t dst = 0; - for (VertexInfo &vi : m_vertexinfo) { - if (vi.tcount) { - vi.tstart = dst; - write_vertex(dst++, read_vertex(vi)); - } - } - - size_t vertex_count = dst; - - dst = 0; - for (const FaceInfo &fi : m_faceinfo) { - Index3 t = read_triangle(fi); - for (size_t &idx : t) idx = m_vertexinfo[idx].tstart; - write_triangle(dst++, t); - } - - mesh_traits::update(*m_mesh, vertex_count, m_faceinfo.size()); -} - -template -double SimplifiableMesh::calculate_error(size_t id_v1, size_t id_v2, Vertex &p_result) -{ - // compute interpolated vertex - - SymMat q = m_vertexinfo[id_v1].q + m_vertexinfo[id_v2].q; - - bool border = m_vertexinfo[id_v1].border & m_vertexinfo[id_v2].border; - double error = 0; - HiPrecison det = q.det(0, 1, 2, 1, 4, 5, 2, 5, 7); - - if (!is_approx(det, HiPrecison(0)) && !border) - { - // q_delta is invertible - x(p_result) = Coord(-1) / det * q.det(1, 2, 3, 4, 5, 6, 5, 7, 8); // vx = A41/det(q_delta) - y(p_result) = Coord( 1) / det * q.det(0, 2, 3, 1, 5, 6, 2, 7, 8); // vy = A42/det(q_delta) - z(p_result) = Coord(-1) / det * q.det(0, 1, 3, 1, 4, 6, 2, 5, 8); // vz = A43/det(q_delta) - - error = vertex_error(q, p_result); - } else { - // det = 0 -> try to find best result - Vertex p1 = read_vertex(id_v1); - Vertex p2 = read_vertex(id_v2); - Vertex p3 = (p1 + p2) / 2; - double error1 = vertex_error(q, p1); - double error2 = vertex_error(q, p2); - double error3 = vertex_error(q, p3); - error = std::min(error1, std::min(error2, error3)); - - if (is_approx(error1, error)) p_result = p1; - if (is_approx(error2, error)) p_result = p2; - if (is_approx(error3, error)) p_result = p3; - } - - return error; -} - -template void SimplifiableMesh::update_mesh(int iteration) -{ - if (iteration > 0) compact_faces(); - - assert(mesh_vcount() == m_vertexinfo.size()); - - // - // Init Quadrics by Plane & Edge Errors - // - // required at the beginning ( iteration == 0 ) - // recomputing during the simplification is not required, - // but mostly improves the result for closed meshes - // - if (iteration == 0) { - - for (VertexInfo &vinf : m_vertexinfo) vinf.q = SymMat{}; - for (FaceInfo &finf : m_faceinfo) { - Index3 t = read_triangle(finf); - std::array p = triangle_vertices(t); - Vertex n = cross(Vertex(p[1] - p[0]), Vertex(p[2] - p[0])); - normalize(n); - finf.n = n; - - for (size_t fi : t) - m_vertexinfo[fi].q += SymMat(x(n), y(n), z(n), -dot(n, p[0])); - - calculate_error(finf); - } - } - - // Init Reference ID list - for (VertexInfo &vi : m_vertexinfo) { vi.tstart = 0; vi.tcount = 0; } - - for (FaceInfo &fi : m_faceinfo) - for (size_t vidx : read_triangle(fi)) - m_vertexinfo[vidx].tcount++; - - size_t tstart = 0; - for (VertexInfo &vi : m_vertexinfo) { - vi.tstart = tstart; - tstart += vi.tcount; - vi.tcount = 0; - } - - // Write References - m_refs.resize(m_faceinfo.size() * 3); - for (size_t i = 0; i < m_faceinfo.size(); ++i) { - const FaceInfo &fi = m_faceinfo[i]; - Index3 t = read_triangle(fi); - for (size_t j = 0; j < 3; ++j) { - VertexInfo &vi = m_vertexinfo[t[j]]; - - assert(vi.tstart + vi.tcount < m_refs.size()); - - Ref &ref = m_refs[vi.tstart + vi.tcount]; - ref.face = i; - ref.vertex = j; - vi.tcount++; - } - } - - // Identify boundary : vertices[].border=0,1 - if (iteration == 0) { - for (VertexInfo &vi: m_vertexinfo) vi.border = false; - - std::vector vcount, vids; - - for (VertexInfo &vi: m_vertexinfo) { - vcount.clear(); - vids.clear(); - - for(size_t j = 0; j < vi.tcount; ++j) { - assert(vi.tstart + j < m_refs.size()); - FaceInfo &fi = m_faceinfo[m_refs[vi.tstart + j].face]; - Index3 t = read_triangle(fi); - - for (size_t fid : t) { - size_t ofs=0; - while (ofs < vcount.size()) - { - if (vids[ofs] == fid) break; - ofs++; - } - if (ofs == vcount.size()) - { - vcount.emplace_back(1); - vids.emplace_back(fid); - } - else - vcount[ofs]++; - } - } - - for (size_t j = 0; j < vcount.size(); ++j) - if(vcount[j] == 1) m_vertexinfo[vids[j]].border = true; - } - } -} - -template -void SimplifiableMesh::update_triangles(size_t i0, - VertexInfo & vi, - std::vector &deleted, - int &deleted_triangles) -{ - Vertex p; - for (size_t k = 0; k < vi.tcount; ++k) { - assert(vi.tstart + k < m_refs.size()); - - Ref &r = m_refs[vi.tstart + k]; - FaceInfo &fi = m_faceinfo[r.face]; - - if (fi.deleted) continue; - - if (deleted[k]) { - fi.deleted = true; - deleted_triangles++; - continue; - } - - Index3 t = read_triangle(fi); - t[r.vertex] = i0; - write_triangle(fi, t); - - fi.dirty = true; - fi.err[0] = calculate_error(t[0], t[1], p); - fi.err[1] = calculate_error(t[1], t[2], p); - fi.err[2] = calculate_error(t[2], t[0], p); - fi.err[3] = std::min(fi.err[0], std::min(fi.err[1], fi.err[2])); - m_refs.emplace_back(r); - } -} - -template -bool SimplifiableMesh::flipped(const Vertex & p, - size_t /*i0*/, - size_t i1, - VertexInfo & v0, - VertexInfo & /*v1*/, - std::vector &deleted) -{ - for (size_t k = 0; k < v0.tcount; ++k) { - size_t ridx = v0.tstart + k; - assert(ridx < m_refs.size()); - - FaceInfo &fi = m_faceinfo[m_refs[ridx].face]; - if (fi.deleted) continue; - - Index3 t = read_triangle(fi); - int s = m_refs[ridx].vertex; - size_t id1 = t[(s+1) % 3]; - size_t id2 = t[(s+2) % 3]; - - if(id1 == i1 || id2 == i1) // delete ? - { - deleted[k] = true; - continue; - } - - Vertex d1 = read_vertex(id1) - p; - normalize(d1); - Vertex d2 = read_vertex(id2) - p; - normalize(d2); - - if (std::abs(dot(d1, d2)) > 0.999) return true; - - Vertex n = cross(d1, d2); - normalize(n); - - deleted[k] = false; - if (dot(n, fi.n) < 0.2) return true; - } - - return false; -} - -template -template void SimplifiableMesh::simplify_mesh_lossless(Fn &&fn) -{ - // init - for (FaceInfo &fi : m_faceinfo) fi.deleted = false; - - // main iteration loop - int deleted_triangles=0; - std::vector deleted0, deleted1; - - for (int iteration = 0; iteration < 9999; iteration ++) { - // update mesh constantly - update_mesh(iteration); - - // clear dirty flag - for (FaceInfo &fi : m_faceinfo) fi.dirty = false; - - // - // All triangles with edges below the threshold will be removed - // - // The following numbers works well for most models. - // If it does not, try to adjust the 3 parameters - // - double threshold = std::numeric_limits::epsilon(); //1.0E-3 EPS; // Really? (tm) - - fn(iteration); - - for (FaceInfo &fi : m_faceinfo) { - if (fi.err[3] > threshold || fi.deleted || fi.dirty) continue; - - for (size_t j = 0; j < 3; ++j) { - if (fi.err[j] > threshold) continue; - - Index3 t = read_triangle(fi); - size_t i0 = t[j]; - VertexInfo &v0 = m_vertexinfo[i0]; - - size_t i1 = t[(j + 1) % 3]; - VertexInfo &v1 = m_vertexinfo[i1]; - - // Border check - if(v0.border != v1.border) continue; - - // Compute vertex to collapse to - Vertex p; - calculate_error(i0, i1, p); - - deleted0.resize(v0.tcount); // normals temporarily - deleted1.resize(v1.tcount); // normals temporarily - - // don't remove if flipped - if (flipped(p, i0, i1, v0, v1, deleted0)) continue; - if (flipped(p, i1, i0, v1, v0, deleted1)) continue; - - // not flipped, so remove edge - write_vertex(v0, p); - v0.q = v1.q + v0.q; - size_t tstart = m_refs.size(); - - update_triangles(i0, v0, deleted0, deleted_triangles); - update_triangles(i0, v1, deleted1, deleted_triangles); - - assert(m_refs.size() >= tstart); - - size_t tcount = m_refs.size() - tstart; - - if(tcount <= v0.tcount) - { - // save ram - if (tcount) { - auto from = m_refs.begin() + tstart, to = from + tcount; - std::copy(from, to, m_refs.begin() + v0.tstart); - } - } - else - // append - v0.tstart = tstart; - - v0.tcount = tcount; - break; - } - } - - if (deleted_triangles <= 0) break; - deleted_triangles = 0; - } - - compact(); -} - -} // namespace implementation -} // namespace SimplifyMesh - -#endif // SIMPLIFYMESHIMPL_HPP diff --git a/tests/libslic3r/CMakeLists.txt b/tests/libslic3r/CMakeLists.txt index 05898db28..6475570c1 100644 --- a/tests/libslic3r/CMakeLists.txt +++ b/tests/libslic3r/CMakeLists.txt @@ -14,7 +14,6 @@ add_executable(${_TEST_NAME}_tests test_mutable_polygon.cpp test_mutable_priority_queue.cpp test_stl.cpp - test_meshsimplify.cpp test_meshboolean.cpp test_marchingsquares.cpp test_timeutils.cpp diff --git a/tests/libslic3r/test_meshboolean.cpp b/tests/libslic3r/test_meshboolean.cpp index 97d03ac23..f1582fe3b 100644 --- a/tests/libslic3r/test_meshboolean.cpp +++ b/tests/libslic3r/test_meshboolean.cpp @@ -3,7 +3,6 @@ #include #include -#include using namespace Slic3r; diff --git a/tests/libslic3r/test_meshsimplify.cpp b/tests/libslic3r/test_meshsimplify.cpp deleted file mode 100644 index d21c3a892..000000000 --- a/tests/libslic3r/test_meshsimplify.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - -//#include - -//TEST_CASE("Mesh simplification", "[mesh_simplify]") { -// Simplify::load_obj(TEST_DATA_DIR PATH_SEPARATOR "zaba.obj"); -// Simplify::simplify_mesh_lossless(); -// Simplify::write_obj("zaba_simplified.obj"); -//} -