[Bf-blender-cvs] [457596d4df7] master: BMesh: move safe loop-normal-calc to own function

Campbell Barton noreply at git.blender.org
Wed Jul 12 15:04:49 CEST 2017


Commit: 457596d4df7be80c8ed47dd2d07952588771192d
Author: Campbell Barton
Date:   Wed Jul 12 23:06:59 2017 +1000
Branches: master
https://developer.blender.org/rB457596d4df7be80c8ed47dd2d07952588771192d

BMesh: move safe loop-normal-calc to own function

This makes sense when we want to avoid float precision error
for near co-linear edges. OTOH, this is an arbitrary decision,
so keep functions separate.

===================================================================

M	source/blender/blenkernel/intern/editderivedmesh.c
M	source/blender/bmesh/intern/bmesh_queries.c
M	source/blender/bmesh/intern/bmesh_queries.h

===================================================================

diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index a91983c001c..ab614b8f460 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -2641,7 +2641,7 @@ static void statvis_calc_distort(
 					              vertexCos[BM_elem_index_get(l_iter->next->v)]);
 				}
 				else {
-					BM_loop_calc_face_normal(l_iter, no_corner);
+					BM_loop_calc_face_normal_safe(l_iter, no_corner);
 				}
 				/* simple way to detect (what is most likely) concave */
 				if (dot_v3v3(f_no, no_corner) < 0.0f) {
diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c
index f5c14304ea3..5e8ae696db2 100644
--- a/source/blender/bmesh/intern/bmesh_queries.c
+++ b/source/blender/bmesh/intern/bmesh_queries.c
@@ -1511,12 +1511,11 @@ float BM_loop_calc_face_angle(const BMLoop *l)
  * Calculate the normal at this loop corner or fallback to the face normal on straight lines.
  *
  * \param l The loop to calculate the normal at
+ * \param epsilon: Value to avoid numeric errors (1e-5f works well).
  * \param r_normal Resulting normal
  */
-void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
+float BM_loop_calc_face_normal_safe_ex(const BMLoop *l, float epsilon_sq, float r_normal[3])
 {
-#define FEPSILON 1e-5f
-
 	/* Note: we cannot use result of normal_tri_v3 here to detect colinear vectors (vertex on a straight line)
 	 * from zero value, because it does not normalize both vectors before making crossproduct.
 	 * Instead of adding two costly normalize computations, just check ourselves for colinear case. */
@@ -1525,20 +1524,55 @@ void BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
 	sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
 	sub_v3_v3v3(v2, l->next->v->co, l->v->co);
 
-	const float fac = (v2[0] == 0.0f) ? ((v2[1] == 0.0f) ? ((v2[2] == 0.0f) ? 0.0f : v1[2] / v2[2]) : v1[1] / v2[1]) : v1[0] / v2[0];
+	const float fac =
+	        ((v2[0] == 0.0f) ?
+	        ((v2[1] == 0.0f) ?
+	        ((v2[2] == 0.0f) ?  0.0f : v1[2] / v2[2]) : v1[1] / v2[1]) : v1[0] / v2[0]);
 
 	mul_v3_v3fl(v_tmp, v2, fac);
 	sub_v3_v3(v_tmp, v1);
-	if (fac != 0.0f && !is_zero_v3(v1) && len_manhattan_v3(v_tmp) > FEPSILON) {
+	if (fac != 0.0f && !is_zero_v3(v1) && len_squared_v3(v_tmp) > epsilon_sq) {
 		/* Not co-linear, we can compute crossproduct and normalize it into normal. */
 		cross_v3_v3v3(r_normal, v1, v2);
-		normalize_v3(r_normal);
+		return normalize_v3(r_normal);
 	}
 	else {
 		copy_v3_v3(r_normal, l->f->no);
+		return 0.0f;
 	}
+}
+
+/**
+ * #BM_loop_calc_face_normal_safe_ex with pre-defined sane epsilon.
+ *
+ * Since this doesn't scale baed on triangle size, fixed value works well.
+ */
+float BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3])
+{
+	return BM_loop_calc_face_normal_safe_ex(l, 1e-5f, r_normal);
+}
 
-#undef FEPSILON
+/**
+ * \brief BM_loop_calc_face_normal
+ *
+ * Calculate the normal at this loop corner or fallback to the face normal on straight lines.
+ *
+ * \param l The loop to calculate the normal at
+ * \param r_normal Resulting normal
+ * \return The length of the cross product (double the area).
+ */
+float BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3])
+{
+	float v1[3], v2[3];
+	sub_v3_v3v3(v1, l->prev->v->co, l->v->co);
+	sub_v3_v3v3(v2, l->next->v->co, l->v->co);
+
+	cross_v3_v3v3(r_normal, v1, v2);
+	const float len = normalize_v3(r_normal);
+	if (UNLIKELY(len == 0.0f)) {
+		copy_v3_v3(r_normal, l->f->no);
+	}
+	return len;
 }
 
 /**
diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h
index 903fdc59cb8..83977fa8be0 100644
--- a/source/blender/bmesh/intern/bmesh_queries.h
+++ b/source/blender/bmesh/intern/bmesh_queries.h
@@ -113,7 +113,9 @@ BMLoop *BM_loop_find_prev_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq
 BMLoop *BM_loop_find_next_nodouble(BMLoop *l, BMLoop *l_stop, const float eps_sq);
 
 float   BM_loop_calc_face_angle(const BMLoop *l) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
-void    BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
+float   BM_loop_calc_face_normal(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
+float   BM_loop_calc_face_normal_safe(const BMLoop *l, float r_normal[3]) ATTR_NONNULL();
+float   BM_loop_calc_face_normal_safe_ex(const BMLoop *l, const float epsilon, float r_normal[3]) ATTR_NONNULL();
 void    BM_loop_calc_face_direction(const BMLoop *l, float r_normal[3]);
 void    BM_loop_calc_face_tangent(const BMLoop *l, float r_tangent[3]);




More information about the Bf-blender-cvs mailing list