[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [42056] trunk/blender/source/blender/ editors/object/object_constraint.c: Attempted bugfix to improve behaviour of inverse calculations for ChildOf

Joshua Leung aligorith at gmail.com
Tue Nov 22 12:51:13 CET 2011


Revision: 42056
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=42056
Author:   aligorith
Date:     2011-11-22 11:51:12 +0000 (Tue, 22 Nov 2011)
Log Message:
-----------
Attempted bugfix to improve behaviour of inverse calculations for ChildOf
Constraint (bones case only for now). See [#29100] for some problematic test
cases

* It is no longer necessary to have to press "Clear Inverse" before doing "Set
Inverse" to get a reliable result. The calculation now calculates the pose with
the inverse cleared as it's "baseline" first now, which has the same result as
clearing the inverse manually first.

* Also, this commit trials a new method for computing inverses when there is
more than one constraint on the bone. Previously it just temporarily muted the
offending constraint, but kept all following constraints active, thus
potentially including their results in the inverse calculation. However, since
the inverse should only really care about what the stack looked like up to and
including when the constraint is applied, all constraints starting from this one
onwards are now disabled when calculating the inverse.  PLEASE TEST!!! In the
few tests I've done, the effects appear minimal, but this may be quite an issue
in the wild

Modified Paths:
--------------
    trunk/blender/source/blender/editors/object/object_constraint.c

Modified: trunk/blender/source/blender/editors/object/object_constraint.c
===================================================================
--- trunk/blender/source/blender/editors/object/object_constraint.c	2011-11-22 11:37:17 UTC (rev 42055)
+++ trunk/blender/source/blender/editors/object/object_constraint.c	2011-11-22 11:51:12 UTC (rev 42056)
@@ -691,6 +691,7 @@
 	Object *ob = ED_object_active_context(C);
 	bConstraint *con = edit_constraint_property_get(op, ob, CONSTRAINT_TYPE_CHILDOF);
 	bChildOfConstraint *data= (con) ? (bChildOfConstraint *)con->data : NULL;
+	bConstraint *lastcon = NULL;
 	bPoseChannel *pchan= NULL;
 	
 	/* despite 3 layers of checks, we may still not be able to find a constraint */
@@ -703,27 +704,45 @@
 	/* nullify inverse matrix first */
 	unit_m4(data->invmat);
 	
-	/* try to find a pose channel */
+	/* try to find a pose channel - assume that this is the constraint owner */
 	// TODO: get from context instead?
 	if (ob && ob->pose)
 		pchan= get_active_posechannel(ob);
 	
-	/* calculate/set inverse matrix */
+	/* calculate/set inverse matrix:
+	 * 	We just calculate all transform-stack eval up to but not including this constraint.
+	 * 	This is because inverse should just inverse correct for just the constraint's influence
+	 * 	when it gets applied; that is, at the time of application, we don't know anything about
+	 * 	what follows.
+	 */
 	if (pchan) {
-		float pmat[4][4], cinf;
 		float imat[4][4], tmat[4][4];
+		float pmat[4][4];
 		
-		/* make copy of pchan's original pose-mat (for use later) */
+		/* 1. calculate posemat where inverse doesn't exist yet (inverse was cleared above), 
+		 * to use as baseline ("pmat") to derive delta from. This extra calc saves users 
+		 * from having pressing "Clear Inverse" first
+		 */
+		where_is_pose(scene, ob);
 		copy_m4_m4(pmat, pchan->pose_mat);
 		
-		/* disable constraint for pose to be solved without it */
-		cinf= con->enforce;
-		con->enforce= 0.0f;
+		/* 2. knock out constraints starting from this one */
+		lastcon = pchan->constraints.last;
+		pchan->constraints.last = con->prev;
 		
-		/* solve pose without constraint */
+		if (con->prev) {
+			/* new end must not point to this one, else this chain cutting is useless */
+			con->prev->next = NULL;
+		}
+		else {
+			/* constraint was first */
+			pchan->constraints.first = NULL;
+		}
+		
+		/* 3. solve pose without disabled constraints */
 		where_is_pose(scene, ob);
 		
-		/* determine effect of constraint by removing the newly calculated 
+		/* 4. determine effect of constraint by removing the newly calculated 
 		 * pchan->pose_mat from the original pchan->pose_mat, thus determining 
 		 * the effect of the constraint
 		 */
@@ -731,8 +750,19 @@
 		mul_m4_m4m4(tmat, imat, pmat);
 		invert_m4_m4(data->invmat, tmat);
 		
-		/* recalculate pose with new inv-mat */
-		con->enforce= cinf;
+		/* 5. restore constraints */
+		pchan->constraints.last = lastcon;
+		
+		if (con->prev) {
+			/* hook up prev to this one again */
+			con->prev->next = con;
+		}
+		else {
+			/* set as first again */
+			pchan->constraints.first = con;
+		}
+		
+		/* 6. recalculate pose with new inv-mat applied */
 		where_is_pose(scene, ob);
 	}
 	else if (ob) {




More information about the Bf-blender-cvs mailing list