Parallel QEC initialization
This commit is contained in:
parent
892c246700
commit
1196fac551
1 changed files with 54 additions and 48 deletions
|
@ -54,17 +54,16 @@ namespace QuadricEdgeCollapse {
|
||||||
Vec3f calculate_vertex(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);
|
||||||
// calculate error for vertex and quadrics, triangle quadrics and triangle vertex give zero, only pozitive number
|
// 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);
|
double vertex_error(const SymMat &q, const Vec3d &vertex);
|
||||||
SymMat create_quadric(const Triangle &t, const TriangleInfo &t_info, const Vertices &vertices);
|
SymMat create_quadric(const Triangle &t, const Vec3f& normal, const Vertices &vertices);
|
||||||
std::tuple<TriangleInfos, VertexInfos, EdgeInfos> init(const indexed_triangle_set &its);
|
std::tuple<TriangleInfos, VertexInfos, EdgeInfos> 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);
|
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 &vn, const Vec3f &v1, const Vec3f &v2, const Vec3f &normal);
|
bool is_flipped(const Vec3f &new_vertex, size_t ti0, size_t ti1, const VertexInfo& v_info,
|
||||||
bool is_flipped(Vec3f &new_vertex, size_t ti0, size_t ti1, const VertexInfo& v_info,
|
|
||||||
const TriangleInfos &t_infos, const EdgeInfos &e_infos, const indexed_triangle_set &its);
|
const TriangleInfos &t_infos, const EdgeInfos &e_infos, const indexed_triangle_set &its);
|
||||||
|
|
||||||
// find edge with smallest error in triangle
|
// find edge with smallest error in triangle
|
||||||
Error calculate_error(const Triangle& t,const Vertices &vertices, const VertexInfos& v_infos);
|
Error calculate_error(const Triangle& t,const Vertices &vertices, const VertexInfos& v_infos);
|
||||||
// subtract quadric of one triangle from triangle vertex
|
// subtract quadric of one triangle from triangle vertex
|
||||||
void sub_quadric(const Triangle &t, const TriangleInfo &t_info, VertexInfos &v_infos, const Vertices &vertices);
|
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 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,
|
void change_neighbors(EdgeInfos &e_infos, VertexInfos &v_infos, size_t ti0, size_t ti1,
|
||||||
|
@ -178,10 +177,10 @@ bool Slic3r::its_quadric_edge_collapse(indexed_triangle_set &its,
|
||||||
std::vector<size_t> changed_triangle_indices;
|
std::vector<size_t> changed_triangle_indices;
|
||||||
changed_triangle_indices.reserve(v_info0.count + v_info1.count - 4);
|
changed_triangle_indices.reserve(v_info0.count + v_info1.count - 4);
|
||||||
|
|
||||||
sub_quadric(t0, t_info0, v_infos, its.vertices);
|
sub_quadric(t0, t_info0.n, v_infos, its.vertices);
|
||||||
TriangleInfo &t_info1 = t_infos[ti1];
|
TriangleInfo &t_info1 = t_infos[ti1];
|
||||||
const Triangle &t1 = its.indices[ti1];
|
const Triangle &t1 = its.indices[ti1];
|
||||||
sub_quadric(t1, t_info1, v_infos, its.vertices);
|
sub_quadric(t1, t_info1.n, v_infos, its.vertices);
|
||||||
// for each vertex0 triangles
|
// for each vertex0 triangles
|
||||||
size_t v_info0_end = v_info0.start + v_info0.count;
|
size_t v_info0_end = v_info0.start + v_info0.count;
|
||||||
for (size_t di = v_info0.start; di < v_info0_end; ++di) {
|
for (size_t di = v_info0.start; di < v_info0_end; ++di) {
|
||||||
|
@ -190,7 +189,7 @@ bool Slic3r::its_quadric_edge_collapse(indexed_triangle_set &its,
|
||||||
size_t ti = e_info.t_index;
|
size_t ti = e_info.t_index;
|
||||||
if (ti == ti0) continue; // ti0 will be deleted
|
if (ti == ti0) continue; // ti0 will be deleted
|
||||||
if (ti == ti1) continue; // ti1 will be deleted
|
if (ti == ti1) continue; // ti1 will be deleted
|
||||||
sub_quadric(its.indices[ti], t_infos[ti], v_infos, its.vertices);
|
sub_quadric(its.indices[ti], t_infos[ti].n, v_infos, its.vertices);
|
||||||
changed_triangle_indices.emplace_back(ti);
|
changed_triangle_indices.emplace_back(ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +202,7 @@ bool Slic3r::its_quadric_edge_collapse(indexed_triangle_set &its,
|
||||||
if (ti == ti0) continue; // ti0 will be deleted
|
if (ti == ti0) continue; // ti0 will be deleted
|
||||||
if (ti == ti1) continue; // ti1 will be deleted
|
if (ti == ti1) continue; // ti1 will be deleted
|
||||||
Triangle &t = its.indices[ti];
|
Triangle &t = its.indices[ti];
|
||||||
sub_quadric(t, t_infos[ti], v_infos, its.vertices);
|
sub_quadric(t, t_infos[ti].n, v_infos, its.vertices);
|
||||||
t[e_info.edge] = vi0; // change index
|
t[e_info.edge] = vi0; // change index
|
||||||
changed_triangle_indices.emplace_back(ti);
|
changed_triangle_indices.emplace_back(ti);
|
||||||
}
|
}
|
||||||
|
@ -224,7 +223,7 @@ bool Slic3r::its_quadric_edge_collapse(indexed_triangle_set &its,
|
||||||
const Triangle& t = its.indices[ti];
|
const Triangle& t = its.indices[ti];
|
||||||
TriangleInfo &t_info = t_infos[ti];
|
TriangleInfo &t_info = t_infos[ti];
|
||||||
t_info.n = create_normal(t, its.vertices); // new normal
|
t_info.n = create_normal(t, its.vertices); // new normal
|
||||||
SymMat q = create_quadric(t, t_info, its.vertices);
|
SymMat q = create_quadric(t, t_info.n, its.vertices);
|
||||||
for (const size_t vi: t) v_infos[vi].q += q;
|
for (const size_t vi: t) v_infos[vi].q += q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,10 +324,10 @@ double QuadricEdgeCollapse::vertex_error(const SymMat &q, const Vec3d &vertex)
|
||||||
}
|
}
|
||||||
|
|
||||||
SymMat QuadricEdgeCollapse::create_quadric(const Triangle & t,
|
SymMat QuadricEdgeCollapse::create_quadric(const Triangle & t,
|
||||||
const TriangleInfo &t_info,
|
const Vec3f &normal,
|
||||||
const Vertices & vertices)
|
const Vertices & vertices)
|
||||||
{
|
{
|
||||||
Vec3d n = t_info.n.cast<double>();
|
Vec3d n = normal.cast<double>();
|
||||||
Vec3d v0 = vertices[t[0]].cast<double>();
|
Vec3d v0 = vertices[t[0]].cast<double>();
|
||||||
return SymMat(n.x(), n.y(), n.z(), -n.dot(v0));
|
return SymMat(n.x(), n.y(), n.z(), -n.dot(v0));
|
||||||
}
|
}
|
||||||
|
@ -340,11 +339,21 @@ std::tuple<TriangleInfos, VertexInfos, EdgeInfos> QuadricEdgeCollapse::init(
|
||||||
VertexInfos v_infos(its.vertices.size());
|
VertexInfos v_infos(its.vertices.size());
|
||||||
EdgeInfos e_infos(its.indices.size() * 3);
|
EdgeInfos e_infos(its.indices.size() * 3);
|
||||||
|
|
||||||
for (size_t i = 0; i < its.indices.size(); i++) {
|
// calculate normals
|
||||||
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, its.indices.size()),
|
||||||
|
[&](const tbb::blocked_range<size_t> &range) {
|
||||||
|
for (size_t i = range.begin(); i < range.end(); ++i) {
|
||||||
const Triangle &t = its.indices[i];
|
const Triangle &t = its.indices[i];
|
||||||
TriangleInfo & t_info = t_infos[i];
|
TriangleInfo & t_info = t_infos[i];
|
||||||
t_info.n = create_normal(t, its.vertices);
|
t_info.n = create_normal(t, its.vertices);
|
||||||
SymMat q = create_quadric(t, t_info, its.vertices);
|
}
|
||||||
|
}); // END parallel for
|
||||||
|
|
||||||
|
// sum quadrics
|
||||||
|
for (size_t i = 0; i < its.indices.size(); i++) {
|
||||||
|
const Triangle &t = its.indices[i];
|
||||||
|
TriangleInfo &t_info = t_infos[i];
|
||||||
|
SymMat q = create_quadric(t, t_info.n, its.vertices);
|
||||||
for (size_t e = 0; e < 3; e++) {
|
for (size_t e = 0; e < 3; e++) {
|
||||||
VertexInfo &v_info = v_infos[t[e]];
|
VertexInfo &v_info = v_infos[t[e]];
|
||||||
v_info.q += q;
|
v_info.q += q;
|
||||||
|
@ -362,11 +371,19 @@ std::tuple<TriangleInfos, VertexInfos, EdgeInfos> QuadricEdgeCollapse::init(
|
||||||
}
|
}
|
||||||
assert(its.indices.size() * 3 == triangle_start);
|
assert(its.indices.size() * 3 == triangle_start);
|
||||||
|
|
||||||
// calc error + create reference
|
// calc error
|
||||||
for (size_t i = 0; i < its.indices.size(); i++) {
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, its.indices.size()),
|
||||||
|
[&](const tbb::blocked_range<size_t> &range) {
|
||||||
|
for (size_t i = range.begin(); i < range.end(); ++i) {
|
||||||
const Triangle &t = its.indices[i];
|
const Triangle &t = its.indices[i];
|
||||||
TriangleInfo & t_info = t_infos[i];
|
TriangleInfo & t_info = t_infos[i];
|
||||||
t_info.e = calculate_error(t, its.vertices, v_infos);
|
t_info.e = calculate_error(t, its.vertices, v_infos);
|
||||||
|
}
|
||||||
|
}); // END parallel for
|
||||||
|
|
||||||
|
// create reference
|
||||||
|
for (size_t i = 0; i < its.indices.size(); i++) {
|
||||||
|
const Triangle &t = its.indices[i];
|
||||||
for (size_t j = 0; j < 3; ++j) {
|
for (size_t j = 0; j < 3; ++j) {
|
||||||
VertexInfo &v_info = v_infos[t[j]];
|
VertexInfo &v_info = v_infos[t[j]];
|
||||||
size_t ei = v_info.start + v_info.count;
|
size_t ei = v_info.start + v_info.count;
|
||||||
|
@ -401,32 +418,7 @@ size_t QuadricEdgeCollapse::find_triangle_index1(size_t vi,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QuadricEdgeCollapse::is_flipped(const Vec3f & new_vertex,
|
||||||
bool QuadricEdgeCollapse::is_flipped(const Vec3f &vn,
|
|
||||||
const Vec3f &v1,
|
|
||||||
const Vec3f &v2,
|
|
||||||
const Vec3f &normal)
|
|
||||||
{
|
|
||||||
static const float thr_pos = 1.0f - std::numeric_limits<float>::epsilon();
|
|
||||||
static const float thr_neg = -thr_pos;
|
|
||||||
static const float dot_thr = 0.2f; // Value from simplify mesh
|
|
||||||
|
|
||||||
Vec3f d1 = v1 - vn;
|
|
||||||
d1.normalize();
|
|
||||||
Vec3f d2 = v2 - vn;
|
|
||||||
d2.normalize();
|
|
||||||
|
|
||||||
float dot = d1.dot(d2);
|
|
||||||
if (dot > thr_pos || dot < thr_neg) return true;
|
|
||||||
|
|
||||||
// IMPROVE: propagate new normal
|
|
||||||
Vec3f n = d1.cross(d2);
|
|
||||||
n.normalize();
|
|
||||||
return n.dot(normal) < dot_thr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool QuadricEdgeCollapse::is_flipped(Vec3f & new_vertex,
|
|
||||||
size_t ti0,
|
size_t ti0,
|
||||||
size_t ti1,
|
size_t ti1,
|
||||||
const VertexInfo & v_info,
|
const VertexInfo & v_info,
|
||||||
|
@ -434,6 +426,10 @@ bool QuadricEdgeCollapse::is_flipped(Vec3f & new_vertex,
|
||||||
const EdgeInfos & e_infos,
|
const EdgeInfos & e_infos,
|
||||||
const indexed_triangle_set &its)
|
const indexed_triangle_set &its)
|
||||||
{
|
{
|
||||||
|
static const float thr_pos = 1.0f - std::numeric_limits<float>::epsilon();
|
||||||
|
static const float thr_neg = -thr_pos;
|
||||||
|
static const float dot_thr = 0.2f; // Value from simplify mesh cca 80 DEG
|
||||||
|
|
||||||
// for each vertex triangles
|
// for each vertex triangles
|
||||||
size_t v_info_end = v_info.start + v_info.count;
|
size_t v_info_end = v_info.start + v_info.count;
|
||||||
for (size_t ei = v_info.start; ei < v_info_end; ++ei) {
|
for (size_t ei = v_info.start; ei < v_info_end; ++ei) {
|
||||||
|
@ -445,8 +441,18 @@ bool QuadricEdgeCollapse::is_flipped(Vec3f & new_vertex,
|
||||||
const Vec3f &normal = t_infos[e_info.t_index].n;
|
const Vec3f &normal = t_infos[e_info.t_index].n;
|
||||||
const Vec3f &vf = its.vertices[t[(e_info.edge + 1) % 3]];
|
const Vec3f &vf = its.vertices[t[(e_info.edge + 1) % 3]];
|
||||||
const Vec3f &vs = its.vertices[t[(e_info.edge + 2) % 3]];
|
const Vec3f &vs = its.vertices[t[(e_info.edge + 2) % 3]];
|
||||||
if (is_flipped(new_vertex, vf, vs, normal))
|
|
||||||
return true;
|
Vec3f d1 = vf - new_vertex;
|
||||||
|
d1.normalize();
|
||||||
|
Vec3f d2 = vs - new_vertex;
|
||||||
|
d2.normalize();
|
||||||
|
|
||||||
|
float dot = d1.dot(d2);
|
||||||
|
if (dot > thr_pos || dot < thr_neg) return true;
|
||||||
|
// IMPROVE: propagate new normal
|
||||||
|
Vec3f n = d1.cross(d2);
|
||||||
|
n.normalize();
|
||||||
|
if(n.dot(normal) < dot_thr) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -471,12 +477,12 @@ Error QuadricEdgeCollapse::calculate_error(const Triangle & t,
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuadricEdgeCollapse::sub_quadric(const Triangle &t,
|
void QuadricEdgeCollapse::sub_quadric(const Triangle &t,
|
||||||
const TriangleInfo & t_info,
|
const Vec3f& normal,
|
||||||
VertexInfos &v_infos,
|
VertexInfos &v_infos,
|
||||||
const Vertices &vertices)
|
const Vertices &vertices)
|
||||||
{
|
{
|
||||||
SymMat quadric = create_quadric(t, t_info, vertices);
|
SymMat quadric = create_quadric(t, normal, vertices);
|
||||||
for (size_t vi: t) v_infos[vi].q -= quadric;
|
for (auto vi: t) v_infos[vi].q -= quadric;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QuadricEdgeCollapse::remove_triangle(EdgeInfos & e_infos,
|
void QuadricEdgeCollapse::remove_triangle(EdgeInfos & e_infos,
|
||||||
|
|
Loading…
Reference in a new issue