Gimbal Transform orientations
authorMartin Poirier <theeth@yahoo.com>
Wed, 28 Oct 2009 20:30:33 +0000 (20:30 +0000)
committerMartin Poirier <theeth@yahoo.com>
Wed, 28 Oct 2009 20:30:33 +0000 (20:30 +0000)
Will use rotation gimbal axis when an object or bone set to Euler rotation mode is selected (global axis otherwise)

Use case: being able to do rotations that only affect one animation curve in the 3d view instead of just in the curve editor.

I'm committing this right now despite what follows because it's already useful as is.

Known bug: manipulator arrows can look slightly skewed (not really a big problem), but more importantly, rotation circles for the rotation manipulator are skewed and will not perfectly reflect the rotation axis (it will still use the correct one though). That will be fixed shortly.

To do: This orientation should act like Local, where each object/bone uses its own orientation and not just the one of the active object/bone.

Note: Saved files with custom orientations might end up with other orientations selected when being opened up. I don't think it's that useful to make a do_version for that, but I can if warranted.

source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/intern/arithb.c
source/blender/editors/transform/transform_constraints.c
source/blender/editors/transform/transform_manipulator.c
source/blender/editors/transform/transform_orientations.c
source/blender/makesdna/DNA_view3d_types.h
source/blender/makesrna/intern/rna_space.c

index fdccb3854a609f666c820b23a2964f46e60e547e..901caaee15fd5db1f465c003dcc1f91656dd485b 100644 (file)
@@ -218,7 +218,7 @@ void Mat4ToEul(float tmat[][4],float *eul);
 void EulToQuat(float *eul, float *quat);
 
 void Mat3ToCompatibleEul(float mat[][3], float *eul, float *oldrot);
-
+void EulToGimbalAxis(float gmat[][3], float *eul, short order);
 
 
 void compatible_eul(float *eul, float *oldrot);
index 6c9ae78bac44f769842d7a607ec704ffe064cff8..0d3304557c3d66885811211e4741e60a6fcd4cf8 100644 (file)
@@ -3310,6 +3310,69 @@ void Mat3ToCompatibleEul(float mat[][3], float *eul, float *oldrot)
                VecCopyf(eul, eul1);
        }
        
+}
+
+/* the matrix is written to as 3 axis vectors */
+void EulToGimbalAxis(float gmat[][3], float *eul, short order)
+{
+       RotOrderInfo *R= GET_ROTATIONORDER_INFO(order);
+       short R_order[3];
+       short R_order2[3];
+
+       float quat[4];
+       float teul[3];
+       float tvec[3];
+       int i, a;
+
+       R_order2[R->i]= 0;
+       R_order2[R->j]= 1;
+       R_order2[R->k]= 2;
+
+       R_order[0]= R->i;
+       R_order[1]= R->j;
+       R_order[2]= R->k;
+
+       for(i= 0; i<3; i++) {
+               tvec[0]= tvec[1]= tvec[2]= 0.0f;
+               tvec[i] = 1.0f;
+
+               VecCopyf(teul, eul);
+
+               for(a= R_order2[i]; a >= 1; a--)
+                       teul[R_order[a-1]]= 0.0f;
+
+               EulOToQuat(teul, order, quat);
+               NormalQuat(quat);
+               QuatMulVecf(quat, tvec);
+               Normalize(tvec);
+
+               VecCopyf(gmat[i], tvec);
+       }
+
+
+#if 0
+
+       for(i= 0; i<3; i++) {
+               tvec[0]= tvec[1]= tvec[2]= 0.0f;
+               tvec[i] = 1.0f;
+
+               VecCopyf(teul, eul);
+
+               for(a= R_order2[i]; a >= 1; a--)
+                       teul[R_order[a-1]]= 0.0f;
+
+               EulToQuat(teul, quat);
+               NormalQuat(quat);
+               QuatMulVecf(quat, tvec);
+               Normalize(tvec);
+
+               VecCopyf(gmat[i], tvec);
+       }
+#endif
+
+
+
+
 }
 
 /* ************ AXIS ANGLE *************** */
index 1143203217b3b74635ed69a27ab2f922b2ee9eb6..f80084f7820397715775b3d57bd6ef6952fa9274 100644 (file)
@@ -575,6 +575,10 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char fte
                sprintf(text, ftext, "view");
                setConstraint(t, t->spacemtx, mode, text);
                break;
+       case V3D_MANIP_GIMBAL:
+               sprintf(text, ftext, "gimbal");
+               setConstraint(t, t->spacemtx, mode, text);
+               break;
        default: /* V3D_MANIP_CUSTOM */
                sprintf(text, ftext, t->spacename);
                setConstraint(t, t->spacemtx, mode, text);
index bdf0a91bf89b259cfde03abf28b9e17035edd888..2247977ef87640088f2254e50bfa59bbde64b38e 100644 (file)
@@ -175,6 +175,61 @@ static void stats_editbone(View3D *v3d, EditBone *ebo)
                protectflag_to_drawflags(OB_LOCK_LOC|OB_LOCK_ROT|OB_LOCK_SCALE, &v3d->twdrawflag);
 }
 
+
+static int test_rotmode_euler(short rotmode)
+{
+       return (ELEM(rotmode, ROT_MODE_AXISANGLE, ROT_MODE_QUAT)) ? 0:1;
+}
+
+void gimbalAxis(Object *ob, float gmat[][3])
+{
+       if(ob->mode & OB_MODE_POSE)
+       {
+               bPoseChannel *pchan= NULL;
+
+               /* use channels to get stats */
+               for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+                       if (pchan->bone && pchan->bone->flag & BONE_ACTIVE) {
+                               if(test_rotmode_euler(pchan->rotmode)) {
+                                       break;
+                               }
+                       }
+               }
+
+               if(pchan) {
+                       int i;
+
+                       EulToGimbalAxis(gmat, pchan->eul, pchan->rotmode);
+
+                       for (i=0; i<3; i++)
+                               Mat3MulVecfl(pchan->bone->bone_mat, gmat[i]);
+
+                       if(pchan->parent) {
+                               bPoseChannel *pchan_par= pchan->parent;
+
+                               float tmat[3][3];
+                               Mat3CpyMat4(tmat, pchan_par->pose_mat);
+
+                               for (i=0; i<3; i++)
+                                       Mat3MulVecfl(tmat, gmat[i]);
+                       }
+
+                       /* needed if object trans isnt identity */
+                       for (i=0; i<3; i++) {
+                               float tmat[3][3];
+                               Mat3CpyMat4(tmat, ob->obmat);
+                               Mat3MulVecfl(tmat, gmat[i]);
+                       }
+               }
+       }
+       else {
+               if(test_rotmode_euler(ob->rotmode)) {
+                       EulToGimbalAxis(gmat, ob->rot, ob->rotmode);
+               }
+       }
+}
+
+
 /* centroid, boundbox, of selection */
 /* returns total items selected */
 int calc_manipulator_stats(const bContext *C)
@@ -416,6 +471,14 @@ int calc_manipulator_stats(const bContext *C)
                case V3D_MANIP_GLOBAL:
                        break; /* nothing to do */
 
+               case V3D_MANIP_GIMBAL:
+               {
+                       float mat[3][3];
+                       Mat3One(mat);
+                       gimbalAxis(ob, mat);
+                       Mat4CpyMat3(rv3d->twmat, mat);
+                       break;
+               }
                case V3D_MANIP_NORMAL:
                        if(obedit || ob->mode & OB_MODE_POSE) {
                                float mat[3][3];
@@ -1404,9 +1467,10 @@ void BIF_draw_manipulator(const bContext *C)
        int totsel;
 
        if(!(v3d->twflag & V3D_USE_MANIPULATOR)) return;
-       if(G.moving && (G.moving & G_TRANSFORM_MANIP)==0) return;
+//     if(G.moving && (G.moving & G_TRANSFORM_MANIP)==0) return;
 
-       if(G.moving==0) {
+//     if(G.moving==0) {
+       {
                v3d->twflag &= ~V3D_DRAW_MANIPULATOR;
 
                totsel= calc_manipulator_stats(C);
@@ -1454,7 +1518,7 @@ void BIF_draw_manipulator(const bContext *C)
                                else draw_manipulator_rotate_cyl(v3d, rv3d, 0, drawflags, v3d->twtype, MAN_RGB);
                        }
                        else
-                               draw_manipulator_rotate(v3d, rv3d, G.moving, drawflags, v3d->twtype);
+                               draw_manipulator_rotate(v3d, rv3d, 0 /* G.moving*/, drawflags, v3d->twtype);
 
                        glDisable(GL_BLEND);
                }
index c9344b97fb20ba798b1ffc79162074088d562569..e790b38dd679eb149820d0451bd9da9b54d1c439 100644 (file)
@@ -434,7 +434,7 @@ EnumPropertyItem *BIF_enumTransformOrientation(bContext *C)
 }
 
 char * BIF_menustringTransformOrientation(const bContext *C, char *title) {
-       char menu[] = "%t|Global%x0|Local%x1|Normal%x2|View%x3";
+       char menu[] = "%t|Global%x0|Local%x1|Gimbal%x4|Normal%x2|View%x3";
        ListBase *transform_spaces = &CTX_data_scene(C)->transform_spaces;
        TransformOrientation *ts;
        int i = V3D_MANIP_CUSTOM;
@@ -510,6 +510,7 @@ static int count_bone_select(bArmature *arm, ListBase *lb, int do_it)
        return total;
 }
 
+extern void gimbalAxis(Object *ob, float gimbal_vecs[][3]);
 void initTransformOrientation(bContext *C, TransInfo *t)
 {
        View3D *v3d = CTX_wm_view3d(C);
@@ -522,7 +523,12 @@ void initTransformOrientation(bContext *C, TransInfo *t)
        case V3D_MANIP_GLOBAL:
                strcpy(t->spacename, "global");
                break;
-               
+
+       case V3D_MANIP_GIMBAL:
+               Mat3One(t->spacemtx);
+               if(ob)
+                       gimbalAxis(ob, t->spacemtx);
+               break;
        case V3D_MANIP_NORMAL:
                if(obedit || ob->mode & OB_MODE_POSE) {
                        float mat[3][3];
index 564d6749c16676574f4f07966a6779091cc51a61..422c56fe4c1218fac0b367ccacedfd2fbaf06986 100644 (file)
@@ -263,7 +263,8 @@ typedef struct View3D {
 #define V3D_MANIP_LOCAL                        1
 #define V3D_MANIP_NORMAL               2
 #define V3D_MANIP_VIEW                 3
-#define V3D_MANIP_CUSTOM               4 /* anything of value 4 or higher is custom */
+#define V3D_MANIP_GIMBAL               4
+#define V3D_MANIP_CUSTOM               5 /* anything of value 5 or higher is custom */
 
 /* View3d->twflag */
    /* USE = user setting, DRAW = based on selection */
index e46ba16e3d924cbdae670016aec73ecd5c38c3c9..43172f0a1e86d5a142f551df7bd2fcae3fc66235 100644 (file)
@@ -77,6 +77,7 @@ static EnumPropertyItem draw_channels_items[] = {
 static EnumPropertyItem transform_orientation_items[] = {
        {V3D_MANIP_GLOBAL, "GLOBAL", 0, "Global", "Align the transformation axes to world space"},
        {V3D_MANIP_LOCAL, "LOCAL", 0, "Local", "Align the transformation axes to the selected objects' local space"},
+       {V3D_MANIP_GIMBAL, "GIMBAL", 0, "Gimbal", "Align each axis to the euler rotation axis as used for input"},
        {V3D_MANIP_NORMAL, "NORMAL", 0, "Normal", "Align the transformation axes to average normal of selected elements (bone Y axis for pose mode)"},
        {V3D_MANIP_VIEW, "VIEW", 0, "View", "Align the transformation axes to the window"},
        {V3D_MANIP_CUSTOM, "CUSTOM", 0, "Custom", "Use a custom transform orientation"},
@@ -169,6 +170,7 @@ EnumPropertyItem *rna_TransformOrientation_itemf(bContext *C, PointerRNA *ptr, i
 
        RNA_enum_items_add_value(&item, &totitem, transform_orientation_items, V3D_MANIP_GLOBAL);
        RNA_enum_items_add_value(&item, &totitem, transform_orientation_items, V3D_MANIP_NORMAL);
+       RNA_enum_items_add_value(&item, &totitem, transform_orientation_items, V3D_MANIP_GIMBAL);
        RNA_enum_items_add_value(&item, &totitem, transform_orientation_items, V3D_MANIP_LOCAL);
        RNA_enum_items_add_value(&item, &totitem, transform_orientation_items, V3D_MANIP_VIEW);