[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [17259] branches/animsys2/source/blender: AnimSys2: Bone Roll Issues

Joshua Leung aligorith at gmail.com
Sat Nov 1 12:14:06 CET 2008


Revision: 17259
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17259
Author:   aligorith
Date:     2008-11-01 12:14:05 +0100 (Sat, 01 Nov 2008)

Log Message:
-----------
AnimSys2: Bone Roll Issues

In this commit, I've attempted to improve the situation of bone roll problems that occur with the recalculate bone roll tool, and also when extruding/moving bones under certain conditions.

What's changed:
* When transforming bones, as part of the recalculations done on every update, the roll of bones who have their tip selected will be recalculated using the 'z-axis up' method. Reported by Glenn Melenhorst on BA.org

* Split the 'z-axis up' and 'align z-axis to cursor' roll recalculation methods into separate functions that can act as callbacks. Refactored the auto_align_armature() function to support this. It was needed for the first major change to occur.

* As an experiment, I've changed the final step of the z-axis method to use mat3_to_vec_roll instead of atan2 directly. It currently seems to work better, but I'm not totally sure yet. Will check on this again another day...

Modified Paths:
--------------
    branches/animsys2/source/blender/include/BIF_editarmature.h
    branches/animsys2/source/blender/src/editarmature.c
    branches/animsys2/source/blender/src/gpencil.c
    branches/animsys2/source/blender/src/transform_generics.c

Modified: branches/animsys2/source/blender/include/BIF_editarmature.h
===================================================================
--- branches/animsys2/source/blender/include/BIF_editarmature.h	2008-11-01 10:18:21 UTC (rev 17258)
+++ branches/animsys2/source/blender/include/BIF_editarmature.h	2008-11-01 11:14:05 UTC (rev 17259)
@@ -117,7 +117,10 @@
 void	setflag_armature(short mode);
 void    unique_editbone_name (struct ListBase *ebones, char *name);
 
+void 	auto_align_ebone_zaxisup(EditBone *ebone);
+void	auto_align_ebone_tocursor(EditBone *ebone);
 void	auto_align_armature(short mode);
+
 void	switch_direction_armature(void);
 
 void	create_vgroups_from_armature(struct Object *ob, struct Object *par);

Modified: branches/animsys2/source/blender/src/editarmature.c
===================================================================
--- branches/animsys2/source/blender/src/editarmature.c	2008-11-01 10:18:21 UTC (rev 17258)
+++ branches/animsys2/source/blender/src/editarmature.c	2008-11-01 11:14:05 UTC (rev 17259)
@@ -1818,6 +1818,74 @@
 	}
 }
 
+
+/* Set roll value for given bone -> Z-Axis Point up (original method) */
+void auto_align_ebone_zaxisup(EditBone *ebone)
+{
+	float	delta[3], curmat[3][3];
+	float	xaxis[3]={1.0, 0.0, 0.0}, yaxis[3], zaxis[3]={0.0f, 0.0f, 1.0f};
+	float	targetmat[3][3], imat[3][3], diffmat[3][3];
+	
+	/* Find the current bone matrix */
+	VecSubf(delta, ebone->tail, ebone->head);
+	vec_roll_to_mat3(delta, 0.0f, curmat);
+	
+	/* Make new matrix based on y axis & z-up */
+	VECCOPY (yaxis, curmat[1]);
+	
+	Mat3One(targetmat);
+	VECCOPY(targetmat[0], xaxis);
+	VECCOPY(targetmat[1], yaxis);
+	VECCOPY(targetmat[2], zaxis);
+	Mat3Ortho(targetmat);
+	
+	/* Find the difference between the two matrices */
+	Mat3Inv(imat, targetmat);
+	Mat3MulMat3(diffmat, imat, curmat);
+	
+	// old-method... let's see if using mat3_to_vec_roll is more accurate
+	//ebone->roll = atan2(diffmat[2][0], diffmat[2][2]);  
+	mat3_to_vec_roll(diffmat, delta, &ebone->roll);
+}
+
+/* Set roll value for given bone -> Z-Axis point towards cursor */
+void auto_align_ebone_tocursor(EditBone *ebone)
+{
+	float	delta[3], curmat[3][3];
+	float  	*cursor= give_cursor();
+	float	mat[4][4], tmat[4][4], imat[4][4];
+	float 	rmat[4][4], rot[3];
+	float	vec[3];
+	
+	/* find the current bone matrix as a 4x4 matrix (in Armature Space) */
+	VecSubf(delta, ebone->tail, ebone->head);
+	vec_roll_to_mat3(delta, ebone->roll, curmat);
+	Mat4CpyMat3(mat, curmat);
+	VECCOPY(mat[3], ebone->head);
+	
+	/* multiply bone-matrix by object matrix (so that bone-matrix is in WorldSpace) */
+	Mat4MulMat4(tmat, mat, G.obedit->obmat);
+	Mat4Invert(imat, tmat);
+	
+	/* find position of cursor relative to bone */
+	VecMat4MulVecfl(vec, imat, cursor);
+	
+	/* check that cursor is in usable position */
+	if ((IS_EQ(vec[0], 0)==0) && (IS_EQ(vec[2], 0)==0)) {
+		/* Compute a rotation matrix around y */
+		rot[1] = atan2(vec[0], vec[2]);
+		rot[0] = rot[2] = 0.0f;
+		EulToMat4(rot, rmat);
+		
+		/* Multiply the bone matrix by rotation matrix. This should be new bone-matrix */
+		Mat4MulMat4(tmat, rmat, mat);
+		Mat3CpyMat4(curmat, tmat);
+		
+		/* Now convert from new bone-matrix, back to a roll value (in radians) */
+		mat3_to_vec_roll(curmat, delta, &ebone->roll);
+	}
+}
+
 /* Sets the roll value of selected bones, depending on the mode
  * 	mode == 0: their z-axes point upwards 
  * 	mode == 1: their z-axes point towards 3d-cursor
@@ -1827,10 +1895,18 @@
 	bArmature *arm= G.obedit->data;
 	EditBone *ebone;
 	EditBone *flipbone = NULL;
-	float	delta[3];
-	float	curmat[3][3];
-	float  	*cursor= give_cursor();
-		
+	void (*roll_func)(EditBone *) = NULL;
+	
+	/* specific method used to calculate roll depends on mode */
+	switch (mode) {
+		case 1:  /* Z-Axis point towards cursor */
+			roll_func= auto_align_ebone_tocursor;
+			break;
+		default: /* Z-Axis Point Up */
+			roll_func= auto_align_ebone_zaxisup;
+			break;
+	}
+	
 	for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
 		if (EBONE_VISIBLE(arm, ebone)) {
 			if (arm->flag & ARM_MIRROR_EDIT)
@@ -1839,65 +1915,8 @@
 			if ((ebone->flag & BONE_SELECTED) || 
 				(flipbone && (flipbone->flag & BONE_SELECTED))) 
 			{
-				/* specific method used to calculate roll depends on mode */
-				if (mode == 1) {
-					/* Z-Axis point towards cursor */
-					float	mat[4][4], tmat[4][4], imat[4][4];
-					float 	rmat[4][4], rot[3];
-					float	vec[3];
-					
-					/* find the current bone matrix as a 4x4 matrix (in Armature Space) */
-					VecSubf(delta, ebone->tail, ebone->head);
-					vec_roll_to_mat3(delta, ebone->roll, curmat);
-					Mat4CpyMat3(mat, curmat);
-					VECCOPY(mat[3], ebone->head);
-					
-					/* multiply bone-matrix by object matrix (so that bone-matrix is in WorldSpace) */
-					Mat4MulMat4(tmat, mat, G.obedit->obmat);
-					Mat4Invert(imat, tmat);
-					
-					/* find position of cursor relative to bone */
-					VecMat4MulVecfl(vec, imat, cursor);
-					
-					/* check that cursor is in usable position */
-					if ((IS_EQ(vec[0], 0)==0) && (IS_EQ(vec[2], 0)==0)) {
-						/* Compute a rotation matrix around y */
-						rot[1] = atan2(vec[0], vec[2]);
-						rot[0] = rot[2] = 0.0f;
-						EulToMat4(rot, rmat);
-						
-						/* Multiply the bone matrix by rotation matrix. This should be new bone-matrix */
-						Mat4MulMat4(tmat, rmat, mat);
-						Mat3CpyMat4(curmat, tmat);
-						
-						/* Now convert from new bone-matrix, back to a roll value (in radians) */
-						mat3_to_vec_roll(curmat, delta, &ebone->roll);
-					}
-				}
-				else { 
-					/* Z-Axis Point Up */
-					float	xaxis[3]={1.0, 0.0, 0.0}, yaxis[3], zaxis[3]={0.0, 0.0, 1.0};
-					float	targetmat[3][3], imat[3][3], diffmat[3][3];
-					
-					/* Find the current bone matrix */
-					VecSubf(delta, ebone->tail, ebone->head);
-					vec_roll_to_mat3(delta, 0.0, curmat);
-					
-					/* Make new matrix based on y axis & z-up */
-					VECCOPY (yaxis, curmat[1]);
-					
-					Mat3One(targetmat);
-					VECCOPY (targetmat[0], xaxis);
-					VECCOPY (targetmat[1], yaxis);
-					VECCOPY (targetmat[2], zaxis);
-					Mat3Ortho(targetmat);
-					
-					/* Find the difference between the two matrices */
-					Mat3Inv(imat, targetmat);
-					Mat3MulMat3(diffmat, imat, curmat);
-					
-					ebone->roll = atan2(diffmat[2][0], diffmat[2][2]);
-				}				
+				/* roll func is a callback which assumes that all is well */
+				roll_func(ebone);			
 			}
 		}
 	}

Modified: branches/animsys2/source/blender/src/gpencil.c
===================================================================
--- branches/animsys2/source/blender/src/gpencil.c	2008-11-01 10:18:21 UTC (rev 17258)
+++ branches/animsys2/source/blender/src/gpencil.c	2008-11-01 11:14:05 UTC (rev 17259)
@@ -1004,7 +1004,7 @@
 		G.edbo.last = bones.last;
 		
 		/* WARNING: need to make sure this magic number doesn't change */
-		auto_align_armature(2);	
+		auto_align_armature(0);	
 		
 		/* clear editbones (not needed anymore) */
 		G.edbo.first= G.edbo.last= NULL;

Modified: branches/animsys2/source/blender/src/transform_generics.c
===================================================================
--- branches/animsys2/source/blender/src/transform_generics.c	2008-11-01 10:18:21 UTC (rev 17258)
+++ branches/animsys2/source/blender/src/transform_generics.c	2008-11-01 11:14:05 UTC (rev 17259)
@@ -473,18 +473,31 @@
 			
 			/* Ensure all bones are correctly adjusted */
 			// TODO: bone roll needs to be tweaked too for normal transforms, as it goes crazy atm
-			for (ebo=G.edbo.first; ebo; ebo=ebo->next){
-				
-				if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
+			for (ebo=G.edbo.first; ebo; ebo=ebo->next) {	
+				/* if we're not actively adjusting roll (i.e. not using 'Bone Roll' tool), 
+				 * we need to adjust the roll of the bone so that is doesn't randomly move change on the user
+				 */
+				// TODO: do we need a setting to turn this on/off someday?
+				if (t->mode != TFM_BONE_ROLL) {
+					/* calculate roll of bone whose tip is selected
+					 *	- normal bones should have tip selected if bone is selected
+					 *	- extruded bones only have tip selected
+					 */
+					if (ebo->flag & BONE_TIPSEL) {
+						auto_align_ebone_zaxisup(ebo);
+					}
+				}
+			
+				if ((ebo->flag & BONE_CONNECTED) && ebo->parent) {
 					/* If this bone has a parent tip that has been moved */
-					if (ebo->parent->flag & BONE_TIPSEL){
+					if (ebo->parent->flag & BONE_TIPSEL) {
 						VECCOPY (ebo->head, ebo->parent->tail);
 						if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail;
 					}
 					/* If this bone has a parent tip that has NOT been moved */
-					else{
+					else {
 						VECCOPY (ebo->parent->tail, ebo->head);
-						if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head;
+						if (t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head;
 					}
 				}
 				
@@ -509,7 +522,6 @@
 			}
 			if(arm->flag & ARM_MIRROR_EDIT) 
 				transform_armature_mirror_update();
-			
 		}
 		else if(G.obedit->type==OB_LATTICE) {
 			DAG_object_flush_update(G.scene, G.obedit, OB_RECALC_DATA);  /* sets recalc flags */





More information about the Bf-blender-cvs mailing list