Revision: 17259
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17259
Author:   aligorith
Date:     2008-11-01 12:14:05 +0100 (Sat, 01 Nov 2008)

Log Message:
-----------
AnimSys2: Bone Roll Issues

In this commit, I've attempted to improve the situation of bone roll problems 
that occur with the recalculate bone roll tool, and also when extruding/moving 
bones under certain conditions.

What's changed:
* When transforming bones, as part of the recalculations done on every update, 
the roll of bones who have their tip selected will be recalculated using the 
'z-axis up' method. Reported by Glenn Melenhorst on BA.org

* Split the 'z-axis up' and 'align z-axis to cursor' roll recalculation methods 
into separate functions that can act as callbacks. Refactored the 
auto_align_armature() function to support this. It was needed for the first 
major change to occur.

* As an experiment, I've changed the final step of the z-axis method to use 
mat3_to_vec_roll instead of atan2 directly. It currently seems to work better, 
but I'm not totally sure yet. Will check on this again another day...

Modified Paths:
--------------
    branches/animsys2/source/blender/include/BIF_editarmature.h
    branches/animsys2/source/blender/src/editarmature.c
    branches/animsys2/source/blender/src/gpencil.c
    branches/animsys2/source/blender/src/transform_generics.c

Modified: branches/animsys2/source/blender/include/BIF_editarmature.h
===================================================================
--- branches/animsys2/source/blender/include/BIF_editarmature.h 2008-11-01 
10:18:21 UTC (rev 17258)
+++ branches/animsys2/source/blender/include/BIF_editarmature.h 2008-11-01 
11:14:05 UTC (rev 17259)
@@ -117,7 +117,10 @@
 void   setflag_armature(short mode);
 void    unique_editbone_name (struct ListBase *ebones, char *name);
 
+void   auto_align_ebone_zaxisup(EditBone *ebone);
+void   auto_align_ebone_tocursor(EditBone *ebone);
 void   auto_align_armature(short mode);
+
 void   switch_direction_armature(void);
 
 void   create_vgroups_from_armature(struct Object *ob, struct Object *par);

Modified: branches/animsys2/source/blender/src/editarmature.c
===================================================================
--- branches/animsys2/source/blender/src/editarmature.c 2008-11-01 10:18:21 UTC 
(rev 17258)
+++ branches/animsys2/source/blender/src/editarmature.c 2008-11-01 11:14:05 UTC 
(rev 17259)
@@ -1818,6 +1818,74 @@
        }
 }
 
+
+/* Set roll value for given bone -> Z-Axis Point up (original method) */
+void auto_align_ebone_zaxisup(EditBone *ebone)
+{
+       float   delta[3], curmat[3][3];
+       float   xaxis[3]={1.0, 0.0, 0.0}, yaxis[3], zaxis[3]={0.0f, 0.0f, 1.0f};
+       float   targetmat[3][3], imat[3][3], diffmat[3][3];
+       
+       /* Find the current bone matrix */
+       VecSubf(delta, ebone->tail, ebone->head);
+       vec_roll_to_mat3(delta, 0.0f, curmat);
+       
+       /* Make new matrix based on y axis & z-up */
+       VECCOPY (yaxis, curmat[1]);
+       
+       Mat3One(targetmat);
+       VECCOPY(targetmat[0], xaxis);
+       VECCOPY(targetmat[1], yaxis);
+       VECCOPY(targetmat[2], zaxis);
+       Mat3Ortho(targetmat);
+       
+       /* Find the difference between the two matrices */
+       Mat3Inv(imat, targetmat);
+       Mat3MulMat3(diffmat, imat, curmat);
+       
+       // old-method... let's see if using mat3_to_vec_roll is more accurate
+       //ebone->roll = atan2(diffmat[2][0], diffmat[2][2]);  
+       mat3_to_vec_roll(diffmat, delta, &ebone->roll);
+}
+
+/* Set roll value for given bone -> Z-Axis point towards cursor */
+void auto_align_ebone_tocursor(EditBone *ebone)
+{
+       float   delta[3], curmat[3][3];
+       float   *cursor= give_cursor();
+       float   mat[4][4], tmat[4][4], imat[4][4];
+       float   rmat[4][4], rot[3];
+       float   vec[3];
+       
+       /* find the current bone matrix as a 4x4 matrix (in Armature Space) */
+       VecSubf(delta, ebone->tail, ebone->head);
+       vec_roll_to_mat3(delta, ebone->roll, curmat);
+       Mat4CpyMat3(mat, curmat);
+       VECCOPY(mat[3], ebone->head);
+       
+       /* multiply bone-matrix by object matrix (so that bone-matrix is in 
WorldSpace) */
+       Mat4MulMat4(tmat, mat, G.obedit->obmat);
+       Mat4Invert(imat, tmat);
+       
+       /* find position of cursor relative to bone */
+       VecMat4MulVecfl(vec, imat, cursor);
+       
+       /* check that cursor is in usable position */
+       if ((IS_EQ(vec[0], 0)==0) && (IS_EQ(vec[2], 0)==0)) {
+               /* Compute a rotation matrix around y */
+               rot[1] = atan2(vec[0], vec[2]);
+               rot[0] = rot[2] = 0.0f;
+               EulToMat4(rot, rmat);
+               
+               /* Multiply the bone matrix by rotation matrix. This should be 
new bone-matrix */
+               Mat4MulMat4(tmat, rmat, mat);
+               Mat3CpyMat4(curmat, tmat);
+               
+               /* Now convert from new bone-matrix, back to a roll value (in 
radians) */
+               mat3_to_vec_roll(curmat, delta, &ebone->roll);
+       }
+}
+
 /* Sets the roll value of selected bones, depending on the mode
  *     mode == 0: their z-axes point upwards 
  *     mode == 1: their z-axes point towards 3d-cursor
@@ -1827,10 +1895,18 @@
        bArmature *arm= G.obedit->data;
        EditBone *ebone;
        EditBone *flipbone = NULL;
-       float   delta[3];
-       float   curmat[3][3];
-       float   *cursor= give_cursor();
-               
+       void (*roll_func)(EditBone *) = NULL;
+       
+       /* specific method used to calculate roll depends on mode */
+       switch (mode) {
+               case 1:  /* Z-Axis point towards cursor */
+                       roll_func= auto_align_ebone_tocursor;
+                       break;
+               default: /* Z-Axis Point Up */
+                       roll_func= auto_align_ebone_zaxisup;
+                       break;
+       }
+       
        for (ebone = G.edbo.first; ebone; ebone=ebone->next) {
                if (EBONE_VISIBLE(arm, ebone)) {
                        if (arm->flag & ARM_MIRROR_EDIT)
@@ -1839,65 +1915,8 @@
                        if ((ebone->flag & BONE_SELECTED) || 
                                (flipbone && (flipbone->flag & BONE_SELECTED))) 
                        {
-                               /* specific method used to calculate roll 
depends on mode */
-                               if (mode == 1) {
-                                       /* Z-Axis point towards cursor */
-                                       float   mat[4][4], tmat[4][4], 
imat[4][4];
-                                       float   rmat[4][4], rot[3];
-                                       float   vec[3];
-                                       
-                                       /* find the current bone matrix as a 
4x4 matrix (in Armature Space) */
-                                       VecSubf(delta, ebone->tail, 
ebone->head);
-                                       vec_roll_to_mat3(delta, ebone->roll, 
curmat);
-                                       Mat4CpyMat3(mat, curmat);
-                                       VECCOPY(mat[3], ebone->head);
-                                       
-                                       /* multiply bone-matrix by object 
matrix (so that bone-matrix is in WorldSpace) */
-                                       Mat4MulMat4(tmat, mat, G.obedit->obmat);
-                                       Mat4Invert(imat, tmat);
-                                       
-                                       /* find position of cursor relative to 
bone */
-                                       VecMat4MulVecfl(vec, imat, cursor);
-                                       
-                                       /* check that cursor is in usable 
position */
-                                       if ((IS_EQ(vec[0], 0)==0) && 
(IS_EQ(vec[2], 0)==0)) {
-                                               /* Compute a rotation matrix 
around y */
-                                               rot[1] = atan2(vec[0], vec[2]);
-                                               rot[0] = rot[2] = 0.0f;
-                                               EulToMat4(rot, rmat);
-                                               
-                                               /* Multiply the bone matrix by 
rotation matrix. This should be new bone-matrix */
-                                               Mat4MulMat4(tmat, rmat, mat);
-                                               Mat3CpyMat4(curmat, tmat);
-                                               
-                                               /* Now convert from new 
bone-matrix, back to a roll value (in radians) */
-                                               mat3_to_vec_roll(curmat, delta, 
&ebone->roll);
-                                       }
-                               }
-                               else { 
-                                       /* Z-Axis Point Up */
-                                       float   xaxis[3]={1.0, 0.0, 0.0}, 
yaxis[3], zaxis[3]={0.0, 0.0, 1.0};
-                                       float   targetmat[3][3], imat[3][3], 
diffmat[3][3];
-                                       
-                                       /* Find the current bone matrix */
-                                       VecSubf(delta, ebone->tail, 
ebone->head);
-                                       vec_roll_to_mat3(delta, 0.0, curmat);
-                                       
-                                       /* Make new matrix based on y axis & 
z-up */
-                                       VECCOPY (yaxis, curmat[1]);
-                                       
-                                       Mat3One(targetmat);
-                                       VECCOPY (targetmat[0], xaxis);
-                                       VECCOPY (targetmat[1], yaxis);
-                                       VECCOPY (targetmat[2], zaxis);
-                                       Mat3Ortho(targetmat);
-                                       
-                                       /* Find the difference between the two 
matrices */
-                                       Mat3Inv(imat, targetmat);
-                                       Mat3MulMat3(diffmat, imat, curmat);
-                                       
-                                       ebone->roll = atan2(diffmat[2][0], 
diffmat[2][2]);
-                               }                               
+                               /* roll func is a callback which assumes that 
all is well */
+                               roll_func(ebone);                       
                        }
                }
        }

Modified: branches/animsys2/source/blender/src/gpencil.c
===================================================================
--- branches/animsys2/source/blender/src/gpencil.c      2008-11-01 10:18:21 UTC 
(rev 17258)
+++ branches/animsys2/source/blender/src/gpencil.c      2008-11-01 11:14:05 UTC 
(rev 17259)
@@ -1004,7 +1004,7 @@
                G.edbo.last = bones.last;
                
                /* WARNING: need to make sure this magic number doesn't change 
*/
-               auto_align_armature(2); 
+               auto_align_armature(0); 
                
                /* clear editbones (not needed anymore) */
                G.edbo.first= G.edbo.last= NULL;

Modified: branches/animsys2/source/blender/src/transform_generics.c
===================================================================
--- branches/animsys2/source/blender/src/transform_generics.c   2008-11-01 
10:18:21 UTC (rev 17258)
+++ branches/animsys2/source/blender/src/transform_generics.c   2008-11-01 
11:14:05 UTC (rev 17259)
@@ -473,18 +473,31 @@
                        
                        /* Ensure all bones are correctly adjusted */
                        // TODO: bone roll needs to be tweaked too for normal 
transforms, as it goes crazy atm
-                       for (ebo=G.edbo.first; ebo; ebo=ebo->next){
-                               
-                               if ((ebo->flag & BONE_CONNECTED) && 
ebo->parent){
+                       for (ebo=G.edbo.first; ebo; ebo=ebo->next) {    
+                               /* if we're not actively adjusting roll (i.e. 
not using 'Bone Roll' tool), 
+                                * we need to adjust the roll of the bone so 
that is doesn't randomly move change on the user
+                                */
+                               // TODO: do we need a setting to turn this 
on/off someday?
+                               if (t->mode != TFM_BONE_ROLL) {
+                                       /* calculate roll of bone whose tip is 
selected
+                                        *      - normal bones should have tip 
selected if bone is selected
+                                        *      - extruded bones only have tip 
selected
+                                        */
+                                       if (ebo->flag & BONE_TIPSEL) {
+                                               auto_align_ebone_zaxisup(ebo);
+                                       }
+                               }
+                       
+                               if ((ebo->flag & BONE_CONNECTED) && 
ebo->parent) {
                                        /* If this bone has a parent tip that 
has been moved */
-                                       if (ebo->parent->flag & BONE_TIPSEL){
+                                       if (ebo->parent->flag & BONE_TIPSEL) {
                                                VECCOPY (ebo->head, 
ebo->parent->tail);
                                                if(t->mode==TFM_BONE_ENVELOPE) 
ebo->rad_head= ebo->parent->rad_tail;
                                        }
                                        /* If this bone has a parent tip that 
has NOT been moved */
-                                       else{
+                                       else {
                                                VECCOPY (ebo->parent->tail, 
ebo->head);
-                                               if(t->mode==TFM_BONE_ENVELOPE) 
ebo->parent->rad_tail= ebo->rad_head;
+                                               if (t->mode==TFM_BONE_ENVELOPE) 
ebo->parent->rad_tail= ebo->rad_head;
                                        }
                                }
                                
@@ -509,7 +522,6 @@
                        }
                        if(arm->flag & ARM_MIRROR_EDIT) 
                                transform_armature_mirror_update();
-                       
                }
                else if(G.obedit->type==OB_LATTICE) {
                        DAG_object_flush_update(G.scene, G.obedit, 
OB_RECALC_DATA);  /* sets recalc flags */


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

Reply via email to