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>2018-04-21 19:34:20 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-04-21 19:34:20 +0300
commit83cb3879442ab29cbfc7a0c56af48bef823aa826 (patch)
tree8b327a5ed4c8cad7af7e641e1384a3ded6a54903
parent26ee70099a1864eea2b1ec42d5f000d4bff7e10c (diff)
BLI math: clamped barycentric weight calculation
-rw-r--r--source/blender/blenlib/BLI_math_geom.h18
-rw-r--r--source/blender/blenlib/intern/math_geom.c36
2 files changed, 44 insertions, 10 deletions
diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h
index ffe0ce11cef..ff80d15ea5d 100644
--- a/source/blender/blenlib/BLI_math_geom.h
+++ b/source/blender/blenlib/BLI_math_geom.h
@@ -356,12 +356,18 @@ void transform_point_by_seg_v3(
const float l_dst_p1[3], const float l_dst_p2[3],
const float l_src_p1[3], const float l_src_p2[3]);
-void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2],
- const float co[2], float w[3]);
-void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const float v3[4],
- const float co[2], float w[3]);
-void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const float v3[2], const float v4[2],
- const float co[2], float w[4]);
+void barycentric_weights_v2(
+ const float v1[2], const float v2[2], const float v3[2],
+ const float co[2], float w[3]);
+void barycentric_weights_v2_clamped(
+ const float v1[2], const float v2[2], const float v3[2],
+ const float co[2], float w[3]);
+void barycentric_weights_v2_persp(
+ const float v1[4], const float v2[4], const float v3[4],
+ const float co[2], float w[3]);
+void barycentric_weights_v2_quad(
+ const float v1[2], const float v2[2], const float v3[2], const float v4[2],
+ const float co[2], float w[4]);
bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3]);
int barycentric_inside_triangle_v2(const float w[3]);
diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c
index e179447936a..ee6a3dcc9b3 100644
--- a/source/blender/blenlib/intern/math_geom.c
+++ b/source/blender/blenlib/intern/math_geom.c
@@ -3021,7 +3021,9 @@ bool barycentric_coords_v2(const float v1[2], const float v2[2], const float v3[
* \note This is *exactly* the same calculation as #resolve_tri_uv_v2,
* although it has double precision and is used for texture baking, so keep both.
*/
-void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
+void barycentric_weights_v2(
+ const float v1[2], const float v2[2], const float v3[2],
+ const float co[2], float w[3])
{
float wtot;
@@ -3039,10 +3041,35 @@ void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3
}
/**
+ * A version of #barycentric_weights_v2 that doesn't allow negative weights.
+ * Useful when negative values cause problems and points are only ever slightly outside of the triangle.
+ */
+void barycentric_weights_v2_clamped(
+ const float v1[2], const float v2[2], const float v3[2],
+ const float co[2], float w[3])
+{
+ float wtot;
+
+ w[0] = max_ff(cross_tri_v2(v2, v3, co), 0.0f);
+ w[1] = max_ff(cross_tri_v2(v3, v1, co), 0.0f);
+ w[2] = max_ff(cross_tri_v2(v1, v2, co), 0.0f);
+ wtot = w[0] + w[1] + w[2];
+
+ if (wtot != 0.0f) {
+ mul_v3_fl(w, 1.0f / wtot);
+ }
+ else { /* dummy values for zero area face */
+ copy_v3_fl(w, 1.0f / 3.0f);
+ }
+}
+
+/**
* still use 2D X,Y space but this works for verts transformed by a perspective matrix,
* using their 4th component as a weight
*/
-void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const float v3[4], const float co[2], float w[3])
+void barycentric_weights_v2_persp(
+ const float v1[4], const float v2[4], const float v3[4],
+ const float co[2], float w[3])
{
float wtot;
@@ -3064,8 +3091,9 @@ void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const fl
* note: untested for values outside the quad's bounds
* this is #interp_weights_poly_v2 expanded for quads only
*/
-void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const float v3[2], const float v4[2],
- const float co[2], float w[4])
+void barycentric_weights_v2_quad(
+ const float v1[2], const float v2[2], const float v3[2], const float v4[2],
+ const float co[2], float w[4])
{
/* note: fabsf() here is not needed for convex quads (and not used in interp_weights_poly_v2).
* but in the case of concave/bow-tie quads for the mask rasterizer it gives unreliable results