Commit: 7617ed972b50920726975c897429bdfa45f383fa
Author: Alexander Gavrilov
Date:   Tue Aug 7 21:08:16 2018 +0300
Branches: temp-angavrilov-bbone-custom-handles
https://developer.blender.org/rB7617ed972b50920726975c897429bdfa45f383fa

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.

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

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 17329beb325..67e7ae368b9 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -140,9 +140,32 @@ typedef struct Mat4 {
        float mat[4][4];
 } Mat4;
 
-void equalize_bbone_bezier(float *data, int desired);
+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 b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 
result_array[MAX_BBONE_SUBDIV]);
 
+void 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 1e9f48d43c2..341c73bb65a 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];
@@ -439,24 +439,23 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, 
Mat4 result_array[MAX_BB
 {
        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) {
+               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);
                }
        }
 
@@ -488,7 +487,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, 
Mat4 result_array[MAX_BB
        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);
@@ -497,7 +496,11 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, 
Mat4 result_array[MAX_BB
                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;
+
+               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)
@@ -505,7 +508,8 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, 
Mat4 result_array[MAX_BB
                        /* 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;
+                               zero_v3(param.prev_h);
+                               done = true;
                        }
                        else {
                                float delta[3];
@@ -520,39 +524,25 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, 
Mat4 result_array[MAX_BB
                        else
                                copy_v3_v3(h1, prev->pose_head);
                }
-               mul_m4_v3(imat, h1);
-
-               if (prev->bone->segments > 1) {
-                       /* if previous bone is B-bone too, use average handle 
direction */
-                       h1[1] -= length;
-                       roll1 = 0.0f;
-               }
 
-               normalize_v3(h1);
-               negate_v3(h1);
+               if (!done)
+                       mul_v3_m4v3(param.prev_h, imat, h1);
 
-               if (prev->bone->segments == 1) {
+               if (!param.prev_bbone) {
                        /* find the previous roll to interpolate */
                        if (rest)
-                               mul_m4_m4m4(difmat, imat, prev->bone->arm_mat);
+                               mul_m4_m4m4(param.prev_mat, 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 */
-
-                       vec_roll_to_mat3(h1, 0.0f, mat3); /* the result of 
vec_roll without roll */
-
-                       invert_m3_m3(imat3, mat3);
-                       mul_m3_m3m3(mat3, result, imat3); /* the matrix 
transforming vec_roll to desired roll */
-
-                       roll1 = atan2f(mat3[2][0], mat3[2][2]);
+                               mul_m4_m4m4(param.prev_mat, imat, 
prev->pose_mat);
                }
        }
-       else {
-               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];
+               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)
@@ -560,7 +550,8 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, 
Mat4 result_array[MAX_BB
                        /* Use delta movement (from restpose), and apply this 
relative to the current bone's tail */
                        if (rest) {
                                /* in restpose, arm_tail == pose_tail */
-                               h2[0] = h2[1] = h2[2] = 0.0f;
+                               copy_v3_fl3(param.next_h, 0.0f, param.length, 
0.0);
+                               done = true;
                        }
                        else {
                                float delta[3];
@@ -575,23 +566,125 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, 
Mat4 result_array[MAX_BB
                        else
                                copy_v3_v3(h2, next->pose_tail);
                }
-               mul_m4_v3(imat, h2);
+
+               if (!done)
+                       mul_v3_m4v3(param.next_h, imat, h2);
+
+               /* find the next roll to interpolate as well */
+               if (rest)
+                       mul_m4_m4m4(param.next_mat, imat, next->bone->arm_mat);
+               else
+                       mul_m4_m4m4(param.next_mat, imat, 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);
+       }
+
+       BKE_compute_b_bone_spline(&param, result_array);
+}
+
+/* returns pointer to static array, filled with desired amount of 
bone->segments elements */
+/* this calculation is done  within unit bone space */
+void 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;
+               }
+
+               normalize_v3(h1);
+               negate_v3(h1);
+
+               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 */
+
+                       invert_m3_m3(imat3, mat3);
+                       mul_m3_m3m3(mat3, result, imat3); /* the matrix 
transforming vec_roll to desired roll */
+
+                       roll1 = atan2f(mat3[2][0], mat3[2][2]);
+               }
+       }
+       else {
+               h1[0] = 0.0f; h1[1] = 1.0; h1[2] = 0.0f;
+               roll1 = 0.0f;
+       }
+
+       if (param->use_next) {
+               copy_v3_v3(h2, param->next_h);
 
                /* if next bone is B-bone too, use average handle direction */
-               if (next->bone->segments > 1) {
+               if (param->next_bbone) {
                        /* pass */
                }
                else {
                        h2[1] -= length;
                }
+
                normalize_v3(h2);
 
                /* find the next roll to interpolate as well */
-               if (rest)
-                       mul_m4_m4m4(difmat, imat, next->bone->arm_mat);
-               else
-                       mul_m4_m4m4(difmat, imat, next->pose_mat);
-               copy_m3_m4(result, difmat); /* the desired rotation at 
beginning of next bone */
+               copy_m3_m4(result, param->next_mat); /* the desired rotation at 
beginning of next bone */
 
                vec_roll_to_mat3(h2, 0.0f, mat3); /* the result of vec_roll 
without roll */
 
@@ -599,7 +692,6 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, 
Mat4 result_array[MAX_BB
                mul_m3_m3m3(mat3, imat3, result); /* the matrix transf

@@ 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