Revision: 17216
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=17216
Author:   aligorith
Date:     2008-10-29 12:20:02 +0100 (Wed, 29 Oct 2008)

Log Message:
-----------
AnimSys2: Bone Rotation (aka choice of Quaternions or Eulers)

This commit introduces an attempt at allowing animators to choose to use 
'euler' rotations for bones (currently, only the default rotation order is 
used... multiple rotation orders may be implemented later). Animators often 
request this feature, so it's time to prove to us that it's genuinely useful!

To switch between quaternions and eulers, use the toggles in the Transform 
Properties panel in PoseMode. This will switch (the active bone only) to 
completely using quaternion rotations or euler rotations. 
- this is a per-bone setting, but can be copied (Ctrl-C menu)
- animation curves for quaternions/eulers will only animate the bone when their 
respective rotation mode is active for that bone (i.e. if you insert keyframes 
for a bone using quaternion rotations, then switch the bone to use eulers, bone 
will not be animated rotating until euler-rotation keyframes are added, and 
visa versa)
- quaternion/euler rotation mode cannot be changed in the middle of an 
animation (it's not implemented, and I don't intend on doing so either... it's 
just asking for trouble in the long run)
- by default, quaternions will be used (to preserve backwards compatability) 
and also because they provide smoother interpolation + no gimble lock
- when switching between interpolation modes, there is conversion of the 
current rotation from quat<->euler (whichever direction is applicable) to avoid 
pops
- euler rotations here use standard euler interpolation. In other words, these 
are not quats masquerading as eulers under a fancy skin.

A number of additional notes:
- Most tools which involve rotation have been adjusted to work with this so 
far. 
--> Note: Copy/Paste of poses doesn't work with this yet.
- NLA pose blending is currently (experimentally) using a simple linear 
interpolation between euler values of poses. This may not well at all, and also 
there are some cases not covered by that yet.
- Improved the keyframing code a bit to add a bit of flexibility so that 
keyframes could be inserted without doubling up entries.

Modified Paths:
--------------
    branches/animsys2/source/blender/blenkernel/intern/action.c
    branches/animsys2/source/blender/blenkernel/intern/armature.c
    branches/animsys2/source/blender/blenkernel/intern/ipo.c
    branches/animsys2/source/blender/include/BIF_keyframing.h
    branches/animsys2/source/blender/makesdna/DNA_action_types.h
    branches/animsys2/source/blender/makesdna/DNA_ipo_types.h
    branches/animsys2/source/blender/src/drawview.c
    branches/animsys2/source/blender/src/editarmature.c
    branches/animsys2/source/blender/src/editipo.c
    branches/animsys2/source/blender/src/editipo_lib.c
    branches/animsys2/source/blender/src/keyframing.c
    branches/animsys2/source/blender/src/poseobject.c
    branches/animsys2/source/blender/src/transform.c
    branches/animsys2/source/blender/src/transform_conversions.c

Modified: branches/animsys2/source/blender/blenkernel/intern/action.c
===================================================================
--- branches/animsys2/source/blender/blenkernel/intern/action.c 2008-10-29 
10:58:00 UTC (rev 17215)
+++ branches/animsys2/source/blender/blenkernel/intern/action.c 2008-10-29 
11:20:02 UTC (rev 17216)
@@ -401,7 +401,9 @@
        
        VECCOPY(pchan->loc, chan->loc);
        VECCOPY(pchan->size, chan->size);
+       VECCOPY(pchan->eul, chan->eul);
        QUATCOPY(pchan->quat, chan->quat);
+       pchan->rotmode= chan->rotmode;
        Mat4CpyMat4(pchan->chan_mat, (float(*)[4])chan->chan_mat);
        Mat4CpyMat4(pchan->pose_mat, (float(*)[4])chan->pose_mat);
        pchan->flag= chan->flag;
@@ -697,7 +699,6 @@
        bPoseChannel *dchan;
        const bPoseChannel *schan;
        bConstraint *dcon, *scon;
-       float   dquat[4], squat[4];
        float dstweight;
        int i;
        
@@ -719,23 +720,34 @@
                        
                        /* Do the transformation blend */
                        if (schan->flag & POSE_ROT) {
-                               QUATCOPY(dquat, dchan->quat);
-                               QUATCOPY(squat, schan->quat);
-                               if(mode==ACTSTRIPMODE_BLEND)
-                                       QuatInterpol(dchan->quat, dquat, squat, 
srcweight);
-                               else {
-                                       QuatMulFac(squat, srcweight);
-                                       QuatMul(dchan->quat, dquat, squat);
+                               /* quat interpolation done separate */
+                               if (schan->rotmode == PCHAN_ROT_QUAT) {
+                                       float dquat[4], squat[4];
+                                       
+                                       QUATCOPY(dquat, dchan->quat);
+                                       QUATCOPY(squat, schan->quat);
+                                       if (mode==ACTSTRIPMODE_BLEND)
+                                               QuatInterpol(dchan->quat, 
dquat, squat, srcweight);
+                                       else {
+                                               QuatMulFac(squat, srcweight);
+                                               QuatMul(dchan->quat, dquat, 
squat);
+                                       }
+                                       
+                                       NormalQuat(dchan->quat);
                                }
-                               
-                               NormalQuat (dchan->quat);
                        }
 
-                       for (i=0; i<3; i++){
+                       for (i=0; i<3; i++) {
+                               /* blending for loc and scale are pretty 
self-explanatory... */
                                if (schan->flag & POSE_LOC)
                                        dchan->loc[i] = 
(dchan->loc[i]*dstweight) + (schan->loc[i]*srcweight);
                                if (schan->flag & POSE_SIZE)
                                        dchan->size[i] = 1.0f + 
((dchan->size[i]-1.0f)*dstweight) + ((schan->size[i]-1.0f)*srcweight);
+                               
+                               /* euler-rotation interpolation done here 
instead... */
+                               // FIXME: are these results decent?
+                               if ((schan->flag & POSE_ROT) && 
(schan->rotmode))
+                                       dchan->eul[i] = 
(dchan->eul[i]*dstweight) + (schan->eul[i]*srcweight);
                        }
                        dchan->flag |= schan->flag;
                }

Modified: branches/animsys2/source/blender/blenkernel/intern/armature.c
===================================================================
--- branches/animsys2/source/blender/blenkernel/intern/armature.c       
2008-10-29 10:58:00 UTC (rev 17215)
+++ branches/animsys2/source/blender/blenkernel/intern/armature.c       
2008-10-29 11:20:02 UTC (rev 17216)
@@ -1216,7 +1216,10 @@
        if (pchan==NULL) return;
        
        /* get the inverse matrix of the pchan's transforms */
-       LocQuatSizeToMat4(pc_trans, pchan->loc, pchan->quat, pchan->size);
+       if (pchan->rotmode)
+               LocEulSizeToMat4(pc_trans, pchan->loc, pchan->eul, pchan->size);
+       else
+               LocQuatSizeToMat4(pc_trans, pchan->loc, pchan->quat, 
pchan->size);
        Mat4Invert(inv_trans, pc_trans);
        
        /* Remove the pchan's transforms from it's pose_mat.
@@ -1967,22 +1970,29 @@
        float rmat[3][3];
        float tmat[3][3];
        
+       /* get scaling matrix */
        SizeToMat3(chan->size, smat);
        
-       NormalQuat(chan->quat);
-
-       QuatToMat3(chan->quat, rmat);
+       /* rotations may either be quats or eulers (no rotation modes for 
now...) */
+       if (chan->rotmode) {
+               /* euler rotations (will cause gimble lock... no rotation order 
to solve that yet) */
+               EulToMat3(chan->eul, rmat);
+       }
+       else {
+               /* quats are normalised before use to eliminate scaling issues 
*/
+               NormalQuat(chan->quat);
+               QuatToMat3(chan->quat, rmat);
+       }
        
+       /* calculate matrix of bone (as 3x3 matrix, but then copy the 4x4) */
        Mat3MulMat3(tmat, rmat, smat);
-       
        Mat4CpyMat3(chan->chan_mat, tmat);
        
        /* prevent action channels breaking chains */
        /* need to check for bone here, CONSTRAINT_TYPE_ACTION uses this call */
-       if (chan->bone==NULL || !(chan->bone->flag & BONE_CONNECTED)) {
+       if ((chan->bone==NULL) || !(chan->bone->flag & BONE_CONNECTED)) {
                VECCOPY(chan->chan_mat[3], chan->loc);
        }
-
 }
 
 /* transform from bone(b) to bone(b+1), store in chan_mat */

Modified: branches/animsys2/source/blender/blenkernel/intern/ipo.c
===================================================================
--- branches/animsys2/source/blender/blenkernel/intern/ipo.c    2008-10-29 
10:58:00 UTC (rev 17215)
+++ branches/animsys2/source/blender/blenkernel/intern/ipo.c    2008-10-29 
11:20:02 UTC (rev 17216)
@@ -103,8 +103,9 @@
 };
 
 int ac_ar[AC_TOTIPO]= {
-       AC_LOC_X, AC_LOC_Y, AC_LOC_Z,  
-        AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z,
+       AC_LOC_X, AC_LOC_Y, AC_LOC_Z,
+       AC_EUL_X, AC_EUL_Y, AC_EUL_Z,
+       AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z,
        AC_SIZE_X, AC_SIZE_Y, AC_SIZE_Z
 };
 
@@ -1158,7 +1159,7 @@
                /* get pointers */
                BezTriple *bezt, *prevbezt, *lastbezt;
                float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac;
-               float cycdx, cycdy, ofs, cycyofs= 0.0;
+               float cycdx, cycdy, ofs, cycyofs= 0.0f;
                int a, b;
                
                /* get pointers */
@@ -1468,12 +1469,17 @@
        if (achan && achan->ipo && pchan) {
                IpoCurve *icu;
                
-               /* loop over IPO-curves, getting a pointer to pchan var to 
write to
-                *      - assume for now that only 'float' channels will ever 
get written into
-                */
+               /* loop over IPO-curves, getting a pointer to pchan var to 
write to */
                for (icu= achan->ipo->curve.first; icu; icu= icu->next) {
                        void *poin= get_pchan_ipo_poin(pchan, icu->adrcode);
-                       if (poin) write_ipo_poin(poin, IPO_FLOAT, icu->curval);
+                       
+                       if (poin) {
+                               /* only euler-rotations are of type 
float-degree, all others are 'float' only */
+                               if (ELEM3(icu->adrcode, AC_EUL_X, AC_EUL_Y, 
AC_EUL_Z))
+                                       write_ipo_poin(poin, IPO_FLOAT_DEGR, 
icu->curval);
+                               else
+                                       write_ipo_poin(poin, IPO_FLOAT, 
icu->curval);
+                       }
                }
        }
 }
@@ -1792,6 +1798,7 @@
 /* --------------------- Get Pointer API ----------------------------- */ 
 
 /* get pointer to pose-channel's channel, but set appropriate flags first */
+// TODO: most channels (except euler rots, which are float-degr) are floats, 
so do we need type arg?
 void *get_pchan_ipo_poin (bPoseChannel *pchan, int adrcode)
 {
        void *poin= NULL;
@@ -1814,6 +1821,22 @@
                        pchan->flag |= POSE_ROT;
                        break;
                        
+               case AC_EUL_X:
+                       poin= &(pchan->eul[0]);
+                       pchan->flag |= POSE_ROT;
+                       //type= IPO_FLOAT_DEGR;
+                       break;
+               case AC_EUL_Y:
+                       poin= &(pchan->eul[1]);
+                       pchan->flag |= POSE_ROT;
+                       //type= IPO_FLOAT_DEGR;
+                       break;
+               case AC_EUL_Z:
+                       poin= &(pchan->eul[2]);
+                       pchan->flag |= POSE_ROT;
+                       //type= IPO_FLOAT_DEGR;
+                       break;
+                       
                case AC_LOC_X:
                        poin= &(pchan->loc[0]); 
                        pchan->flag |= POSE_LOC;

Modified: branches/animsys2/source/blender/include/BIF_keyframing.h
===================================================================
--- branches/animsys2/source/blender/include/BIF_keyframing.h   2008-10-29 
10:58:00 UTC (rev 17215)
+++ branches/animsys2/source/blender/include/BIF_keyframing.h   2008-10-29 
11:20:02 UTC (rev 17216)
@@ -58,8 +58,11 @@
        INSERTKEY_FASTR         = (1<<3),       /* don't realloc mem (or 
increase count, as array has already been set out) */
        INSERTKEY_REPLACE       = (1<<4),       /* only replace an existing 
keyframe (this overrides INSERTKEY_NEEDED) */
        
-               /* used by common_*key() functions */
+               /* used by common_*key() functions - Note: these are generally 
mutually exclusive (only one will work at a time) */
        COMMONKEY_ADDMAP        = (1<<10),      /* common key: add texture-slot 
offset bitflag to adrcode before use */
+       COMMONKEY_PCHANROT      = (1<<11),      /* common key: extend channel 
list using relevant pchan-rotations */
+               /* all possible items for common_*key() functions */
+       COMMONKEY_MODES         = (COMMONKEY_ADDMAP|COMMONKEY_PCHANROT)
 } eInsertKeyFlags;
 
 /* -------- */

Modified: branches/animsys2/source/blender/makesdna/DNA_action_types.h
===================================================================
--- branches/animsys2/source/blender/makesdna/DNA_action_types.h        
2008-10-29 10:58:00 UTC (rev 17215)
+++ branches/animsys2/source/blender/makesdna/DNA_action_types.h        
2008-10-29 11:20:02 UTC (rev 17216)
@@ -22,6 +22,7 @@
  *
  * Contributor(s): Original design: Reevan McKay
  * Contributor(s): Full recode, Ton Roosendaal, Crete 2005
+ * Contributor(s): Animation recode, Joshua Leung
  *
  * ***** END GPL LICENSE BLOCK *****
  */
@@ -70,9 +71,13 @@
        void                            *dual_quat;
        void                            *b_bone_dual_quats;
        
-       float           loc[3];                         /* written in by 
actions or transform */
+       float           loc[3];                         /* transforms - written 
in by actions or transform */
        float           size[3];
+       
+       float           eul[3];                         /* rotations - written 
in by actions or transform (but only euler/quat in use at any one time!) */
        float           quat[4];
+       short           rotmode;                        /* for now either quat 
(0), or xyz-euler (1) */
+       short           pad;
        
        float           chan_mat[4][4];         /* matrix result of 
loc/quat/size , and where we put deform in, see next line */
        float           pose_mat[4][4];         /* constraints accumulate here. 
in the end, pose_mat = bone->arm_mat * chan_mat */
@@ -325,6 +330,13 @@
        BONE_IK_NO_ZDOF_TEMP = (1<<12)
 } PCHAN_IKFLAG;
 
+/* PoseChannel->rotmode */
+typedef enum PCHAN_ROTMODE {
+               /* quaternion rotations (default, and for older Blender 
versions) */
+       PCHAN_ROT_QUAT  = 0,
+               /* euler rotations (xyz only) */
+       PCHAN_ROT_EUL,
+} PCHAN_ROTMODE;
 
 #endif
 

Modified: branches/animsys2/source/blender/makesdna/DNA_ipo_types.h
===================================================================
--- branches/animsys2/source/blender/makesdna/DNA_ipo_types.h   2008-10-29 
10:58:00 UTC (rev 17215)
+++ branches/animsys2/source/blender/makesdna/DNA_ipo_types.h   2008-10-29 
11:20:02 UTC (rev 17216)
@@ -349,8 +349,8 @@
 
 /* ******* PoseChannel (ID_PO) ********* */
 
-#define AC_TOTIPO      10
-#define AC_TOTNAM      10
+#define AC_TOTIPO      13
+#define AC_TOTNAM      13
 
 #define AC_LOC_X       1
 #define AC_LOC_Y       2
@@ -360,6 +360,10 @@
 #define AC_SIZE_Y      14
 #define AC_SIZE_Z      15
 
+#define AC_EUL_X       16
+#define AC_EUL_Y       17
+#define AC_EUL_Z       18
+
 #define AC_QUAT_W      25
 #define AC_QUAT_X      26
 #define AC_QUAT_Y      27
@@ -463,7 +467,6 @@
 #define IPO_CONST              0
 #define IPO_LIN                        1
 #define IPO_BEZ                        2
-       /* not used yet */
 #define IPO_MIXED              3 
 
 /* icu->extrap */

Modified: branches/animsys2/source/blender/src/drawview.c
===================================================================
--- branches/animsys2/source/blender/src/drawview.c     2008-10-29 10:58:00 UTC 
(rev 17215)
+++ branches/animsys2/source/blender/src/drawview.c     2008-10-29 11:20:02 UTC 
(rev 17216)

@@ Diff output truncated at 10240 characters. @@

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

Reply via email to