Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2017-07-12 16:06:59 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-07-12 16:13:04 +0300
commit457596d4df7be80c8ed47dd2d07952588771192d (patch)
tree354e0066d835c006bf12a0d0e524338308f024a2 /source/blender/bmesh
parent87164114a306d5dc9f609695c0c6a8e36d79673d (diff)
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.
Diffstat (limited to 'source/blender/bmesh')
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.c48
-rw-r--r--source/blender/bmesh/intern/bmesh_queries.h4
2 files changed, 44 insertions, 8 deletions
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]);