bugfix [#21097] Rotating multiple bones with non-local location behaves incorrectly.
authorCampbell Barton <ideasman42@gmail.com>
Sun, 24 Oct 2010 06:16:44 +0000 (06:16 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 24 Oct 2010 06:16:44 +0000 (06:16 +0000)
- 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
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_conversions.c

index a43078e5d6a25fdf6b054b9e8d0c470341d988c9..dbeee4fddbda162d1271bf9ae2b0518a0eadcdeb 100644 (file)
@@ -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);
index c897c1df84299882ffaf9731c35dd71be71cdea0..49ce4d2e0dd6c3723d3c490cafa99cc82727e90c 100644 (file)
@@ -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
index 5b1813559bb0255e5046aa9204ed33d2cc3edc61..818e5c2df6678b75f997aa13334e0283b1cb0564 100644 (file)
@@ -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);