From e37c4e5819aec1f853fdd71cf60004aa2363f7d9 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 21 May 2015 21:00:27 +1000 Subject: [PATCH] Fix T44780: Decimate planar creates concave edges Float precision was causing problems for decimate, small faces that create a nearly flat surface were detected as having no 'cost' to collapse. --- source/blender/blenlib/BLI_quadric.h | 14 +++--- source/blender/blenlib/intern/quadric.c | 49 +++++++++---------- .../bmesh/tools/bmesh_decimate_collapse.c | 21 ++++---- 3 files changed, 43 insertions(+), 41 deletions(-) diff --git a/source/blender/blenlib/BLI_quadric.h b/source/blender/blenlib/BLI_quadric.h index 251469ab88f..eaf9c7a0738 100644 --- a/source/blender/blenlib/BLI_quadric.h +++ b/source/blender/blenlib/BLI_quadric.h @@ -31,14 +31,14 @@ */ typedef struct Quadric { - float a2, ab, ac, ad, - b2, bc, bd, - c2, cd, - d2; + double a2, ab, ac, ad, + b2, bc, bd, + c2, cd, + d2; } Quadric; /* conversion */ -void BLI_quadric_from_plane(Quadric *q, const float v[4]); +void BLI_quadric_from_plane(Quadric *q, const double v[4]); void BLI_quadric_to_tensor_m3(const Quadric *q, float m[3][3]); void BLI_quadric_to_vector_v3(const Quadric *q, float v[3]); @@ -47,10 +47,10 @@ void BLI_quadric_clear(Quadric *q); /* math */ void BLI_quadric_add_qu_qu(Quadric *a, const Quadric *b); void BLI_quadric_add_qu_ququ(Quadric *r, const Quadric *a, const Quadric *b); -void BLI_quadric_mul(Quadric *a, const float scalar); +void BLI_quadric_mul(Quadric *a, const double scalar); /* solve */ -float BLI_quadric_evaluate(const Quadric *q, const float v[3]); +double BLI_quadric_evaluate(const Quadric *q, const float v_fl[3]); bool BLI_quadric_optimize(const Quadric *q, float v[3], const float epsilon); #endif /* __BLI_QUADRIC_H__ */ diff --git a/source/blender/blenlib/intern/quadric.c b/source/blender/blenlib/intern/quadric.c index 4aa0cdd509d..c1abacee42e 100644 --- a/source/blender/blenlib/intern/quadric.c +++ b/source/blender/blenlib/intern/quadric.c @@ -32,17 +32,15 @@ * \note try to follow BLI_math naming convention here. */ -//#include - #include "BLI_math.h" #include "BLI_strict_flags.h" #include "BLI_quadric.h" /* own include */ -#define QUADRIC_FLT_TOT (sizeof(Quadric) / sizeof(float)) +#define QUADRIC_FLT_TOT (sizeof(Quadric) / sizeof(double)) -void BLI_quadric_from_plane(Quadric *q, const float v[4]) +void BLI_quadric_from_plane(Quadric *q, const double v[4]) { q->a2 = v[0] * v[0]; q->b2 = v[1] * v[1]; @@ -61,24 +59,24 @@ void BLI_quadric_from_plane(Quadric *q, const float v[4]) void BLI_quadric_to_tensor_m3(const Quadric *q, float m[3][3]) { - m[0][0] = q->a2; - m[0][1] = q->ab; - m[0][2] = q->ac; + m[0][0] = (float)q->a2; + m[0][1] = (float)q->ab; + m[0][2] = (float)q->ac; - m[1][0] = q->ab; - m[1][1] = q->b2; - m[1][2] = q->bc; + m[1][0] = (float)q->ab; + m[1][1] = (float)q->b2; + m[1][2] = (float)q->bc; - m[2][0] = q->ac; - m[2][1] = q->bc; - m[2][2] = q->c2; + m[2][0] = (float)q->ac; + m[2][1] = (float)q->bc; + m[2][2] = (float)q->c2; } void BLI_quadric_to_vector_v3(const Quadric *q, float v[3]) { - v[0] = q->ad; - v[1] = q->bd; - v[2] = q->cd; + v[0] = (float)q->ad; + v[1] = (float)q->bd; + v[2] = (float)q->cd; } void BLI_quadric_clear(Quadric *q) @@ -88,25 +86,26 @@ void BLI_quadric_clear(Quadric *q) void BLI_quadric_add_qu_qu(Quadric *a, const Quadric *b) { - add_vn_vn((float *)a, (float *)b, QUADRIC_FLT_TOT); + add_vn_vn_d((double *)a, (double *)b, QUADRIC_FLT_TOT); } void BLI_quadric_add_qu_ququ(Quadric *r, const Quadric *a, const Quadric *b) { - add_vn_vnvn((float *)r, (const float *)a, (const float *)b, QUADRIC_FLT_TOT); + add_vn_vnvn_d((double *)r, (const double *)a, (const double *)b, QUADRIC_FLT_TOT); } -void BLI_quadric_mul(Quadric *a, const float scalar) +void BLI_quadric_mul(Quadric *a, const double scalar) { - mul_vn_fl((float *)a, QUADRIC_FLT_TOT, scalar); + mul_vn_db((double *)a, QUADRIC_FLT_TOT, scalar); } -float BLI_quadric_evaluate(const Quadric *q, const float v[3]) +double BLI_quadric_evaluate(const Quadric *q, const float v_fl[3]) { - return (v[0] * v[0] * q->a2 + 2.0f * v[0] * v[1] * q->ab + 2.0f * v[0] * v[2] * q->ac + 2.0f * v[0] * q->ad + - v[1] * v[1] * q->b2 + 2.0f * v[1] * v[2] * q->bc + 2.0f * v[1] * q->bd + - v[2] * v[2] * q->c2 + 2.0f * v[2] * q->cd + - q->d2); + const double v[3] = {UNPACK3(v_fl)}; + return ((q->a2 * v[0] * v[0]) + (q->ab * 2 * v[0] * v[1]) + (q->ac * 2 * v[0] * v[2]) + (q->ad * 2 * v[0]) + + (q->b2 * v[1] * v[1]) + (q->bc * 2 * v[1] * v[2]) + (q->bd * 2 * v[1]) + + (q->c2 * v[2] * v[2]) + (q->cd * 2 * v[2]) + + (q->d2)); } bool BLI_quadric_optimize(const Quadric *q, float v[3], const float epsilon) diff --git a/source/blender/bmesh/tools/bmesh_decimate_collapse.c b/source/blender/bmesh/tools/bmesh_decimate_collapse.c index fafd4c5ae3f..9b35414f9e6 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/tools/bmesh_decimate_collapse.c @@ -84,14 +84,14 @@ static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics) BMLoop *l_iter; float center[3]; - float plane[4]; + double plane_db[4]; Quadric q; BM_face_calc_center_mean(f, center); - copy_v3_v3(plane, f->no); - plane[3] = -dot_v3v3(plane, center); + copy_v3db_v3fl(plane_db, f->no); + plane_db[3] = -dot_v3db_v3fl(plane_db, center); - BLI_quadric_from_plane(&q, plane); + BLI_quadric_from_plane(&q, plane_db); l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { @@ -103,19 +103,22 @@ static void bm_decim_build_quadrics(BMesh *bm, Quadric *vquadrics) BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { if (UNLIKELY(BM_edge_is_boundary(e))) { float edge_vector[3]; - float edge_plane[4]; + float edge_plane[3]; + double edge_plane_db[4]; sub_v3_v3v3(edge_vector, e->v2->co, e->v1->co); f = e->l->f; - cross_v3_v3v3(edge_plane, edge_vector, f->no); - if (normalize_v3(edge_plane) > FLT_EPSILON) { + cross_v3_v3v3(edge_plane, edge_vector, f->no); + copy_v3db_v3fl(edge_plane_db, edge_plane); + + if (normalize_v3_d(edge_plane_db) > FLT_EPSILON) { Quadric q; float center[3]; mid_v3_v3v3(center, e->v1->co, e->v2->co); - edge_plane[3] = -dot_v3v3(edge_plane, center); - BLI_quadric_from_plane(&q, edge_plane); + edge_plane_db[3] = -dot_v3db_v3fl(edge_plane_db, center); + BLI_quadric_from_plane(&q, edge_plane_db); BLI_quadric_mul(&q, BOUNDARY_PRESERVE_WEIGHT); BLI_quadric_add_qu_qu(&vquadrics[BM_elem_index_get(e->v1)], &q);