merge with trunk at r27259 and commit of a patch by anthony jones to fix msvc (though...
[blender-staging.git] / source / blender / blenkernel / intern / armature.c
index 348daeaf45e03bf35a182fc77f69e4f06d80a2f8..41fe3da248ea03c6ff819ea336b0efd19bae4c81 100644 (file)
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
@@ -275,7 +275,7 @@ void bone_flip_name (char *name, int strip_number)
 
        /* We first check the case with a .### extension, let's find the last period */
        if(isdigit(name[len-1])) {
-               index= strrchr(name, '.');      // last occurrance
+               index= strrchr(name, '.');      // last occurrence
                if (index && isdigit(index[1]) ) {              // doesnt handle case bone.1abc2 correct..., whatever!
                        if(strip_number==0) 
                                strcpy(number, index);
@@ -1267,8 +1267,36 @@ void armature_loc_pose_to_bone(bPoseChannel *pchan, float *inloc, float *outloc)
        VECCOPY(outloc, nLocMat[3]);
 }
 
+
+/* Apply a 4x4 matrix to the pose bone,
+ * similar to object_apply_mat4()
+ */
+void pchan_apply_mat4(bPoseChannel *pchan, float mat[][4])
+{
+       /* location */
+       copy_v3_v3(pchan->loc, mat[3]);
+
+       /* scale */
+       mat4_to_size(pchan->size, mat);
+
+       /* rotation */
+       if (pchan->rotmode == ROT_MODE_AXISANGLE) {
+               float tmp_quat[4];
+
+               /* need to convert to quat first (in temp var)... */
+               mat4_to_quat(tmp_quat, mat);
+               quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, tmp_quat);
+       }
+       else if (pchan->rotmode == ROT_MODE_QUAT) {
+               mat4_to_quat(pchan->quat, mat);
+       }
+       else {
+               mat4_to_eulO(pchan->eul, pchan->rotmode, mat);
+       }
+}
+
 /* Remove rest-position effects from pose-transform for obtaining
- * 'visual' transformation of pose-channel. 
+ * 'visual' transformation of pose-channel.
  * (used by the Visual-Keyframing stuff)
  */
 void armature_mat_pose_to_delta(float delta_mat[][4], float pose_mat[][4], float arm_mat[][4])
@@ -1475,7 +1503,8 @@ void where_is_armature (bArmature *arm)
        }
 }
 
-/* if bone layer is protected, copy the data from from->pose */
+/* if bone layer is protected, copy the data from from->pose
+ * when used with linked libraries this copies from the linked pose into the local pose */
 static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected)
 {
        bPose *pose= ob->pose, *frompose= from->pose;
@@ -1516,9 +1545,10 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
        pose->active_group= frompose->active_group;
        
        for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
+               pchanp= get_pose_channel(frompose, pchan->name);
+
                if (pchan->bone->layer & layer_protected) {
                        ListBase proxylocal_constraints = {NULL, NULL};
-                       pchanp= get_pose_channel(frompose, pchan->name);
                        
                        /* copy posechannel to temp, but restore important pointers */
                        pchanw= *pchanp;
@@ -1529,9 +1559,15 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
                        pchanw.path= NULL;
                        
                        /* this is freed so copy a copy, else undo crashes */
-                       if(pchanw.prop)
+                       if(pchanw.prop) {
                                pchanw.prop= IDP_CopyProperty(pchanw.prop);
 
+                               /* use the values from the the existing props */
+                               if(pchan->prop) {
+                                       IDP_SyncGroupValues(pchanw.prop, pchan->prop);
+                               }
+                       }
+
                        /* constraints - proxy constraints are flushed... local ones are added after 
                         *      1. extract constraints not from proxy (CONSTRAINT_PROXY_LOCAL) from pchan's constraints
                         *      2. copy proxy-pchan's constraints on-to new
@@ -1566,6 +1602,30 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected
                        /* the final copy */
                        *pchan= pchanw;
                }
+               else {
+                       /* always copy custom shape */
+                       pchan->custom= pchanp->custom;
+                       pchan->custom_tx= pchanp->custom_tx;
+
+                       /* ID-Property Syncing */
+                       {
+                               IDProperty *prop_orig= pchan->prop;
+                               if(pchanp->prop) {
+                                       pchan->prop= IDP_CopyProperty(pchanp->prop);
+                                       if(prop_orig) {
+                                               /* copy existing values across when types match */
+                                               IDP_SyncGroupValues(pchan->prop, prop_orig);
+                                       }
+                               }
+                               else {
+                                       pchan->prop= NULL;
+                               }
+                               if (prop_orig) {
+                                       IDP_FreeProperty(prop_orig);
+                                       MEM_freeN(prop_orig);
+                               }
+                       }
+               }
        }
 }
 
@@ -1598,7 +1658,13 @@ void armature_rebuild_pose(Object *ob, bArmature *arm)
        int counter=0;
                
        /* only done here */
-       if(ob->pose==NULL) ob->pose= MEM_callocN(sizeof(bPose), "new pose");
+       if(ob->pose==NULL) {
+               /* create new pose */
+               ob->pose= MEM_callocN(sizeof(bPose), "new pose");
+               
+               /* set default settings for animviz */
+               animviz_settings_init(&ob->pose->avs);
+       }
        pose= ob->pose;
        
        /* clear */
@@ -1623,8 +1689,10 @@ void armature_rebuild_pose(Object *ob, bArmature *arm)
        // printf("rebuild pose %s, %d bones\n", ob->id.name, counter);
        
        /* synchronize protected layers with proxy */
-       if(ob->proxy)
+       if(ob->proxy) {
+               object_copy_proxy_drivers(ob, ob->proxy);
                pose_proxy_synchronize(ob, ob->proxy, arm->layer_protected);
+       }
        
        update_pose_constraint_flags(ob->pose); // for IK detection for example
        
@@ -1857,7 +1925,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
        float splineVec[3], scaleFac, radius=1.0f;
        
        /* firstly, calculate the bone matrix the standard way, since this is needed for roll control */
-       where_is_pose_bone(scene, ob, pchan, ctime);
+       where_is_pose_bone(scene, ob, pchan, ctime, 1);
        
        VECCOPY(poseHead, pchan->pose_head);
        VECCOPY(poseTail, pchan->pose_tail);
@@ -1880,6 +1948,12 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
                
                /* tail endpoint */
                if ( where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad) ) {
+                       /* apply curve's object-mode transforms to the position 
+                        * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root)
+                        */
+                       if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0)
+                               mul_m4_v3(ikData->tar->obmat, vec);
+                       
                        /* convert the position to pose-space, then store it */
                        mul_m4_v3(ob->imat, vec);
                        interp_v3_v3v3(poseTail, pchan->pose_tail, vec, tailBlendFac);
@@ -1890,6 +1964,12 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
                
                /* head endpoint */
                if ( where_on_path(ikData->tar, tree->points[index+1], vec, dir, NULL, &rad) ) {
+                       /* apply curve's object-mode transforms to the position 
+                        * unless the option to allow curve to be positioned elsewhere is activated (i.e. no root)
+                        */
+                       if ((ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) == 0)
+                               mul_m4_v3(ikData->tar->obmat, vec);
+                       
                        /* store the position, and convert it to pose space */
                        mul_m4_v3(ob->imat, vec);
                        VECCOPY(poseHead, vec);
@@ -2004,11 +2084,9 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
         *        the shape but be moved elsewhere
         */
        if (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) {
-               VECCOPY(poseMat[3], pchan->pose_head);
-       }
-       else {
-               VECCOPY(poseMat[3], poseHead);
+               VECCOPY(poseHead, pchan->pose_head);
        }
+       VECCOPY(poseMat[3], poseHead);
        
        /* finally, store the new transform */
        copy_m4_m4(pchan->pose_mat, poseMat);
@@ -2053,44 +2131,59 @@ static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_
 
 /* ********************** THE POSE SOLVER ******************* */
 
-
-/* loc/rot/size to mat4 */
-/* used in constraint.c too */
-void chan_calc_mat(bPoseChannel *chan)
+/* loc/rot/size to given mat4 */
+void pchan_to_mat4(bPoseChannel *pchan, float chan_mat[4][4])
 {
        float smat[3][3];
        float rmat[3][3];
        float tmat[3][3];
        
        /* get scaling matrix */
-       size_to_mat3( smat,chan->size);
+       size_to_mat3(smat, pchan->size);
        
        /* rotations may either be quats, eulers (with various rotation orders), or axis-angle */
-       if (chan->rotmode > 0) {
+       if (pchan->rotmode > 0) {
                /* euler rotations (will cause gimble lock, but this can be alleviated a bit with rotation orders) */
-               eulO_to_mat3( rmat,chan->eul, chan->rotmode);
+               eulO_to_mat3(rmat, pchan->eul, pchan->rotmode);
        }
-       else if (chan->rotmode == ROT_MODE_AXISANGLE) {
+       else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
                /* axis-angle - not really that great for 3D-changing orientations */
-               axis_angle_to_mat3( rmat,chan->rotAxis, chan->rotAngle);
+               axis_angle_to_mat3(rmat, pchan->rotAxis, pchan->rotAngle);
        }
        else {
                /* quats are normalised before use to eliminate scaling issues */
-               normalize_qt(chan->quat); // TODO: do this with local vars only!
-               quat_to_mat3( rmat,chan->quat);
+               float quat[4];
+               
+               /* NOTE: we now don't normalise the stored values anymore, since this was kindof evil in some cases
+                * but if this proves to be too problematic, switch back to the old system of operating directly on 
+                * the stored copy
+                */
+               QUATCOPY(quat, pchan->quat);
+               normalize_qt(quat);
+               quat_to_mat3(rmat, quat);
        }
        
        /* calculate matrix of bone (as 3x3 matrix, but then copy the 4x4) */
        mul_m3_m3m3(tmat, rmat, smat);
-       copy_m4_m3(chan->chan_mat, tmat);
+       copy_m4_m3(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)) {
-               VECCOPY(chan->chan_mat[3], chan->loc);
+       if ((pchan->bone==NULL) || !(pchan->bone->flag & BONE_CONNECTED)) {
+               VECCOPY(chan_mat[3], pchan->loc);
        }
 }
 
+/* loc/rot/size to mat4 */
+/* used in constraint.c too */
+void chan_calc_mat(bPoseChannel *pchan)
+{
+       /* this is just a wrapper around the copy of this function which calculates the matrix 
+        * and stores the result in any given channel
+        */
+       pchan_to_mat4(pchan, pchan->chan_mat);
+}
+
 /* NLA strip modifiers */
 static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseChannel *pchan)
 {
@@ -2215,8 +2308,10 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha
 
 
 /* The main armature solver, does all constraints excluding IK */
-/* pchan is validated, as having bone and parent pointer */
-void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime)
+/* pchan is validated, as having bone and parent pointer
+ * 'do_extra': when zero skips loc/size/rot, constraints and strip modifiers.
+ */
+void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime, int do_extra)
 {
        Bone *bone, *parbone;
        bPoseChannel *parchan;
@@ -2228,8 +2323,9 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti
        parchan= pchan->parent;
        
        /* this gives a chan_mat with actions (ipos) results */
-       chan_calc_mat(pchan);
-       
+       if(do_extra)    chan_calc_mat(pchan);
+       else                    unit_m4(pchan->chan_mat);
+
        /* construct the posemat based on PoseChannels, that we do before applying constraints */
        /* pose_mat(b)= pose_mat(b-1) * yoffs(b-1) * d_root(b) * bone_mat(b) * chan_mat(b) */
        
@@ -2294,32 +2390,34 @@ void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cti
                        add_v3_v3v3(pchan->pose_mat[3], pchan->pose_mat[3], ob->pose->cyclic_offset);
        }
        
-       /* do NLA strip modifiers - i.e. curve follow */
-       do_strip_modifiers(scene, ob, bone, pchan);
-       
-       /* Do constraints */
-       if (pchan->constraints.first) {
-               bConstraintOb *cob;
-               
-               /* make a copy of location of PoseChannel for later */
-               VECCOPY(vec, pchan->pose_mat[3]);
-               
-               /* prepare PoseChannel for Constraint solving 
-                * - makes a copy of matrix, and creates temporary struct to use 
-                */
-               cob= constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE);
-               
-               /* Solve PoseChannel's Constraints */
-               solve_constraints(&pchan->constraints, cob, ctime);     // ctime doesnt alter objects
-               
-               /* cleanup after Constraint Solving 
-                * - applies matrix back to pchan, and frees temporary struct used
-                */
-               constraints_clear_evalob(cob);
+       if(do_extra) {
+               /* do NLA strip modifiers - i.e. curve follow */
+               do_strip_modifiers(scene, ob, bone, pchan);
                
-               /* prevent constraints breaking a chain */
-               if(pchan->bone->flag & BONE_CONNECTED) {
-                       VECCOPY(pchan->pose_mat[3], vec);
+               /* Do constraints */
+               if (pchan->constraints.first) {
+                       bConstraintOb *cob;
+
+                       /* make a copy of location of PoseChannel for later */
+                       VECCOPY(vec, pchan->pose_mat[3]);
+
+                       /* prepare PoseChannel for Constraint solving
+                        * - makes a copy of matrix, and creates temporary struct to use
+                        */
+                       cob= constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE);
+
+                       /* Solve PoseChannel's Constraints */
+                       solve_constraints(&pchan->constraints, cob, ctime);     // ctime doesnt alter objects
+
+                       /* cleanup after Constraint Solving
+                        * - applies matrix back to pchan, and frees temporary struct used
+                        */
+                       constraints_clear_evalob(cob);
+
+                       /* prevent constraints breaking a chain */
+                       if(pchan->bone->flag & BONE_CONNECTED) {
+                               VECCOPY(pchan->pose_mat[3], vec);
+                       }
                }
        }
        
@@ -2391,7 +2489,7 @@ void where_is_pose (Scene *scene, Object *ob)
                        }
                        /* 5. otherwise just call the normal solver */
                        else if(!(pchan->flag & POSE_DONE)) {
-                               where_is_pose_bone(scene, ob, pchan, ctime);
+                               where_is_pose_bone(scene, ob, pchan, ctime, 1);
                        }
                }
                /* 6. release the IK tree */