diff --git a/src/libslic3r/QuadricEdgeCollapse.cpp b/src/libslic3r/QuadricEdgeCollapse.cpp index c59fa09b6f..da409ff58d 100644 --- a/src/libslic3r/QuadricEdgeCollapse.cpp +++ b/src/libslic3r/QuadricEdgeCollapse.cpp @@ -12,73 +12,83 @@ namespace QuadricEdgeCollapse { using Indices = std::vector; using SymMat = SimplifyMesh::implementation::SymetricMatrix; + // smallest error caused by edges, identify smallest edge in triangle struct Error { - float value; + float value = -1.; // range(0 .. 2), - unsigned char min_index; - Error(float value, unsigned char min_index): value(value), min_index(min_index) { + uint32_t triangle_index = 0; + Error(float value, uint32_t triangle_index) + : value(value) + , triangle_index(triangle_index) + { assert(min_index < 3); } Error() = default; }; using Errors = std::vector; + // merge information together - faster access during processing - struct TriangleInfo - { + struct TriangleInfo { Vec3f n; // normalized normal - speed up calcualtion of q and check flip - Error e; // smallest error caused by edges, identify smallest edge in triangle + unsigned char min_index = 0; // identify edge for minimal Error -> lightweight Error structure TriangleInfo() = default; - bool is_deleted() const { return e.min_index > 2; } - void set_deleted() { e.min_index = 3; } + bool is_deleted() const { return n.x() > 2.f; } + void set_deleted() { n.x() = 3.f; } }; using TriangleInfos = std::vector; - struct VertexInfo - { + struct VertexInfo { SymMat q; // sum quadric of surround triangles - size_t start = 0, count = 0; // vertex neighbor triangles + uint32_t start = 0, count = 0; // vertex neighbor triangles VertexInfo() = default; bool is_deleted() const { return count == 0; } }; using VertexInfos = std::vector; - struct EdgeInfo - { - size_t t_index=0; // triangle index + struct EdgeInfo { + uint32_t t_index=0; // triangle index unsigned char edge = 0; // 0 or 1 or 2 EdgeInfo() = default; }; using EdgeInfos = std::vector; + // DTO for change neighbors + struct CopyEdgeInfo { + uint32_t start; + uint32_t count; + uint32_t move; + CopyEdgeInfo(uint32_t start, uint32_t count, uint32_t move) + : start(start), count(count), move(move) + {} + }; + using CopyEdgeInfos = std::vector; + Vec3f create_normal(const Triangle &triangle, const Vertices &vertices); - double calculate_error(size_t id_v1, size_t id_v2, SymMat & q, const Vertices &vertices); - Vec3f calculate_vertex(size_t id_v1, size_t id_v2, SymMat & q, const Vertices &vertices); + double calculate_error(uint32_t id_v1, uint32_t id_v2, SymMat & q, const Vertices &vertices); + Vec3f calculate_vertex(uint32_t id_v1, uint32_t id_v2, SymMat & q, const Vertices &vertices); // calculate error for vertex and quadrics, triangle quadrics and triangle vertex give zero, only pozitive number double vertex_error(const SymMat &q, const Vec3d &vertex); SymMat create_quadric(const Triangle &t, const Vec3f& normal, const Vertices &vertices); - std::tuple init(const indexed_triangle_set &its); - size_t find_triangle_index1(size_t vi, const VertexInfo& v_info, size_t ti, const EdgeInfos& e_infos, const Indices& indices); - bool is_flipped(const Vec3f &new_vertex, size_t ti0, size_t ti1, const VertexInfo& v_info, + std::tuple init(const indexed_triangle_set &its); + uint32_t find_triangle_index1(uint32_t vi, const VertexInfo& v_info, uint32_t ti, const EdgeInfos& e_infos, const Indices& indices); + bool is_flipped(const Vec3f &new_vertex, uint32_t ti0, uint32_t ti1, const VertexInfo& v_info, const TriangleInfos &t_infos, const EdgeInfos &e_infos, const indexed_triangle_set &its); - // find edge with smallest error in triangle - Error calculate_error(const Triangle& t,const Vertices &vertices, const VertexInfos& v_infos); - // subtract quadric of one triangle from triangle vertex - void sub_quadric(const Triangle &t, const Vec3f& normal, VertexInfos &v_infos, const Vertices &vertices); - - void remove_triangle(EdgeInfos &e_infos, VertexInfo &v_info, size_t ti); - void change_neighbors(EdgeInfos &e_infos, VertexInfos &v_infos, size_t ti0, size_t ti1, - size_t vi0, size_t vi1, size_t vi_top0, const Triangle &t1); - + Error calculate_error(uint32_t ti, const Triangle& t,const Vertices &vertices, const VertexInfos& v_infos, unsigned char& min_index); + void remove_triangle(EdgeInfos &e_infos, VertexInfo &v_info, uint32_t ti); + void change_neighbors(EdgeInfos &e_infos, VertexInfos &v_infos, uint32_t ti0, uint32_t ti1, + uint32_t vi0, uint32_t vi1, uint32_t vi_top0, + const Triangle &t1, CopyEdgeInfos& infos, EdgeInfos &e_infos1); void compact(const VertexInfos &v_infos, const TriangleInfos &t_infos, const EdgeInfos &e_infos, indexed_triangle_set &its); } using namespace QuadricEdgeCollapse; +#ifdef NDEBUG bool check_neighbors(TriangleInfos &t_infos, Indices& indices, VertexInfos & v_infos) { - std::vector t_counts(v_infos.size(), 0); + std::vector t_counts(v_infos.size(), 0); for (size_t i = 0; i < indices.size(); i++) { TriangleInfo &t_info = t_infos[i]; if (t_info.is_deleted()) continue; @@ -114,41 +124,53 @@ bool check_new_vertex(const Vec3f& nv, const Vec3f& v0, const Vec3f& v1) { return true; } -bool Slic3r::its_quadric_edge_collapse(indexed_triangle_set &its, - size_t triangle_count) +#endif // NDEBUG + +void Slic3r::its_quadric_edge_collapse(indexed_triangle_set &its, + uint32_t triangle_count, + float * max_error) { - TriangleInfos t_infos; + TriangleInfos t_infos; // only normals with information about deleted triangle VertexInfos v_infos; EdgeInfos e_infos; - std::tie(t_infos, v_infos, e_infos) = init(its); + Errors errors; + std::tie(t_infos, v_infos, e_infos, errors) = init(its); - static constexpr float max_error = std::numeric_limits::max(); - - auto cmp = [&t_infos](size_t ti0, size_t ti1) -> bool { - const Error &e0 = t_infos[ti0].e; - const Error &e1 = t_infos[ti1].e; - return e0.value < e1.value; - }; - // convert triangle index to priority queue index - std::vector i_convert(its.indices.size(), {0}); - auto setter = [&i_convert](size_t it, size_t index) { i_convert[it] = index; }; - MutablePriorityQueue mpq(std::move(setter), std::move(cmp)); + float max_float = std::numeric_limits::max(); + float last_collapsed_error = 0.f; + if (max_error == nullptr) { + max_error = &max_float; + } + + // convert from triangle index to mutable priority queue index + std::vector ti_2_mpqi(its.indices.size(), {0}); + auto setter = [&ti_2_mpqi](const Error &e, size_t index) { ti_2_mpqi[e.triangle_index] = index; }; + auto less = [](const Error &e1, const Error &e2) -> bool { return e1.value < e2.value; }; + MutablePriorityQueue mpq(std::move(setter), std::move(less)); mpq.reserve(its.indices.size()); - for (size_t i = 0; i < its.indices.size(); i++) mpq.push(i); + for (Error &error :errors) mpq.push(error); - size_t actual_triangle_count = its.indices.size(); + const size_t max_triangle_count_for_one_vertex = 50; + CopyEdgeInfos ceis; + ceis.reserve(max_triangle_count_for_one_vertex); + EdgeInfos e_infos_swap; + e_infos_swap.reserve(max_triangle_count_for_one_vertex); + std::vector changed_triangle_indices; + changed_triangle_indices.reserve(2 * max_triangle_count_for_one_vertex); + + uint32_t actual_triangle_count = its.indices.size(); while (actual_triangle_count > triangle_count && !mpq.empty()) { // triangle index 0 - size_t ti0 = mpq.top(); + Error e = mpq.top(); // copy + if (e.value >= *max_error) break; // Too big error mpq.pop(); + uint32_t ti0 = e.triangle_index; TriangleInfo &t_info0 = t_infos[ti0]; if (t_info0.is_deleted()) continue; - Error &e = t_info0.e; - if (e.value >= max_error) return false; // only flipped triangles const Triangle &t0 = its.indices[ti0]; - size_t vi0 = t0[e.min_index]; - size_t vi1 = t0[(e.min_index+1) %3]; + uint32_t vi0 = t0[t_info0.min_index]; + uint32_t vi1 = t0[(t_info0.min_index+1) %3]; // Need by move of neighbor edge infos in function: change_neighbors if (vi0 > vi1) std::swap(vi0, vi1); VertexInfo &v_info0 = v_infos[vi0]; @@ -161,7 +183,7 @@ bool Slic3r::its_quadric_edge_collapse(indexed_triangle_set &its, Vec3f new_vertex0 = calculate_vertex(vi0, vi1, q, its.vertices); //assert(check_new_vertex(new_vertex0, its.vertices[vi0], its.vertices[vi1])); // set of triangle indices that change quadric - size_t ti1 = (v_info0.count < v_info1.count)? + uint32_t ti1 = (v_info0.count < v_info1.count)? find_triangle_index1(vi1, v_info0, ti0, e_infos, its.indices) : find_triangle_index1(vi0, v_info1, ti0, e_infos, its.indices) ; @@ -169,73 +191,63 @@ bool Slic3r::its_quadric_edge_collapse(indexed_triangle_set &its, is_flipped(new_vertex0, ti0, ti1, v_info1, t_infos, e_infos, its)) { // IMPROVE1: what about other edges in triangle? // IMPROVE2: check mpq top if it is ti1 with same edge - e.value = max_error; + e.value = std::numeric_limits::max(); // error is changed when surround edge is reduced - mpq.push(ti0); + mpq.push(e); continue; } - - std::vector changed_triangle_indices; + last_collapsed_error = e.value; + changed_triangle_indices.clear(); changed_triangle_indices.reserve(v_info0.count + v_info1.count - 4); - - sub_quadric(t0, t_info0.n, v_infos, its.vertices); - TriangleInfo &t_info1 = t_infos[ti1]; - const Triangle &t1 = its.indices[ti1]; - sub_quadric(t1, t_info1.n, v_infos, its.vertices); + // for each vertex0 triangles - size_t v_info0_end = v_info0.start + v_info0.count; - for (size_t di = v_info0.start; di < v_info0_end; ++di) { + uint32_t v_info0_end = v_info0.start + v_info0.count; + for (uint32_t di = v_info0.start; di < v_info0_end; ++di) { assert(di < e_infos.size()); - size_t ti = e_infos[di].t_index; + uint32_t ti = e_infos[di].t_index; if (ti == ti0) continue; // ti0 will be deleted if (ti == ti1) continue; // ti1 will be deleted - sub_quadric(its.indices[ti], t_infos[ti].n, v_infos, its.vertices); changed_triangle_indices.emplace_back(ti); } // for each vertex1 triangles - size_t v_info1_end = v_info1.start + v_info1.count; - for (size_t di = v_info1.start; di < v_info1_end; ++di) { + uint32_t v_info1_end = v_info1.start + v_info1.count; + for (uint32_t di = v_info1.start; di < v_info1_end; ++di) { assert(di < e_infos.size()); EdgeInfo &e_info = e_infos[di]; - size_t ti = e_info.t_index; + uint32_t ti = e_info.t_index; if (ti == ti0) continue; // ti0 will be deleted if (ti == ti1) continue; // ti1 will be deleted Triangle &t = its.indices[ti]; - sub_quadric(t, t_infos[ti].n, v_infos, its.vertices); t[e_info.edge] = vi0; // change index changed_triangle_indices.emplace_back(ti); } + v_info0.q = q; // fix neighbors // vertex index of triangle 0 which is not vi0 nor vi1 - size_t vi_top0 = t0[(e.min_index + 2) % 3]; - change_neighbors(e_infos, v_infos, ti0, ti1, vi0, vi1, vi_top0, t1); + uint32_t vi_top0 = t0[(t_info0.min_index + 2) % 3]; + const Triangle &t1 = its.indices[ti1]; + change_neighbors(e_infos, v_infos, ti0, ti1, vi0, vi1, + vi_top0, t1, ceis, e_infos_swap); // Change vertex // Has to be set after subtract quadric its.vertices[vi0] = new_vertex0; - // add new quadrics - v_info0.q = SymMat(); // zero value - for (size_t ti : changed_triangle_indices) { - const Triangle& t = its.indices[ti]; - TriangleInfo &t_info = t_infos[ti]; - t_info.n = create_normal(t, its.vertices); // new normal - SymMat q = create_quadric(t, t_info.n, its.vertices); - for (const size_t vi: t) v_infos[vi].q += q; - } - - // fix errors - must be after calculate all quadric - mpq.remove(i_convert[ti1]); - for (size_t ti : changed_triangle_indices) { - const Triangle &t = its.indices[ti]; - t_infos[ti].e = calculate_error(t, its.vertices, v_infos); - mpq.update(i_convert[ti]); + // fix errors - must be after set neighbors - v_infos + mpq.remove(ti_2_mpqi[ti1]); + for (uint32_t ti : changed_triangle_indices) { + size_t priority_queue_index = ti_2_mpqi[ti]; + auto iterator = mpq.begin() + priority_queue_index; + TriangleInfo& t_info = t_infos[ti]; + *iterator = calculate_error(ti, its.indices[ti], its.vertices, v_infos, t_info.min_index); + mpq.update(priority_queue_index); } // set triangle(0 + 1) indices as deleted + TriangleInfo &t_info1 = t_infos[ti1]; t_info0.set_deleted(); t_info1.set_deleted(); // triangle counter decrementation @@ -246,10 +258,10 @@ bool Slic3r::its_quadric_edge_collapse(indexed_triangle_set &its, // compact triangle compact(v_infos, t_infos, e_infos, its); - return true; + *max_error = last_collapsed_error; } -Vec3f QuadricEdgeCollapse::create_normal(const Triangle & triangle, +Vec3f QuadricEdgeCollapse::create_normal(const Triangle &triangle, const Vertices &vertices) { const Vec3f &v0 = vertices[triangle[0]]; @@ -261,9 +273,9 @@ Vec3f QuadricEdgeCollapse::create_normal(const Triangle & triangle, return n; } -double QuadricEdgeCollapse::calculate_error(size_t id_v1, - size_t id_v2, - SymMat & q, +double QuadricEdgeCollapse::calculate_error(uint32_t id_v1, + uint32_t id_v2, + SymMat & q, const Vertices &vertices) { double det = q.det(0, 1, 2, 1, 4, 5, 2, 5, 7); @@ -288,8 +300,8 @@ double QuadricEdgeCollapse::calculate_error(size_t id_v1, } // similar as calculate error but focus on new vertex without calculation of error -Vec3f QuadricEdgeCollapse::calculate_vertex(size_t id_v1, - size_t id_v2, +Vec3f QuadricEdgeCollapse::calculate_vertex(uint32_t id_v1, + uint32_t id_v2, SymMat & q, const Vertices &vertices) { @@ -331,13 +343,13 @@ SymMat QuadricEdgeCollapse::create_quadric(const Triangle & t, return SymMat(n.x(), n.y(), n.z(), -n.dot(v0)); } -std::tuple QuadricEdgeCollapse::init( - const indexed_triangle_set &its) +std::tuple +QuadricEdgeCollapse::init(const indexed_triangle_set &its) { TriangleInfos t_infos(its.indices.size()); VertexInfos v_infos(its.vertices.size()); EdgeInfos e_infos(its.indices.size() * 3); - + Errors errors(its.indices.size()); // calculate normals tbb::parallel_for(tbb::blocked_range(0, its.indices.size()), [&](const tbb::blocked_range &range) { @@ -361,7 +373,7 @@ std::tuple QuadricEdgeCollapse::init( } // set offseted starts - size_t triangle_start = 0; + uint32_t triangle_start = 0; for (VertexInfo &v_info : v_infos) { v_info.start = triangle_start; triangle_start += v_info.count; @@ -376,7 +388,7 @@ std::tuple QuadricEdgeCollapse::init( for (size_t i = range.begin(); i < range.end(); ++i) { const Triangle &t = its.indices[i]; TriangleInfo & t_info = t_infos[i]; - t_info.e = calculate_error(t, its.vertices, v_infos); + errors[i] = calculate_error(i, t, its.vertices, v_infos, t_info.min_index); } }); // END parallel for @@ -393,18 +405,18 @@ std::tuple QuadricEdgeCollapse::init( ++v_info.count; } } - return {t_infos, v_infos, e_infos}; + return {t_infos, v_infos, e_infos, errors}; } -size_t QuadricEdgeCollapse::find_triangle_index1(size_t vi, - const VertexInfo &v_info, - size_t ti0, - const EdgeInfos & e_infos, - const Indices &indices) +uint32_t QuadricEdgeCollapse::find_triangle_index1(uint32_t vi, + const VertexInfo &v_info, + uint32_t ti0, + const EdgeInfos & e_infos, + const Indices & indices) { coord_t vi_coord = static_cast(vi); - size_t end = v_info.start + v_info.count; - for (size_t ei = v_info.start; ei < end; ++ei) { + uint32_t end = v_info.start + v_info.count; + for (uint32_t ei = v_info.start; ei < end; ++ei) { const EdgeInfo &e_info = e_infos[ei]; if (e_info.t_index == ti0) continue; const Triangle& t = indices[e_info.t_index]; @@ -417,12 +429,12 @@ size_t QuadricEdgeCollapse::find_triangle_index1(size_t vi, return -1; } -bool QuadricEdgeCollapse::is_flipped(const Vec3f & new_vertex, - size_t ti0, - size_t ti1, - const VertexInfo & v_info, - const TriangleInfos &t_infos, - const EdgeInfos & e_infos, +bool QuadricEdgeCollapse::is_flipped(const Vec3f & new_vertex, + uint32_t ti0, + uint32_t ti1, + const VertexInfo & v_info, + const TriangleInfos & t_infos, + const EdgeInfos & e_infos, const indexed_triangle_set &its) { static const float thr_pos = 1.0f - std::numeric_limits::epsilon(); @@ -456,37 +468,29 @@ bool QuadricEdgeCollapse::is_flipped(const Vec3f & new_vertex, return false; } -Error QuadricEdgeCollapse::calculate_error(const Triangle & t, +Error QuadricEdgeCollapse::calculate_error(uint32_t ti, + const Triangle & t, const Vertices & vertices, - const VertexInfos &v_infos) + const VertexInfos &v_infos, + unsigned char & min_index) { Vec3d error; for (size_t j = 0; j < 3; ++j) { - size_t j2 = (j == 2) ? 0 : (j + 1); - size_t vi0 = t[j]; - size_t vi1 = t[j2]; + size_t j2 = (j == 2) ? 0 : (j + 1); + uint32_t vi0 = t[j]; + uint32_t vi1 = t[j2]; SymMat q(v_infos[vi0].q); // copy q += v_infos[vi1].q; error[j] = calculate_error(vi0, vi1, q, vertices); } - unsigned char min_index = (error[0] < error[1]) ? - ((error[0] < error[2]) ? 0 : 2) : - ((error[1] < error[2]) ? 1 : 2); - return Error(static_cast(error[min_index]), min_index); -} - -void QuadricEdgeCollapse::sub_quadric(const Triangle &t, - const Vec3f& normal, - VertexInfos &v_infos, - const Vertices &vertices) -{ - SymMat quadric = create_quadric(t, normal, vertices); - for (auto vi: t) v_infos[vi].q -= quadric; + min_index = (error[0] < error[1]) ? ((error[0] < error[2]) ? 0 : 2) : + ((error[1] < error[2]) ? 1 : 2); + return Error(static_cast(error[min_index]), ti); } void QuadricEdgeCollapse::remove_triangle(EdgeInfos & e_infos, VertexInfo &v_info, - size_t ti) + uint32_t ti) { auto e_info = e_infos.begin() + v_info.start; auto e_info_end = e_info + v_info.count - 1; @@ -504,19 +508,20 @@ void QuadricEdgeCollapse::remove_triangle(EdgeInfos & e_infos, void QuadricEdgeCollapse::change_neighbors(EdgeInfos & e_infos, VertexInfos & v_infos, - size_t ti0, - size_t ti1, - size_t vi0, - size_t vi1, - size_t vi_top0, - const Triangle &t1) + uint32_t ti0, + uint32_t ti1, + uint32_t vi0, + uint32_t vi1, + uint32_t vi_top0, + const Triangle &t1, + CopyEdgeInfos& infos, + EdgeInfos & e_infos1) { // have to copy Edge info from higher vertex index into smaller assert(vi0 < vi1); - // vertex index of triangle 1 which is not vi0 nor vi1 - size_t vi_top1 = t1[0]; + uint32_t vi_top1 = t1[0]; if (vi_top1 == vi0 || vi_top1 == vi1) { vi_top1 = t1[1]; if (vi_top1 == vi0 || vi_top1 == vi1) vi_top1 = t1[2]; @@ -528,15 +533,15 @@ void QuadricEdgeCollapse::change_neighbors(EdgeInfos & e_infos, VertexInfo &v_info0 = v_infos[vi0]; VertexInfo &v_info1 = v_infos[vi1]; - size_t new_triangle_count = v_info0.count + v_info1.count - 4; + uint32_t new_triangle_count = v_info0.count + v_info1.count - 4; remove_triangle(e_infos, v_info0, ti0); remove_triangle(e_infos, v_info0, ti1); // copy second's edge infos out of e_infos, to free size - EdgeInfos e_infos1; + e_infos1.clear(); e_infos1.reserve(v_info1.count - 2); - size_t v_info_s_end = v_info1.start + v_info1.count; - for (size_t ei = v_info1.start; ei < v_info_s_end; ++ei) { + uint32_t v_info_s_end = v_info1.start + v_info1.count; + for (uint32_t ei = v_info1.start; ei < v_info_s_end; ++ei) { const EdgeInfo &e_info = e_infos[ei]; if (e_info.t_index == ti0) continue; if (e_info.t_index == ti1) continue; @@ -544,33 +549,25 @@ void QuadricEdgeCollapse::change_neighbors(EdgeInfos & e_infos, } v_info1.count = 0; - size_t need = (new_triangle_count < v_info0.count)? 0: + uint32_t need = (new_triangle_count < v_info0.count)? 0: (new_triangle_count - v_info0.count); - size_t act_vi = vi0 + 1; + uint32_t act_vi = vi0 + 1; VertexInfo *act_v_info = &v_infos[act_vi]; - size_t act_start = act_v_info->start; - size_t last_end = v_info0.start + v_info0.count; + uint32_t act_start = act_v_info->start; + uint32_t last_end = v_info0.start + v_info0.count; + + infos.clear(); + infos.reserve(need); - struct CopyEdgeInfo - { - size_t start; - size_t count; - unsigned char move; - CopyEdgeInfo(size_t start, size_t count, unsigned char move) - : start(start), count(count), move(move) - {} - }; - std::vector c_infos; - c_infos.reserve(need); while (true) { - size_t save = act_start - last_end; + uint32_t save = act_start - last_end; if (save > 0) { if (save >= need) break; need -= save; - c_infos.emplace_back(act_v_info->start, act_v_info->count, need); + infos.emplace_back(act_v_info->start, act_v_info->count, need); } else { - c_infos.back().count += act_v_info->count; + infos.back().count += act_v_info->count; } last_end = act_v_info->start + act_v_info->count; act_v_info->start += need; @@ -583,15 +580,15 @@ void QuadricEdgeCollapse::change_neighbors(EdgeInfos & e_infos, } // copy by c_infos - for (size_t i = c_infos.size(); i > 0; --i) { - const CopyEdgeInfo &c_info = c_infos[i - 1]; - for (size_t ei = c_info.start + c_info.count - 1; ei >= c_info.start; --ei) + for (uint32_t i = infos.size(); i > 0; --i) { + const CopyEdgeInfo &c_info = infos[i - 1]; + for (uint32_t ei = c_info.start + c_info.count - 1; ei >= c_info.start; --ei) e_infos[ei + c_info.move] = e_infos[ei]; // copy } // copy triangle from first info into second - for (size_t ei_s = 0; ei_s < e_infos1.size(); ++ei_s) { - size_t ei_f = v_info0.start + v_info0.count; + for (uint32_t ei_s = 0; ei_s < e_infos1.size(); ++ei_s) { + uint32_t ei_f = v_info0.start + v_info0.count; e_infos[ei_f] = e_infos1[ei_s]; // copy ++v_info0.count; } @@ -602,12 +599,12 @@ void QuadricEdgeCollapse::compact(const VertexInfos & v_infos, const EdgeInfos & e_infos, indexed_triangle_set &its) { - size_t vi_new = 0; - for (size_t vi = 0; vi < v_infos.size(); vi++) { + uint32_t vi_new = 0; + for (uint32_t vi = 0; vi < v_infos.size(); ++vi) { const VertexInfo &v_info = v_infos[vi]; if (v_info.is_deleted()) continue; // deleted - size_t e_info_end = v_info.start + v_info.count; - for (size_t ei = v_info.start; ei < e_info_end; ei++) { + uint32_t e_info_end = v_info.start + v_info.count; + for (uint32_t ei = v_info.start; ei < e_info_end; ++ei) { const EdgeInfo &e_info = e_infos[ei]; // change vertex index its.indices[e_info.t_index][e_info.edge] = vi_new; @@ -618,8 +615,8 @@ void QuadricEdgeCollapse::compact(const VertexInfos & v_infos, // remove vertices tail its.vertices.erase(its.vertices.begin() + vi_new, its.vertices.end()); - size_t ti_new = 0; - for (size_t ti = 0; ti < t_infos.size(); ti++) { + uint32_t ti_new = 0; + for (uint32_t ti = 0; ti < t_infos.size(); ti++) { const TriangleInfo &t_info = t_infos[ti]; if (t_info.is_deleted()) continue; its.indices[ti_new++] = its.indices[ti]; diff --git a/src/libslic3r/QuadricEdgeCollapse.hpp b/src/libslic3r/QuadricEdgeCollapse.hpp index d435656b20..422227d288 100644 --- a/src/libslic3r/QuadricEdgeCollapse.hpp +++ b/src/libslic3r/QuadricEdgeCollapse.hpp @@ -2,6 +2,7 @@ // sum up: https://users.csc.calpoly.edu/~zwood/teaching/csc570/final06/jseeba/ // inspiration: https://github.com/sp4cerat/Fast-Quadric-Mesh-Simplification +#include #include "TriangleMesh.hpp" namespace Slic3r { @@ -10,8 +11,13 @@ namespace Slic3r { /// Simplify mesh by Quadric metric /// /// IN/OUT triangle mesh to be simplified. -/// wanted triangle count. -/// TRUE on success otherwise FALSE -bool its_quadric_edge_collapse(indexed_triangle_set &its, size_t triangle_count); +/// Wanted triangle count. +/// Maximal Quadric for reduce. +/// When nullptr then max float is used +/// Output: Last used ErrorValue to collapse edge +/// +void its_quadric_edge_collapse(indexed_triangle_set &its, + uint32_t triangle_count = 0, + float * max_error = nullptr); } // namespace Slic3r