BLI math: clamped barycentric weight calculation
authorCampbell Barton <ideasman42@gmail.com>
Sat, 21 Apr 2018 16:34:20 +0000 (18:34 +0200)
committerCampbell Barton <ideasman42@gmail.com>
Sat, 21 Apr 2018 16:34:20 +0000 (18:34 +0200)
source/blender/blenlib/BLI_math_geom.h
source/blender/blenlib/intern/math_geom.c

index ffe0ce11ceff264751663bca48cd9cbc25d8c8cd..ff80d15ea5d75543bed1f5b933194de8c443d95c 100644 (file)
@@ -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]);
index e179447936a737814d7df13180c0dd398394db2b..ee6a3dcc9b39ff097b4a3edf9bc4b01823b01d14 100644 (file)
@@ -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;
 
@@ -3038,11 +3040,36 @@ 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