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) {

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to