Commit: 65f77ccea1645f8c66fc171377641b08b62010e0
Author: Alexander Gavrilov
Date:   Tue Aug 7 21:08:16 2018 +0300
Branches: blender2.8
https://developer.blender.org/rB65f77ccea1645f8c66fc171377641b08b62010e0

Fix T56268: display the correct rest shape for B-Bones in Edit Mode.

The rest shape of B-Bones is actually affected by custom handles or
the default connected parent/child mechanism. Ignoring these effects
thus leads to the edit mode shape being different from the actual
rest pose.

This splits the b_bone_spline_setup function that is used to compute
the correct rest and pose shape from pose channels into two parts,
and applies the data structure independent half to edit mode.

In order to access the custom handle settings in Edit Mode, they are
moved to Bone and EditBone, while the bPoseChannel fields are downgraded
in status to a cache for performance. Also, instead of flags, introduce
an enum to specify the handle operation modes, so that new ones could
be added later.

Reviewers: aligorith, brecht

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

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

M       source/blender/blenkernel/BKE_armature.h
M       source/blender/blenkernel/intern/armature.c
M       source/blender/draw/intern/draw_armature.c
M       source/blender/editors/include/ED_armature.h

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

diff --git a/source/blender/blenkernel/BKE_armature.h 
b/source/blender/blenkernel/BKE_armature.h
index 44120d182b7..abcf1388c55 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -140,11 +140,34 @@ typedef struct Mat4 {
        float mat[4][4];
 } Mat4;
 
+typedef struct BBoneSplineParameters {
+       int segments;
+       float length;
+
+       /* Non-uniform scale correction. */
+       bool do_scale;
+       float scale[3];
+
+       /* Handle control bone data. */
+       bool use_prev, prev_bbone;
+       bool use_next, next_bbone;
+
+       float prev_h[3], next_h[3];
+       float prev_mat[4][4], next_mat[4][4];
+
+       /* Control values. */
+       float ease1, ease2;
+       float roll1, roll2;
+       float scaleIn, scaleOut;
+       float curveInX, curveInY, curveOutX, curveOutY;
+} BBoneSplineParameters;
+
 void BKE_pchan_get_bbone_handles(struct bPoseChannel *pchan, struct 
bPoseChannel **r_prev, struct bPoseChannel **r_next);
 
-void equalize_bbone_bezier(float *data, int desired);
 void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 
result_array[MAX_BBONE_SUBDIV]);
 
+int BKE_compute_b_bone_spline(struct BBoneSplineParameters *param, Mat4 
result_array[MAX_BBONE_SUBDIV]);
+
 /* like EBONE_VISIBLE */
 #define PBONE_VISIBLE(arm, bone) ( \
        CHECK_TYPE_INLINE(arm, bArmature *), \
diff --git a/source/blender/blenkernel/intern/armature.c 
b/source/blender/blenkernel/intern/armature.c
index 61472068399..5ffb38414a8 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -393,7 +393,7 @@ int bone_autoside_name(char name[MAXBONENAME], int 
UNUSED(strip_number), short a
 /* ************* B-Bone support ******************* */
 
 /* data has MAX_BBONE_SUBDIV+1 interpolated points, will become desired amount 
with equal distances */
-void equalize_bbone_bezier(float *data, int desired)
+static void equalize_bbone_bezier(float *data, int desired)
 {
        float *fp, totdist, ddist, dist, fac1, fac2;
        float pdist[MAX_BBONE_SUBDIV + 1];
@@ -460,59 +460,63 @@ void BKE_pchan_get_bbone_handles(bPoseChannel *pchan, 
bPoseChannel **r_prev, bPo
        }
 }
 
-/* returns pointer to static array, filled with desired amount of 
bone->segments elements */
-/* this calculation is done  within unit bone space */
+/* Fills the array with the desired amount of bone->segments elements.
+ * This calculation is done within unit bone space. */
 void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 
result_array[MAX_BBONE_SUBDIV])
 {
        bPoseChannel *next, *prev;
        Bone *bone = pchan->bone;
-       float h1[3], h2[3], scale[3], length, roll1 = 0.0f, roll2;
-       float mat3[3][3], imat[4][4], posemat[4][4], scalemat[4][4], 
iscalemat[4][4];
-       float data[MAX_BBONE_SUBDIV + 1][4], *fp;
-       int a;
-       bool do_scale = false;
+       BBoneSplineParameters param;
+       float imat[4][4], posemat[4][4];
 
-       length = bone->length;
+       memset(&param, 0, sizeof(param));
+
+       param.segments = bone->segments;
+       param.length = bone->length;
 
        if (!rest) {
-               /* check if we need to take non-uniform bone scaling into 
account */
+               float scale[3];
+
+               /* Check if we need to take non-uniform bone scaling into 
account. */
                mat4_to_size(scale, pchan->pose_mat);
 
                if (fabsf(scale[0] - scale[1]) > 1e-6f || fabsf(scale[1] - 
scale[2]) > 1e-6f) {
-                       size_to_mat4(scalemat, scale);
-                       invert_m4_m4(iscalemat, scalemat);
-
-                       length *= scale[1];
-                       do_scale = 1;
+                       param.do_scale = true;
+                       copy_v3_v3(param.scale, scale);
                }
        }
 
        BKE_pchan_get_bbone_handles(pchan, &prev, &next);
 
-       /* find the handle points, since this is inside bone space, the
+       /* Find the handle points, since this is inside bone space, the
         * first point = (0, 0, 0)
         * last point =  (0, length, 0) */
        if (rest) {
                invert_m4_m4(imat, pchan->bone->arm_mat);
        }
-       else if (do_scale) {
+       else if (param.do_scale) {
                copy_m4_m4(posemat, pchan->pose_mat);
                normalize_m4(posemat);
                invert_m4_m4(imat, posemat);
        }
-       else
+       else {
                invert_m4_m4(imat, pchan->pose_mat);
+       }
 
        if (prev) {
-               float difmat[4][4], result[3][3], imat3[3][3];
+               float h1[3];
+               bool done = false;
 
-               /* transform previous point inside this bone space */
-               if (bone->bbone_prev_type == BBONE_HANDLE_RELATIVE)
-               {
-                       /* Use delta movement (from restpose), and apply this 
relative to the current bone's head */
+               param.use_prev = true;
+               param.prev_bbone = (prev->bone->segments > 1);
+
+               /* Transform previous point inside this bone space. */
+               if (bone->bbone_prev_type == BBONE_HANDLE_RELATIVE) {
+                       /* Use delta movement (from restpose), and apply this 
relative to the current bone's head. */
                        if (rest) {
-                               /* in restpose, arm_head == pose_head */
-                               h1[0] = h1[1] = h1[2] = 0.0f;
+                               /* In restpose, arm_head == pose_head */
+                               zero_v3(param.prev_h);
+                               done = true;
                        }
                        else {
                                float delta[3];
@@ -521,16 +525,125 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, 
Mat4 result_array[MAX_BB
                        }
                }
                else {
-                       /* Use bone head as absolute position */
-                       if (rest)
-                               copy_v3_v3(h1, prev->bone->arm_head);
-                       else
-                               copy_v3_v3(h1, prev->pose_head);
+                       /* Use bone head as absolute position. */
+                       copy_v3_v3(h1, rest ? prev->bone->arm_head : 
prev->pose_head);
+               }
+
+               if (!done) {
+                       mul_v3_m4v3(param.prev_h, imat, h1);
+               }
+
+               if (!param.prev_bbone) {
+                       /* Find the previous roll to interpolate. */
+                       mul_m4_m4m4(param.prev_mat, imat, rest ? 
prev->bone->arm_mat : prev->pose_mat);
+               }
+       }
+
+       if (next) {
+               float h2[3];
+               bool done = false;
+
+               param.use_next = true;
+               param.next_bbone = (next->bone->segments > 1);
+
+               /* Transform next point inside this bone space. */
+               if (bone->bbone_next_type == BBONE_HANDLE_RELATIVE) {
+                       /* Use delta movement (from restpose), and apply this 
relative to the current bone's tail. */
+                       if (rest) {
+                               /* In restpose, arm_tail == pose_tail */
+                               copy_v3_fl3(param.next_h, 0.0f, param.length, 
0.0);
+                               done = true;
+                       }
+                       else {
+                               float delta[3];
+                               sub_v3_v3v3(delta, next->pose_tail, 
next->bone->arm_tail);
+                               add_v3_v3v3(h2, pchan->pose_tail, delta);
+                       }
+               }
+               else {
+                       /* Use bone tail as absolute position. */
+                       copy_v3_v3(h2, rest ? next->bone->arm_tail : 
next->pose_tail);
+               }
+
+               if (!done) {
+                       mul_v3_m4v3(param.next_h, imat, h2);
                }
-               mul_m4_v3(imat, h1);
 
-               if (prev->bone->segments > 1) {
-                       /* if previous bone is B-bone too, use average handle 
direction */
+               /* Find the next roll to interpolate as well. */
+               mul_m4_m4m4(param.next_mat, imat, rest ? next->bone->arm_mat : 
next->pose_mat);
+       }
+
+       /* Add effects from bbone properties over the top
+        * - These properties allow users to hand-animate the
+        *   bone curve/shape, without having to resort to using
+        *   extra bones
+        * - The "bone" level offsets are for defining the restpose
+        *   shape of the bone (e.g. for curved eyebrows for example).
+        *   -> In the viewport, it's needed to define what the rest pose
+        *      looks like
+        *   -> For "rest == 0", we also still need to have it present
+        *      so that we can "cancel out" this restpose when it comes
+        *      time to deform some geometry, it won't cause double transforms.
+        * - The "pchan" level offsets are the ones that animators actually
+        *   end up animating
+        */
+       {
+               param.ease1 = bone->ease1 + (!rest ? pchan->ease1 : 0.0f);
+               param.ease2 = bone->ease2 + (!rest ? pchan->ease2 : 0.0f);
+
+               param.roll1 = bone->roll1 + (!rest ? pchan->roll1 : 0.0f);
+               param.roll2 = bone->roll2 + (!rest ? pchan->roll2 : 0.0f);
+
+               if (bone->flag & BONE_ADD_PARENT_END_ROLL) {
+                       if (prev) {
+                               if (prev->bone) {
+                                       param.roll1 += prev->bone->roll2;
+                               }
+
+                               if (!rest) {
+                                       param.roll1 += prev->roll2;
+                               }
+                       }
+               }
+
+               param.scaleIn = bone->scaleIn * (!rest ? pchan->scaleIn : 1.0f);
+               param.scaleOut = bone->scaleOut * (!rest ? pchan->scaleOut : 
1.0f);
+
+               /* Extra curve x / y */
+               param.curveInX = bone->curveInX + (!rest ? pchan->curveInX : 
0.0f);
+               param.curveInY = bone->curveInY + (!rest ? pchan->curveInY : 
0.0f);
+
+               param.curveOutX = bone->curveOutX + (!rest ? pchan->curveOutX : 
0.0f);
+               param.curveOutY = bone->curveOutY + (!rest ? pchan->curveOutY : 
0.0f);
+       }
+
+       bone->segments = BKE_compute_b_bone_spline(&param, result_array);
+}
+
+/* Fills the array with the desired amount of bone->segments elements.
+ * This calculation is done within unit bone space. */
+int BKE_compute_b_bone_spline(BBoneSplineParameters *param, Mat4 
result_array[MAX_BBONE_SUBDIV])
+{
+       float scalemat[4][4], iscalemat[4][4];
+       float result[3][3], mat3[3][3], imat3[3][3];
+       float h1[3], roll1, h2[3], roll2;
+       float data[MAX_BBONE_SUBDIV + 1][4], *fp;
+       int a;
+
+       float length = param->length;
+
+       if (param->do_scale) {
+               size_to_mat4(scalemat, param->scale);
+               invert_m4_m4(iscalemat, scalemat);
+
+               length *= param->scale[1];
+       }
+
+       if (param->use_prev) {
+               copy_v3_v3(h1, param->prev_h);
+
+               if (param->prev_bbone) {
+                       /* If previous bone is B-bone too, use average handle 
direction. */
                        h1[1] -= length;
                        roll1 = 0.0f;
                }
@@ -538,13 +651,9 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, 
Mat4 result_array[MAX_BB
                normalize_v3(h1);
                negate_v3(h1);
 
-               if (prev->bone->segments == 1) {
-                       /* find the previous roll to interpolate */
-                       if (rest)
-                               mul_m4_m4m4(difmat, imat, prev->bone->arm_mat);
-                       else
-                               mul_m4_m4m4(difmat, imat, prev->pose_mat);
-                       copy_m3_m4(result, difmat); /* the desired rotation at 
beginning of next bone */
+               if (!param->prev_bbone) {
+                       /* Find the previous roll to interpolate. */
+                       copy_m3_m4(result, param->prev_mat); /* the desired 
rotation at beginning of next bone */
 
                        vec_roll_to_mat3(h1, 0.0f, mat3); /* the result of 
vec_roll without roll */
 
@@ -558,47 +667,22 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, 
Mat4 result_array[MAX_BB
                h1[0] = 0.0f; h1[1] = 1.0; h1[2] = 0.0f;
                roll1 = 0.0f;
        }
-       if (next) {
-               float difmat[4][4], result[3][3], imat3[3][3];
 
-               /* transform next point inside this bone space */
-               if (bone->bbone_next_type == BBONE_HANDLE_RELATIVE)
-               {
-                       /* Use delta movement (from restpose), and apply this 
relative to the current bone's tail */
-                       if (rest) {
-                               /* in restpose, arm_tail == 

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to