From 1424a171a464f79073da2a00c2b5bfa66bf00bc4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 24 Oct 2010 06:16:44 +0000 Subject: bugfix [#21097] Rotating multiple bones with non-local location behaves incorrectly. - rotation and bone scaling with Durian feature 'Local Location' would fail to correctly translate the bone because a different matrix is needed for translation and rotation. --- source/blender/editors/transform/transform.c | 16 +++++++++++++--- source/blender/editors/transform/transform.h | 3 +++ source/blender/editors/transform/transform_conversions.c | 15 ++++++++++++++- 3 files changed, 30 insertions(+), 4 deletions(-) (limited to 'source/blender/editors') diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index a43078e5d6a..dbeee4fddbd 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -2916,9 +2916,19 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short sub_v3_v3v3(vec, vec, td->center); // Translation needed from the initial location - mul_m3_v3(pmtx, vec); // To Global space - mul_m3_v3(td->smtx, vec);// To Pose space - + /* special exception, see TD_PBONE_LOCAL_MTX definition comments */ + if(td->flag & TD_PBONE_LOCAL_MTX_P) { + /* do nothing */ + } + else if (td->flag & TD_PBONE_LOCAL_MTX_C) { + mul_m3_v3(pmtx, vec); // To Global space + mul_m3_v3(td->ext->l_smtx, vec);// To Pose space (Local Location) + } + else { + mul_m3_v3(pmtx, vec); // To Global space + mul_m3_v3(td->smtx, vec);// To Pose space + } + protectedTransBits(td->protectflag, vec); add_v3_v3v3(td->loc, td->iloc, vec); diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index c897c1df842..49ce4d2e0dd 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -146,6 +146,7 @@ typedef struct TransDataExtension { float *size; /* Size of the data to transform (Faculative) */ float isize[3]; /* Initial size */ float obmat[4][4]; /* Object matrix */ + float l_smtx[3][3]; /* use instead of td->smtx, It is the same but without the 'bone->bone_mat', see TD_PBONE_LOCAL_MTX_C */ } TransDataExtension; typedef struct TransData2D { @@ -432,6 +433,8 @@ typedef struct TransInfo { #define TD_MIRROR_EDGE (1 << 16) /* For editmode mirror, clamp to x = 0 */ #define TD_MOVEHANDLE1 (1 << 17) /* For fcurve handles, move them along with their keyframes */ #define TD_MOVEHANDLE2 (1 << 18) +#define TD_PBONE_LOCAL_MTX_P (1 << 19) /* exceptional case with pose bone rotating when a parent bone has 'Local Location' option enabled and rotating also transforms it. */ +#define TD_PBONE_LOCAL_MTX_C (1 << 20) /* same as above but for a child bone */ /* transsnap->status */ #define SNAP_FORCED 1 diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 5b1813559bb..818e5c2df66 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -554,7 +554,7 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr /* proper way to get parent transform + own transform + constraints transform */ copy_m3_m4(omat, ob->obmat); - if (t->mode==TFM_TRANSLATION && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) + if (ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) unit_m3(bmat); else copy_m3_m3(bmat, pchan->bone->bone_mat); @@ -585,6 +585,19 @@ static void add_pose_transdata(TransInfo *t, bPoseChannel *pchan, Object *ob, Tr invert_m3_m3(td->smtx, td->mtx); + /* exceptional case: rotate the pose bone which also applies transformation + * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */ + if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) { + if(pchan->parent) { + /* same as td->smtx but without pchan->bone->bone_mat */ + td->flag |= TD_PBONE_LOCAL_MTX_C; + mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx); + } + else { + td->flag |= TD_PBONE_LOCAL_MTX_P; + } + } + /* for axismat we use bone's own transform */ copy_m3_m4(pmat, pchan->pose_mat); mul_m3_m3m3(td->axismtx, omat, pmat); -- cgit v1.2.3