[Bf-blender-cvs] [65f77ccea16] blender2.8: Fix T56268: display the correct rest shape for B-Bones in Edit Mode.

Alexander Gavrilov noreply at git.blender.org
Thu Oct 4 18:56:01 CEST 2018


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



More information about the Bf-blender-cvs mailing list