[Bf-blender-cvs] [7617ed972b5] temp-angavrilov-bbone-custom-handles: Fix T56268: display the correct rest shape for B-Bones in Edit Mode.
Alexander Gavrilov
noreply at git.blender.org
Tue Aug 7 20:08:28 CEST 2018
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(¶m, 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(¶m, 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. @@
More information about the Bf-blender-cvs
mailing list