Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2011-11-22 15:51:12 +0400
committerJoshua Leung <aligorith@gmail.com>2011-11-22 15:51:12 +0400
commit374214ecb2e7d735a12032e8873c6be08ba418e4 (patch)
tree5673344f1f4ee2e7a3175d4abf1ee64effc056ba /source/blender/editors/object/object_constraint.c
parent4521192ee7c96fd6ac50fd251a8b27d17028d217 (diff)
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
Diffstat (limited to 'source/blender/editors/object/object_constraint.c')
-rw-r--r--source/blender/editors/object/object_constraint.c52
1 files changed, 41 insertions, 11 deletions
diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c
index 3c84b2df1d2..40d52e0b261 100644
--- a/source/blender/editors/object/object_constraint.c
+++ b/source/blender/editors/object/object_constraint.c
@@ -691,6 +691,7 @@ static int childof_set_inverse_exec (bContext *C, wmOperator *op)
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 @@ static int childof_set_inverse_exec (bContext *C, wmOperator *op)
/* 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;
+
+ 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;
+ }
- /* solve pose without constraint */
+ /* 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 @@ static int childof_set_inverse_exec (bContext *C, wmOperator *op)
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) {