[Bf-blender-cvs] [fbaa6db7acb] temp-angavrilov-constraints: Armature: apply Y scale to B-Bone segments.

Alexander Gavrilov noreply at git.blender.org
Tue Jun 22 15:44:25 CEST 2021


Commit: fbaa6db7acbbbfae1faf7fe1d220804470c2e2cf
Author: Alexander Gavrilov
Date:   Tue Jun 15 13:52:23 2021 +0300
Branches: temp-angavrilov-constraints
https://developer.blender.org/rBfbaa6db7acbbbfae1faf7fe1d220804470c2e2cf

Armature: apply Y scale to B-Bone segments.

This fixes a strange behavior where the segments were not actually
scaled in the Y direction to match their actual length, thus
producing gaps or overlap depending on the shape of the curve. For
transformation the change should be very small if enough segments
are used, but this will affect the results of the Copy Transforms
and Armature constraints, so a backwards compatibility option is
provided. Newly created bones default to the new behavior.

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

M	release/scripts/startup/bl_ui/properties_data_bone.py
M	source/blender/blenkernel/BKE_armature.h
M	source/blender/blenkernel/intern/armature.c
M	source/blender/draw/engines/overlay/overlay_armature.c
M	source/blender/editors/armature/armature_add.c
M	source/blender/makesdna/DNA_armature_types.h
M	source/blender/makesrna/intern/rna_armature.c

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

diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index daf64642f68..d141501d6bc 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -178,6 +178,8 @@ class BONE_PT_curved(BoneButtonsPanel, Panel):
         col.prop(bbone, "bbone_easeout", text="Out")
         col.prop(bone, "use_scale_easing")
 
+        topcol.prop(bone, "use_unscaled_segments")
+
         col = topcol.column(align=True)
         col.prop(bone, "bbone_handle_type_start", text="Start Handle")
 
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 112b8bf3ad4..a603a54810c 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -288,7 +288,7 @@ typedef struct BBoneSplineParameters {
   float length;
 
   /* Non-uniform scale correction. */
-  bool do_scale;
+  bool do_scale, do_scale_segments;
   float scale[3];
 
   /* Handle control bone data. */
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index d308b2da6a3..e2e33821d59 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -967,6 +967,8 @@ void BKE_pchan_bbone_spline_params_get(struct bPoseChannel *pchan,
   param->segments = bone->segments;
   param->length = bone->length;
 
+  param->do_scale_segments = (bone->bbone_flag & BBONE_SCALE_SEGMENTS) != 0;
+
   if (!rest) {
     float scale[3];
 
@@ -1335,6 +1337,7 @@ static void make_bbone_spline_matrix(BBoneSplineParameters *param,
                                      const float axis[3],
                                      float roll,
                                      float scalex,
+                                     float scaley,
                                      float scalez,
                                      float result[4][4])
 {
@@ -1352,6 +1355,7 @@ static void make_bbone_spline_matrix(BBoneSplineParameters *param,
 
   /* BBone scale... */
   mul_v3_fl(result[0], scalex);
+  mul_v3_fl(result[1], scaley);
   mul_v3_fl(result[2], scalez);
 }
 
@@ -1418,6 +1422,8 @@ int BKE_pchan_bbone_spline_compute(BBoneSplineParameters *param,
   equalize_cubic_bezier(
       bezt_controls, MAX_BBONE_SUBDIV, param->segments, segment_scales, bezt_points);
 
+  const float scale_fac = param->segments / length;
+
   /* Deformation uses N+1 matrices computed at points between the segments. */
   if (for_deform) {
     /* Bezier derivatives. */
@@ -1430,6 +1436,32 @@ int BKE_pchan_bbone_spline_compute(BBoneSplineParameters *param,
       sub_v3_v3v3(bezt_deriv2[i], bezt_deriv1[i + 1], bezt_deriv1[i]);
     }
 
+    /* Inner segment points. */
+    float points[MAX_BBONE_SUBDIV][3], tangents[MAX_BBONE_SUBDIV][3];
+
+    copy_v3_v3(points[0], bezt_controls[0]);
+
+    for (int a = 1; a < param->segments; a++) {
+      evaluate_cubic_bezier(bezt_controls, bezt_points[a], points[a], tangents[a]);
+    }
+
+    /* Segment lengths. */
+    float seg_length[MAX_BBONE_SUBDIV + 1];
+
+    if (param->do_scale_segments) {
+      for (int a = 1; a < param->segments; a++) {
+        seg_length[a] = len_v3v3(points[a - 1], points[a]) * scale_fac;
+      }
+
+      seg_length[param->segments] = len_v3v3(points[param->segments - 1], bezt_controls[3]) *
+                                    scale_fac;
+    }
+    else {
+      for (int a = 1; a <= param->segments; a++) {
+        seg_length[a] = 1;
+      }
+    }
+
     /* End points require special handling to fix zero length handles. */
     ease_handle_axis(bezt_deriv1[0], bezt_deriv2[0], axis);
     make_bbone_spline_matrix(param,
@@ -1438,19 +1470,26 @@ int BKE_pchan_bbone_spline_compute(BBoneSplineParameters *param,
                              axis,
                              roll1,
                              param->scale_in[0],
+                             seg_length[1],
                              param->scale_in[2],
                              result_array[0].mat);
 
     for (int a = 1; a < param->segments; a++) {
-      evaluate_cubic_bezier(bezt_controls, bezt_points[a], cur, axis);
-
       float fac = ((float)a) / param->segments;
       float roll = interpf(roll2, roll1, fac);
       float scalex = interpf(param->scale_out[0], param->scale_in[0], fac);
       float scalez = interpf(param->scale_out[2], param->scale_in[2], fac);
+      float scaley = sqrtf(seg_length[a] * seg_length[a + 1]);
 
-      make_bbone_spline_matrix(
-          param, scalemats, cur, axis, roll, scalex, scalez, result_array[a].mat);
+      make_bbone_spline_matrix(param,
+                               scalemats,
+                               points[a],
+                               tangents[a],
+                               roll,
+                               scalex,
+                               scaley,
+                               scalez,
+                               result_array[a].mat);
     }
 
     negate_v3(bezt_deriv2[1]);
@@ -1461,6 +1500,7 @@ int BKE_pchan_bbone_spline_compute(BBoneSplineParameters *param,
                              axis,
                              roll2,
                              param->scale_out[0],
+                             seg_length[param->segments],
                              param->scale_out[2],
                              result_array[param->segments].mat);
   }
@@ -1477,9 +1517,10 @@ int BKE_pchan_bbone_spline_compute(BBoneSplineParameters *param,
       float roll = interpf(roll2, roll1, fac);
       float scalex = interpf(param->scale_out[0], param->scale_in[0], fac);
       float scalez = interpf(param->scale_out[2], param->scale_in[2], fac);
+      float scaley = param->do_scale_segments ? len_v3(axis) * scale_fac : 1;
 
       make_bbone_spline_matrix(
-          param, scalemats, prev, axis, roll, scalex, scalez, result_array[a].mat);
+          param, scalemats, prev, axis, roll, scalex, scaley, scalez, result_array[a].mat);
       copy_v3_v3(prev, cur);
     }
   }
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index ea636c3d185..33a26150ffc 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -1090,6 +1090,8 @@ static void ebone_spline_preview(EditBone *ebone, const float result_array[MAX_B
   param.segments = ebone->segments;
   param.length = ebone->length;
 
+  param.do_scale_segments = !!(ebone->bbone_flag & BBONE_SCALE_SEGMENTS);
+
   /* Get "next" and "prev" bones - these are used for handle calculations. */
   if (ebone->bbone_prev_type == BBONE_HANDLE_AUTO) {
     /* Use connected parent. */
diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c
index 69389bc3af1..ab07e574610 100644
--- a/source/blender/editors/armature/armature_add.c
+++ b/source/blender/editors/armature/armature_add.c
@@ -98,6 +98,8 @@ EditBone *ED_armature_ebone_add(bArmature *arm, const char *name)
   copy_v3_fl(bone->scale_in, 1.0f);
   copy_v3_fl(bone->scale_out, 1.0f);
 
+  bone->bbone_flag = BBONE_SCALE_SEGMENTS;
+
   return bone;
 }
 
diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h
index 3d83d0d2f6f..04e53c8e4bb 100644
--- a/source/blender/makesdna/DNA_armature_types.h
+++ b/source/blender/makesdna/DNA_armature_types.h
@@ -304,6 +304,8 @@ typedef enum eBone_BBoneFlag {
   BBONE_ADD_PARENT_END_ROLL = (1 << 0),
   /** Multiply B-Bone easing values with Scale Length. */
   BBONE_SCALE_EASING = (1 << 1),
+  /** Apply Y scale to B-Bone segments. */
+  BBONE_SCALE_SEGMENTS = (1 << 2),
 } eBone_BBoneFlag;
 
 /* bone->bbone_prev/next_flag */
diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c
index f07aae0bb15..0750dd4db4e 100644
--- a/source/blender/makesrna/intern/rna_armature.c
+++ b/source/blender/makesrna/intern/rna_armature.c
@@ -775,6 +775,15 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone, bool is_editb
         prop, "Scale Easing", "Multiply the final easing values by the Scale In/Out Y factors");
     RNA_def_property_boolean_sdna(prop, NULL, "bbone_flag", BBONE_SCALE_EASING);
     RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
+
+    prop = RNA_def_property(srna, "use_unscaled_segments", PROP_BOOLEAN, PROP_NONE);
+    RNA_def_property_ui_text(prop,
+                             "Unscaled Segments (Legacy)",
+                             "Do not apply scaling necessary to fit segments to the curve length "
+                             "without gaps or overlap for compatibility with old files");
+    RNA_def_property_boolean_negative_sdna(prop, NULL, "bbone_flag", BBONE_SCALE_SEGMENTS);
+    RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+    RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone, is_editbone);
   }
 
   /* Scale In/Out */



More information about the Bf-blender-cvs mailing list