Stretch To: implement a mode similar to Damped Track for rotation.
authorAlexander Gavrilov <angavrilov@gmail.com>
Wed, 6 Nov 2019 14:11:32 +0000 (17:11 +0300)
committerAlexander Gavrilov <angavrilov@gmail.com>
Thu, 7 Nov 2019 16:03:03 +0000 (19:03 +0300)
Most of the time Stretch To is used in actual rigs, like BlenRig
or Rigify, in combination with Damped Track to handle rotation
before the stretch, because it produces rotations more appropriate
for organic deformation, and doesn't flip because of internal
gimbal lock.

The prevalence of this pattern suggests that Stretch To should
support that kind of rotation directly as an option.

Differential Revision: https://developer.blender.org/D6134

release/scripts/startup/bl_ui/properties_constraint.py
source/blender/blenkernel/intern/constraint.c
source/blender/makesdna/DNA_constraint_types.h
source/blender/makesrna/intern/rna_constraint.c

index dce2d2f2758ea70f056ffaeec59918042394a2f6..b75d67b5350296ea63674a6078063cb80ea9ca62 100644 (file)
@@ -543,11 +543,14 @@ class ConstraintButtonsPanel:
         col.active = con.use_bulge_min or con.use_bulge_max
         col.prop(con, "bulge_smooth", text="Smooth")
 
-        row = layout.row()
-        row.label(text="Volume:")
+        split = layout.split(factor=0.3)
+        split.label(text="Volume:")
+        row = split.row()
         row.prop(con, "volume", expand=True)
 
-        row.label(text="Plane:")
+        split = layout.split(factor=0.3)
+        split.label(text="Rotation:")
+        row = split.row()
         row.prop(con, "keep_axis", expand=True)
 
     def FLOOR(self, _context, layout, con):
index bee2e05f8d96d2d86af667141469b782bd6f5a81..c397fbcf1157b1d98205dae73377fbe84979e709 100644 (file)
@@ -3242,6 +3242,12 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
     float size[3], scale[3], vec[3], xx[3], zz[3], orth[3];
     float dist, bulge;
 
+    /* Remove shear if using the Damped Track mode; the other modes
+     * do it as a side effect, which is relied on by rigs. */
+    if (data->plane == SWING_Y) {
+      orthogonalize_m4_stable(cob->matrix, 1, false);
+    }
+
     /* store scaling before destroying obmat */
     normalize_m4_ex(cob->matrix, size);
 
@@ -3329,6 +3335,10 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
     mul_v3_v3(size, scale);
 
     switch (data->plane) {
+      case SWING_Y:
+        /* Point the Y axis using Damped Track math. */
+        damptrack_do_transform(cob->matrix, vec, TRACK_Y);
+        break;
       case PLANE_X:
         /* new Y aligns  object target connection*/
         copy_v3_v3(cob->matrix[1], vec);
index 83fc4d2a3f7f5174a32b0e43e2cf2cd4faa9a464..d7b392d5133ef661b4833d18d60040a4ee386889 100644 (file)
@@ -930,7 +930,7 @@ typedef enum eStretchTo_VolMode {
 /* Stretch To Constraint -> plane mode */
 typedef enum eStretchTo_PlaneMode {
   PLANE_X = 0,
-  PLANE_Y = 1,
+  SWING_Y = 1,
   PLANE_Z = 2,
 } eStretchTo_PlaneMode;
 
index c021179919244d1e53348e02203f1129a179922a..6a10074810dff5e6276f0b1ce0f246975f0e1ed3 100644 (file)
@@ -1811,8 +1811,13 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna)
   };
 
   static const EnumPropertyItem plane_items[] = {
-      {PLANE_X, "PLANE_X", 0, "X", "Keep X Axis"},
-      {PLANE_Z, "PLANE_Z", 0, "Z", "Keep Z Axis"},
+      {PLANE_X, "PLANE_X", 0, "XZ", "Rotate around local X, then Z"},
+      {PLANE_Z, "PLANE_Z", 0, "ZX", "Rotate around local Z, then X"},
+      {SWING_Y,
+       "SWING_Y",
+       0,
+       "Swing",
+       "Use the smallest single axis rotation, similar to Damped Track"},
       {0, NULL, 0, NULL, NULL},
   };
 
@@ -1836,7 +1841,7 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna)
   prop = RNA_def_property(srna, "keep_axis", PROP_ENUM, PROP_NONE);
   RNA_def_property_enum_sdna(prop, NULL, "plane");
   RNA_def_property_enum_items(prop, plane_items);
-  RNA_def_property_ui_text(prop, "Keep Axis", "Axis to maintain during stretch");
+  RNA_def_property_ui_text(prop, "Keep Axis", "The rotation type and axis order to use");
   RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
 
   prop = RNA_def_property(srna, "rest_length", PROP_FLOAT, PROP_DISTANCE);