diff options
-rw-r--r-- | source/blender/blenkernel/BKE_constraint.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/constraint.c | 59 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/fcurve.c | 8 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_object_api.c | 2 |
4 files changed, 59 insertions, 18 deletions
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index 73bd36844ac..8fe3bd77a26 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -191,8 +191,12 @@ struct bConstraintOb *BKE_constraints_make_evalob(struct Depsgraph *depsgraph, short datatype); void BKE_constraints_clear_evalob(struct bConstraintOb *cob); -void BKE_constraint_mat_convertspace( - struct Object *ob, struct bPoseChannel *pchan, float mat[4][4], short from, short to); +void BKE_constraint_mat_convertspace(struct Object *ob, + struct bPoseChannel *pchan, + float mat[4][4], + short from, + short to, + const bool keep_scale); void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index c1492810a11..f751ccd66b0 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -255,7 +255,7 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob) * For now, this is only implemented for Objects and PoseChannels. */ void BKE_constraint_mat_convertspace( - Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to) + Object *ob, bPoseChannel *pchan, float mat[4][4], short from, short to, const bool keep_scale) { float diff_mat[4][4]; float imat[4][4]; @@ -282,7 +282,7 @@ void BKE_constraint_mat_convertspace( /* use pose-space as stepping stone for other spaces... */ if (ELEM(to, CONSTRAINT_SPACE_LOCAL, CONSTRAINT_SPACE_PARLOCAL)) { /* call self with slightly different values */ - BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); + BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); } break; } @@ -318,7 +318,7 @@ void BKE_constraint_mat_convertspace( /* use pose-space as stepping stone for other spaces */ if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_PARLOCAL)) { /* call self with slightly different values */ - BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); + BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); } break; } @@ -332,7 +332,7 @@ void BKE_constraint_mat_convertspace( /* use pose-space as stepping stone for other spaces */ if (ELEM(to, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) { /* call self with slightly different values */ - BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to); + BKE_constraint_mat_convertspace(ob, pchan, mat, CONSTRAINT_SPACE_POSE, to, keep_scale); } break; } @@ -348,6 +348,27 @@ void BKE_constraint_mat_convertspace( invert_m4_m4_safe(imat, diff_mat); mul_m4_m4m4(mat, imat, mat); } + else { + /* Local space in this case will have to be defined as local to the owner's + * transform-property-rotated axes. So subtract this rotation component. + */ + /* XXX This is actually an ugly hack, local space of a parent-less object *is* the same as + * global space! + * Think what we want actually here is some kind of 'Final Space', i.e + * . once transformations are applied - users are often confused about this too, + * this is not consistent with bones + * local space either... Meh :| + * --mont29 + */ + BKE_object_to_mat4(ob, diff_mat); + if (!keep_scale) { + normalize_m4(diff_mat); + } + zero_v3(diff_mat[3]); + + invert_m4_m4_safe(imat, diff_mat); + mul_m4_m4m4(mat, imat, mat); + } } else if (from == CONSTRAINT_SPACE_LOCAL && to == CONSTRAINT_SPACE_WORLD) { /* check that object has a parent - otherwise this won't work */ @@ -356,6 +377,19 @@ void BKE_constraint_mat_convertspace( mul_m4_m4m4(diff_mat, ob->parent->obmat, ob->parentinv); mul_m4_m4m4(mat, diff_mat, mat); } + else { + /* Local space in this case will have to be defined as local to the owner's + * transform-property-rotated axes. So add back this rotation component. + */ + /* XXX See comment above for world->local case... */ + BKE_object_to_mat4(ob, diff_mat); + if (!keep_scale) { + normalize_m4(diff_mat); + } + zero_v3(diff_mat[3]); + + mul_m4_m4m4(mat, diff_mat, mat); + } } } } @@ -541,7 +575,7 @@ static void constraint_target_to_mat4(Object *ob, /* Case OBJECT */ if (substring[0] == '\0') { copy_m4_m4(mat, ob->obmat); - BKE_constraint_mat_convertspace(ob, NULL, mat, from, to); + BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false); } /* Case VERTEXGROUP */ /* Current method just takes the average location of all the points in the @@ -554,11 +588,11 @@ static void constraint_target_to_mat4(Object *ob, */ else if (ob->type == OB_MESH) { contarget_get_mesh_mat(ob, substring, mat); - BKE_constraint_mat_convertspace(ob, NULL, mat, from, to); + BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false); } else if (ob->type == OB_LATTICE) { contarget_get_lattice_mat(ob, substring, mat); - BKE_constraint_mat_convertspace(ob, NULL, mat, from, to); + BKE_constraint_mat_convertspace(ob, NULL, mat, from, to, false); } /* Case BONE */ else { @@ -622,7 +656,7 @@ static void constraint_target_to_mat4(Object *ob, } /* convert matrix space as required */ - BKE_constraint_mat_convertspace(ob, pchan, mat, from, to); + BKE_constraint_mat_convertspace(ob, pchan, mat, from, to, false); } } @@ -4051,9 +4085,12 @@ static void shrinkwrap_get_tarmat(struct Depsgraph *UNUSED(depsgraph), } /* Transform normal into requested space */ + /* Note that in this specific case, we need to keep scaling in non-parented 'local2world' + * object case, because SpaceTransform also takes it into account when handling normals. + * See T42447. */ unit_m4(mat); BKE_constraint_mat_convertspace( - cob->ob, cob->pchan, mat, CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace); + cob->ob, cob->pchan, mat, CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace, true); invert_m4(mat); mul_mat3_m4_v3(mat, no); @@ -5798,7 +5835,7 @@ void BKE_constraints_solve(struct Depsgraph *depsgraph, /* move owner matrix into right space */ BKE_constraint_mat_convertspace( - cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace); + cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace, false); /* prepare targets for constraint solving */ BKE_constraint_targets_for_solving_get(depsgraph, con, cob, &targets, ctime); @@ -5817,7 +5854,7 @@ void BKE_constraints_solve(struct Depsgraph *depsgraph, /* move owner back into worldspace for next constraint/other business */ if ((con->flag & CONSTRAINT_SPACEONCE) == 0) { BKE_constraint_mat_convertspace( - cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD); + cob->ob, cob->pchan, cob->matrix, con->ownspace, CONSTRAINT_SPACE_WORLD, false); } /* Interpolate the enforcement, to blend result of constraint into final owner transform diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index ee6daa632fc..ebc048ce286 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -1595,7 +1595,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) /* extract transform just like how the constraints do it! */ copy_m4_m4(mat, pchan->pose_mat); BKE_constraint_mat_convertspace( - ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); + ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); /* ... and from that, we get our transform */ copy_v3_v3(tmp_loc, mat[3]); @@ -1621,7 +1621,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) /* extract transform just like how the constraints do it! */ copy_m4_m4(mat, ob->obmat); BKE_constraint_mat_convertspace( - ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL); + ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); /* ... and from that, we get our transform */ copy_v3_v3(tmp_loc, mat[3]); @@ -1698,7 +1698,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) /* just like how the constraints do it! */ copy_m4_m4(mat, pchan->pose_mat); BKE_constraint_mat_convertspace( - ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); + ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); } else { /* specially calculate local matrix, since chan_mat is not valid @@ -1726,7 +1726,7 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) /* just like how the constraints do it! */ copy_m4_m4(mat, ob->obmat); BKE_constraint_mat_convertspace( - ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL); + ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); } else { /* transforms to matrix */ diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index cbeb8f17991..2afebf7e3f6 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -323,7 +323,7 @@ static void rna_Object_mat_convert_space(Object *ob, } } - BKE_constraint_mat_convertspace(ob, pchan, (float(*)[4])mat_ret, from, to); + BKE_constraint_mat_convertspace(ob, pchan, (float(*)[4])mat_ret, from, to, false); } static void rna_Object_calc_matrix_camera(Object *ob, |