[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(&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. @@



More information about the Bf-blender-cvs mailing list