[Bf-blender-cvs] [18d4ad5a59d] master: Copy Rotation & Transform: add Euler order override options.

Alexander Gavrilov noreply at git.blender.org
Sun Sep 1 14:40:06 CEST 2019


Commit: 18d4ad5a59d32922f9d70b0412da0c830baceb17
Author: Alexander Gavrilov
Date:   Sun Sep 1 13:19:11 2019 +0300
Branches: master
https://developer.blender.org/rB18d4ad5a59d32922f9d70b0412da0c830baceb17

Copy Rotation & Transform: add Euler order override options.

For reasons similar to drivers, it should be possible to set an
explicit Euler rotation order in constraints that use Euler angles.

The Transform constraint in a way approaches drivers in its use,
in that it effectively alters channels using values of other
channels after applying a fixed form mathematical expression.

For this reason, instead of just specifying the euler order for
its inputs, it uses the same enum as driver variables. However
Quaternion components are converted to a weighted pseudo-angle
representation as the rest of the constraint UI expects angles.

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

M	release/scripts/startup/bl_ui/properties_constraint.py
M	source/blender/blenkernel/BKE_fcurve.h
M	source/blender/blenkernel/intern/constraint.c
M	source/blender/blenkernel/intern/fcurve.c
M	source/blender/makesdna/DNA_constraint_types.h
M	source/blender/makesrna/RNA_enum_types.h
M	source/blender/makesrna/intern/rna_constraint.c
M	source/blender/makesrna/intern/rna_fcurve.c

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

diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index d8eb0db62fc..0ba9fd0630c 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -370,6 +370,8 @@ class ConstraintButtonsPanel:
     def COPY_ROTATION(self, _context, layout, con):
         self.target_template(layout, con)
 
+        layout.prop(con, "euler_order", text="Order")
+
         split = layout.split()
 
         col = split.column()
@@ -685,6 +687,9 @@ class ConstraintButtonsPanel:
         col.row().label(text="Source:")
         col.row().prop(con, "map_from", expand=True)
 
+        if con.map_from == 'ROTATION':
+            layout.prop(con, "from_rotation_mode", text="Mode")
+
         split = layout.split()
         ext = "" if con.map_from == 'LOCATION' else "_rot" if con.map_from == 'ROTATION' else "_scale"
 
@@ -727,6 +732,9 @@ class ConstraintButtonsPanel:
         col.label(text="Destination:")
         col.row().prop(con, "map_to", expand=True)
 
+        if con.map_to == 'ROTATION':
+            layout.prop(con, "to_euler_order", text="Order")
+
         split = layout.split()
         ext = "" if con.map_to == 'LOCATION' else "_rot" if con.map_to == 'ROTATION' else "_scale"
 
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 4c1a115eb23..5be9a35b168 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -89,6 +89,9 @@ struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver);
 
 void driver_variables_copy(struct ListBase *dst_list, const struct ListBase *src_list);
 
+void BKE_driver_target_matrix_to_rot_channels(
+    float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]);
+
 void driver_free_variable(struct ListBase *variables, struct DriverVar *dvar);
 void driver_free_variable_ex(struct ChannelDriver *driver, struct DriverVar *dvar);
 
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 1a3c562941e..ccacb85651c 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -62,6 +62,7 @@
 #include "BKE_deform.h"
 #include "BKE_displist.h"
 #include "BKE_editmesh.h"
+#include "BKE_fcurve.h"
 #include "BKE_global.h"
 #include "BKE_idprop.h"
 #include "BKE_library.h"
@@ -1808,18 +1809,25 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
     copy_v3_v3(loc, cob->matrix[3]);
     mat4_to_size(size, cob->matrix);
 
+    /* Select the Euler rotation order, defaulting to the owner. */
+    short rot_order = cob->rotOrder;
+
+    if (data->euler_order != CONSTRAINT_EULER_AUTO) {
+      rot_order = data->euler_order;
+    }
+
     /* To allow compatible rotations, must get both rotations in the order of the owner... */
-    mat4_to_eulO(obeul, cob->rotOrder, cob->matrix);
+    mat4_to_eulO(obeul, rot_order, cob->matrix);
     /* We must get compatible eulers from the beginning because
      * some of them can be modified below (see bug T21875). */
-    mat4_to_compatible_eulO(eul, obeul, cob->rotOrder, ct->matrix);
+    mat4_to_compatible_eulO(eul, obeul, rot_order, ct->matrix);
 
     if ((data->flag & ROTLIKE_X) == 0) {
       eul[0] = obeul[0];
     }
     else {
       if (data->flag & ROTLIKE_OFFSET) {
-        rotate_eulO(eul, cob->rotOrder, 'X', obeul[0]);
+        rotate_eulO(eul, rot_order, 'X', obeul[0]);
       }
 
       if (data->flag & ROTLIKE_X_INVERT) {
@@ -1832,7 +1840,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
     }
     else {
       if (data->flag & ROTLIKE_OFFSET) {
-        rotate_eulO(eul, cob->rotOrder, 'Y', obeul[1]);
+        rotate_eulO(eul, rot_order, 'Y', obeul[1]);
       }
 
       if (data->flag & ROTLIKE_Y_INVERT) {
@@ -1845,7 +1853,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
     }
     else {
       if (data->flag & ROTLIKE_OFFSET) {
-        rotate_eulO(eul, cob->rotOrder, 'Z', obeul[2]);
+        rotate_eulO(eul, rot_order, 'Z', obeul[2]);
       }
 
       if (data->flag & ROTLIKE_Z_INVERT) {
@@ -1856,7 +1864,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
     /* Good to make eulers compatible again,
      * since we don't know how much they were changed above. */
     compatible_eul(eul, obeul);
-    loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
+    loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, rot_order);
   }
 }
 
@@ -3719,7 +3727,8 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
   if (VALID_CONS_TARGET(ct)) {
     float *from_min, *from_max, *to_min, *to_max;
     float loc[3], eul[3], size[3];
-    float dvec[3], sval[3];
+    float dbuf[4], sval[3];
+    float *const dvec = dbuf + 1;
     int i;
 
     /* obtain target effect */
@@ -3738,7 +3747,8 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
         from_max = data->from_max_scale;
         break;
       case TRANS_ROTATION:
-        mat4_to_eulO(dvec, cob->rotOrder, ct->matrix);
+        BKE_driver_target_matrix_to_rot_channels(
+            ct->matrix, cob->rotOrder, data->from_rotation_mode, -1, true, dbuf);
         from_min = data->from_min_rot;
         from_max = data->from_max_rot;
         break;
@@ -3750,9 +3760,16 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
         break;
     }
 
+    /* Select the output Euler rotation order, defaulting to the owner. */
+    short rot_order = cob->rotOrder;
+
+    if (data->to == TRANS_ROTATION && data->to_euler_order != CONSTRAINT_EULER_AUTO) {
+      rot_order = data->to_euler_order;
+    }
+
     /* extract components of owner's matrix */
     copy_v3_v3(loc, cob->matrix[3]);
-    mat4_to_eulO(eul, cob->rotOrder, cob->matrix);
+    mat4_to_eulO(eul, rot_order, cob->matrix);
     mat4_to_size(size, cob->matrix);
 
     /* determine where in range current transforms lie */
@@ -3811,7 +3828,7 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
     }
 
     /* apply to matrix */
-    loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
+    loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, rot_order);
   }
 }
 
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index ef53c926daa..c4da2d2efc9 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1732,35 +1732,21 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
      *         - only an option for "transform space", if quality is really bad with a)
      */
     float quat[4];
-    float *const eul = quat + 1;
     int channel;
 
     if (dtar->transChan == DTAR_TRANSCHAN_ROTW) {
       channel = 0;
-      quat[0] = 0.0f;
     }
     else {
       channel = 1 + dtar->transChan - DTAR_TRANSCHAN_ROTX;
       BLI_assert(channel < 4);
     }
 
-    if (dtar->rotation_mode == DTAR_ROTMODE_AUTO) {
-      mat4_to_eulO(eul, rot_order, mat);
+    BKE_driver_target_matrix_to_rot_channels(
+        mat, rot_order, dtar->rotation_mode, channel, false, quat);
 
-      if (use_eulers) {
-        compatible_eul(eul, oldEul);
-      }
-    }
-    else if (dtar->rotation_mode >= DTAR_ROTMODE_EULER_MIN &&
-             dtar->rotation_mode <= DTAR_ROTMODE_EULER_MAX) {
-      mat4_to_eulO(eul, dtar->rotation_mode, mat);
-    }
-    else if (dtar->rotation_mode == DTAR_ROTMODE_QUATERNION) {
-      mat4_to_quat(quat, mat);
-    }
-    else {
-      BLI_assert(false);
-      zero_v3(eul);
+    if (use_eulers && dtar->rotation_mode == DTAR_ROTMODE_AUTO) {
+      compatible_eul(quat + 1, oldEul);
     }
 
     return quat[channel];
@@ -1771,6 +1757,52 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
   }
 }
 
+/* Convert a quaternion to pseudo-angles representing the weighted amount of rotation. */
+static void quaternion_to_angles(float quat[4], int channel)
+{
+  if (channel < 0) {
+    quat[0] = 2.0f * saacosf(quat[0]);
+
+    for (int i = 1; i < 4; i++) {
+      quat[i] = 2.0f * saasinf(quat[i]);
+    }
+  }
+  else if (channel == 0) {
+    quat[0] = 2.0f * saacosf(quat[0]);
+  }
+  else {
+    quat[channel] = 2.0f * saasinf(quat[channel]);
+  }
+}
+
+/* Compute channel values for a rotational Transform Channel driver variable. */
+void BKE_driver_target_matrix_to_rot_channels(
+    float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4])
+{
+  float *const quat = r_buf;
+  float *const eul = r_buf + 1;
+
+  zero_v4(r_buf);
+
+  if (rotation_mode == DTAR_ROTMODE_AUTO) {
+    mat4_to_eulO(eul, auto_order, mat);
+  }
+  else if (rotation_mode >= DTAR_ROTMODE_EULER_MIN && rotation_mode <= DTAR_ROTMODE_EULER_MAX) {
+    mat4_to_eulO(eul, rotation_mode, mat);
+  }
+  else if (rotation_mode == DTAR_ROTMODE_QUATERNION) {
+    mat4_to_quat(quat, mat);
+
+    /* For Transformation constraint convenience, convert to pseudo-angles. */
+    if (angles) {
+      quaternion_to_angles(quat, channel);
+    }
+  }
+  else {
+    BLI_assert(false);
+  }
+}
+
 /* ......... */
 
 /* Table of Driver Variable Type Info Data */
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 17ce279f1b7..42d58cb34d0 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -271,7 +271,8 @@ typedef struct bTrackToConstraint {
 typedef struct bRotateLikeConstraint {
   struct Object *tar;
   int flag;
-  int reserved1;
+  char euler_order;
+  char _pad[3];
   /** MAX_ID_NAME-2. */
   char subtarget[64];
 } bRotateLikeConstraint;
@@ -441,6 +442,13 @@ typedef struct bTransformConstraint {
   /** Extrapolate motion? if 0, confine to ranges. */
   char expo;
 
+  /** Input rotation type - uses the same values as driver targets. */
+  char from_rotation_mode;
+  /** Output euler order o

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list