[Bf-blender-cvs] [fc9f1b1754b] blender-v2.91-release: Fix T81988: Surface Deform "Bind" causes vertices to spike

Campbell Barton noreply at git.blender.org
Tue Nov 3 10:53:05 CET 2020


Commit: fc9f1b1754bbafa262f875969f7e1bb2554802a3
Author: Campbell Barton
Date:   Tue Nov 3 20:26:36 2020 +1100
Branches: blender-v2.91-release
https://developer.blender.org/rBfc9f1b1754bbafa262f875969f7e1bb2554802a3

Fix T81988: Surface Deform "Bind" causes vertices to spike

Surface deform weight calculation assigned weights in a non-uniform
way that caused vertices to deform upon binding.

This was caused by the face-corner angle being used in
calculations which where squared & scaled.
Causing a triangle fan of many thin faces to have a much greater
influence compared to the same shape made from a single triangle.

Change the calculation of the weight so each face-corner is scaled
by it's angle.

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

M	source/blender/modifiers/intern/MOD_surfacedeform.c

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

diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c
index aef7df3282f..aa48eaa6a32 100644
--- a/source/blender/modifiers/intern/MOD_surfacedeform.c
+++ b/source/blender/modifiers/intern/MOD_surfacedeform.c
@@ -424,15 +424,9 @@ static void freeBindData(SDefBindWeightData *const bwdata)
   MEM_freeN(bwdata);
 }
 
-BLI_INLINE float computeAngularWeight(const float point_angle, const float edgemid_angle)
+BLI_INLINE float computeAngularWeight(const float point_angle)
 {
-  float weight;
-
-  weight = point_angle;
-  weight /= edgemid_angle;
-  weight *= M_PI_2;
-
-  return sinf(weight);
+  return sinf(point_angle * M_PI_2);
 }
 
 BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
@@ -658,15 +652,12 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
 
       /* Compute angular weight component */
       if (epolys->num == 1) {
-        ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]],
-                                              bpolys[0]->edgemid_angle);
+        ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]]);
         bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[0];
       }
       else if (epolys->num == 2) {
-        ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]],
-                                              bpolys[0]->edgemid_angle);
-        ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]],
-                                              bpolys[1]->edgemid_angle);
+        ang_weights[0] = computeAngularWeight(bpolys[0]->point_edgemid_angles[edge_on_poly[0]]);
+        ang_weights[1] = computeAngularWeight(bpolys[1]->point_edgemid_angles[edge_on_poly[1]]);
 
         bpolys[0]->weight_angular *= ang_weights[0] * ang_weights[1];
         bpolys[1]->weight_angular *= ang_weights[0] * ang_weights[1];
@@ -707,9 +698,14 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
       bpoly->dominant_angle_weight = sinf(bpoly->dominant_angle_weight * M_PI_2);
 
       /* Compute quadratic angular scale interpolation weight */
-      scale_weight = bpoly->point_edgemid_angles[bpoly->dominant_edge] / bpoly->edgemid_angle;
-      scale_weight /= scale_weight +
-                      (bpoly->point_edgemid_angles[!bpoly->dominant_edge] / bpoly->edgemid_angle);
+      {
+        const float edge_angle_a = bpoly->point_edgemid_angles[bpoly->dominant_edge];
+        const float edge_angle_b = bpoly->point_edgemid_angles[!bpoly->dominant_edge];
+        /* Clamp so skinny faces with near zero `edgemid_angle`
+         * won't cause numeric problems. see T81988. */
+        scale_weight = edge_angle_a / max_ff(edge_angle_a, bpoly->edgemid_angle);
+        scale_weight /= scale_weight + (edge_angle_b / max_ff(edge_angle_b, bpoly->edgemid_angle));
+      }
 
       sqr = scale_weight * scale_weight;
       inv_sqr = 1.0f - scale_weight;
@@ -776,6 +772,11 @@ BLI_INLINE SDefBindWeightData *computeBindWeights(SDefBindCalcData *const data,
       bpoly->weight = 1.0f / bpoly->weight_angular / bpoly->weight_dist_proj / bpoly->weight_dist;
     }
 
+    /* Apply after other kinds of scaling so the faces corner angle is always
+     * scaled in a uniform way, preventing heavily sub-divided triangle fans
+     * from having a lop-sided influence on the weighting, see T81988. */
+    bpoly->weight *= bpoly->edgemid_angle / M_PI;
+
     tot_weight += bpoly->weight;
   }



More information about the Bf-blender-cvs mailing list