Merge of itasc branch. Project files, scons and cmake should be working. Makefile...
[blender.git] / source / blender / blenkernel / intern / armature.c
index 1b930a7..b236845 100644 (file)
 #include "BKE_object.h"
 #include "BKE_object.h"
 #include "BKE_utildefines.h"
-
-//XXX #include "BIF_editdeform.h"
-
-#include "IK_solver.h"
+#include "BIK_api.h"
+#include "BKE_sketch.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -83,6 +81,7 @@ bArmature *add_armature(char *name)
        
        arm= alloc_libblock (&G.main->armature, ID_AR, name);
        arm->deformflag = ARM_DEF_VGROUP|ARM_DEF_ENVELOPE;
+       arm->flag = ARM_COL_CUSTOM; /* custom bone-group colors */
        arm->layer= 1;
        return arm;
 }
@@ -130,7 +129,6 @@ void free_bones (bArmature *arm)
 void free_armature(bArmature *arm)
 {
        if (arm) {
-               /*              unlink_armature(arm);*/
                free_bones(arm);
                
                /* free editmode data */
@@ -140,6 +138,12 @@ void free_armature(bArmature *arm)
                        MEM_freeN(arm->edbo);
                        arm->edbo= NULL;
                }
+
+               /* free sketch */
+               if (arm->sketch) {
+                       freeSketch(arm->sketch);
+                       arm->sketch = NULL;
+               }
        }
 }
 
@@ -661,10 +665,10 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest)
        if(bone->segments > MAX_BBONE_SUBDIV)
                bone->segments= MAX_BBONE_SUBDIV;
        
-       forward_diff_bezier(0.0, h1[0],         h2[0],                  0.0,            data[0],        MAX_BBONE_SUBDIV, 4);
-       forward_diff_bezier(0.0, h1[1],         length + h2[1], length,         data[0]+1,      MAX_BBONE_SUBDIV, 4);
-       forward_diff_bezier(0.0, h1[2],         h2[2],                  0.0,            data[0]+2,      MAX_BBONE_SUBDIV, 4);
-       forward_diff_bezier(roll1, roll1 + 0.390464f*(roll2-roll1), roll2 - 0.390464f*(roll2-roll1),    roll2,  data[0]+3,      MAX_BBONE_SUBDIV, 4);
+       forward_diff_bezier(0.0, h1[0],         h2[0],                  0.0,            data[0],        MAX_BBONE_SUBDIV, 4*sizeof(float));
+       forward_diff_bezier(0.0, h1[1],         length + h2[1], length,         data[0]+1,      MAX_BBONE_SUBDIV, 4*sizeof(float));
+       forward_diff_bezier(0.0, h1[2],         h2[2],                  0.0,            data[0]+2,      MAX_BBONE_SUBDIV, 4*sizeof(float));
+       forward_diff_bezier(roll1, roll1 + 0.390464f*(roll2-roll1), roll2 - 0.390464f*(roll2-roll1),    roll2,  data[0]+3,      MAX_BBONE_SUBDIV, 4*sizeof(float));
        
        equalize_bezier(data[0], bone->segments);       // note: does stride 4!
        
@@ -1564,409 +1568,10 @@ void armature_rebuild_pose(Object *ob, bArmature *arm)
                DAG_pose_sort(ob);
        
        ob->pose->flag &= ~POSE_RECALC;
+       ob->pose->flag |= POSE_WAS_REBUILT;
 }
 
 
-/* ********************** THE IK SOLVER ******************* */
-
-
-
-/* allocates PoseTree, and links that to root bone/channel */
-/* Note: detecting the IK chain is duplicate code... in drawarmature.c and in transform_conversions.c */
-static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip)
-{
-       bPoseChannel *curchan, *pchan_root=NULL, *chanlist[256], **oldchan;
-       PoseTree *tree;
-       PoseTarget *target;
-       bConstraint *con;
-       bKinematicConstraint *data= NULL;
-       int a, segcount= 0, size, newsize, *oldparent, parent;
-       
-       /* find IK constraint, and validate it */
-       for(con= pchan_tip->constraints.first; con; con= con->next) {
-               if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
-                       data=(bKinematicConstraint*)con->data;
-                       if (data->flag & CONSTRAINT_IK_AUTO) break;
-                       if (data->tar==NULL) continue;
-                       if (data->tar->type==OB_ARMATURE && data->subtarget[0]==0) continue;
-                       if ((con->flag & CONSTRAINT_DISABLE)==0 && (con->enforce!=0.0)) break;
-               }
-       }
-       if(con==NULL) return;
-       
-       /* exclude tip from chain? */
-       if(!(data->flag & CONSTRAINT_IK_TIP))
-               pchan_tip= pchan_tip->parent;
-       
-       /* Find the chain's root & count the segments needed */
-       for (curchan = pchan_tip; curchan; curchan=curchan->parent){
-               pchan_root = curchan;
-               
-               curchan->flag |= POSE_CHAIN;    // don't forget to clear this
-               chanlist[segcount]=curchan;
-               segcount++;
-               
-               if(segcount==data->rootbone || segcount>255) break; // 255 is weak
-       }
-       if (!segcount) return;
-
-       /* setup the chain data */
-       
-       /* we make tree-IK, unless all existing targets are in this chain */
-       for(tree= pchan_root->iktree.first; tree; tree= tree->next) {
-               for(target= tree->targets.first; target; target= target->next) {
-                       curchan= tree->pchan[target->tip];
-                       if(curchan->flag & POSE_CHAIN)
-                               curchan->flag &= ~POSE_CHAIN;
-                       else
-                               break;
-               }
-               if(target) break;
-       }
-
-       /* create a target */
-       target= MEM_callocN(sizeof(PoseTarget), "posetarget");
-       target->con= con;
-       pchan_tip->flag &= ~POSE_CHAIN;
-
-       if(tree==NULL) {
-               /* make new tree */
-               tree= MEM_callocN(sizeof(PoseTree), "posetree");
-
-               tree->iterations= data->iterations;
-               tree->totchannel= segcount;
-               tree->stretch = (data->flag & CONSTRAINT_IK_STRETCH);
-               
-               tree->pchan= MEM_callocN(segcount*sizeof(void*), "ik tree pchan");
-               tree->parent= MEM_callocN(segcount*sizeof(int), "ik tree parent");
-               for(a=0; a<segcount; a++) {
-                       tree->pchan[a]= chanlist[segcount-a-1];
-                       tree->parent[a]= a-1;
-               }
-               target->tip= segcount-1;
-               
-               /* AND! link the tree to the root */
-               BLI_addtail(&pchan_root->iktree, tree);
-       }
-       else {
-               tree->iterations= MAX2(data->iterations, tree->iterations);
-               tree->stretch= tree->stretch && !(data->flag & CONSTRAINT_IK_STRETCH);
-
-               /* skip common pose channels and add remaining*/
-               size= MIN2(segcount, tree->totchannel);
-               for(a=0; a<size && tree->pchan[a]==chanlist[segcount-a-1]; a++);
-               parent= a-1;
-
-               segcount= segcount-a;
-               target->tip= tree->totchannel + segcount - 1;
-
-               if (segcount > 0) {
-                       /* resize array */
-                       newsize= tree->totchannel + segcount;
-                       oldchan= tree->pchan;
-                       oldparent= tree->parent;
-
-                       tree->pchan= MEM_callocN(newsize*sizeof(void*), "ik tree pchan");
-                       tree->parent= MEM_callocN(newsize*sizeof(int), "ik tree parent");
-                       memcpy(tree->pchan, oldchan, sizeof(void*)*tree->totchannel);
-                       memcpy(tree->parent, oldparent, sizeof(int)*tree->totchannel);
-                       MEM_freeN(oldchan);
-                       MEM_freeN(oldparent);
-
-                       /* add new pose channels at the end, in reverse order */
-                       for(a=0; a<segcount; a++) {
-                               tree->pchan[tree->totchannel+a]= chanlist[segcount-a-1];
-                               tree->parent[tree->totchannel+a]= tree->totchannel+a-1;
-                       }
-                       tree->parent[tree->totchannel]= parent;
-                       
-                       tree->totchannel= newsize;
-               }
-
-               /* move tree to end of list, for correct evaluation order */
-               BLI_remlink(&pchan_root->iktree, tree);
-               BLI_addtail(&pchan_root->iktree, tree);
-       }
-
-       /* add target to the tree */
-       BLI_addtail(&tree->targets, target);
-}
-
-/* called from within the core where_is_pose loop, all animsystems and constraints
-were executed & assigned. Now as last we do an IK pass */
-static void execute_posetree(Object *ob, PoseTree *tree)
-{
-       float R_parmat[3][3], identity[3][3];
-       float iR_parmat[3][3];
-       float R_bonemat[3][3];
-       float goalrot[3][3], goalpos[3];
-       float rootmat[4][4], imat[4][4];
-       float goal[4][4], goalinv[4][4];
-       float irest_basis[3][3], full_basis[3][3];
-       float end_pose[4][4], world_pose[4][4];
-       float length, basis[3][3], rest_basis[3][3], start[3], *ikstretch=NULL;
-       float resultinf=0.0f;
-       int a, flag, hasstretch=0, resultblend=0;
-       bPoseChannel *pchan;
-       IK_Segment *seg, *parent, **iktree, *iktarget;
-       IK_Solver *solver;
-       PoseTarget *target;
-       bKinematicConstraint *data, *poleangledata=NULL;
-       Bone *bone;
-
-       if (tree->totchannel == 0)
-               return;
-       
-       iktree= MEM_mallocN(sizeof(void*)*tree->totchannel, "ik tree");
-
-       for(a=0; a<tree->totchannel; a++) {
-               pchan= tree->pchan[a];
-               bone= pchan->bone;
-               
-               /* set DoF flag */
-               flag= 0;
-               if(!(pchan->ikflag & BONE_IK_NO_XDOF) && !(pchan->ikflag & BONE_IK_NO_XDOF_TEMP))
-                       flag |= IK_XDOF;
-               if(!(pchan->ikflag & BONE_IK_NO_YDOF) && !(pchan->ikflag & BONE_IK_NO_YDOF_TEMP))
-                       flag |= IK_YDOF;
-               if(!(pchan->ikflag & BONE_IK_NO_ZDOF) && !(pchan->ikflag & BONE_IK_NO_ZDOF_TEMP))
-                       flag |= IK_ZDOF;
-               
-               if(tree->stretch && (pchan->ikstretch > 0.0)) {
-                       flag |= IK_TRANS_YDOF;
-                       hasstretch = 1;
-               }
-               
-               seg= iktree[a]= IK_CreateSegment(flag);
-               
-               /* find parent */
-               if(a == 0)
-                       parent= NULL;
-               else
-                       parent= iktree[tree->parent[a]];
-                       
-               IK_SetParent(seg, parent);
-                       
-               /* get the matrix that transforms from prevbone into this bone */
-               Mat3CpyMat4(R_bonemat, pchan->pose_mat);
-               
-               /* gather transformations for this IK segment */
-               
-               if (pchan->parent)
-                       Mat3CpyMat4(R_parmat, pchan->parent->pose_mat);
-               else
-                       Mat3One(R_parmat);
-               
-               /* bone offset */
-               if (pchan->parent && (a > 0))
-                       VecSubf(start, pchan->pose_head, pchan->parent->pose_tail);
-               else
-                       /* only root bone (a = 0) has no parent */
-                       start[0]= start[1]= start[2]= 0.0f;
-               
-               /* change length based on bone size */
-               length= bone->length*VecLength(R_bonemat[1]);
-               
-               /* compute rest basis and its inverse */
-               Mat3CpyMat3(rest_basis, bone->bone_mat);
-               Mat3CpyMat3(irest_basis, bone->bone_mat);
-               Mat3Transp(irest_basis);
-               
-               /* compute basis with rest_basis removed */
-               Mat3Inv(iR_parmat, R_parmat);
-               Mat3MulMat3(full_basis, iR_parmat, R_bonemat);
-               Mat3MulMat3(basis, irest_basis, full_basis);
-               
-               /* basis must be pure rotation */
-               Mat3Ortho(basis);
-               
-               /* transform offset into local bone space */
-               Mat3Ortho(iR_parmat);
-               Mat3MulVecfl(iR_parmat, start);
-               
-               IK_SetTransform(seg, start, rest_basis, basis, length);
-               
-               if (pchan->ikflag & BONE_IK_XLIMIT)
-                       IK_SetLimit(seg, IK_X, pchan->limitmin[0], pchan->limitmax[0]);
-               if (pchan->ikflag & BONE_IK_YLIMIT)
-                       IK_SetLimit(seg, IK_Y, pchan->limitmin[1], pchan->limitmax[1]);
-               if (pchan->ikflag & BONE_IK_ZLIMIT)
-                       IK_SetLimit(seg, IK_Z, pchan->limitmin[2], pchan->limitmax[2]);
-               
-               IK_SetStiffness(seg, IK_X, pchan->stiffness[0]);
-               IK_SetStiffness(seg, IK_Y, pchan->stiffness[1]);
-               IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]);
-               
-               if(tree->stretch && (pchan->ikstretch > 0.0f)) {
-                       float ikstretch = pchan->ikstretch*pchan->ikstretch;
-                       IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0f-ikstretch, 0.99f));
-                       IK_SetLimit(seg, IK_TRANS_Y, 0.001f, 1e10);
-               }
-       }
-
-       solver= IK_CreateSolver(iktree[0]);
-
-       /* set solver goals */
-
-       /* first set the goal inverse transform, assuming the root of tree was done ok! */
-       pchan= tree->pchan[0];
-       if (pchan->parent)
-               /* transform goal by parent mat, so this rotation is not part of the
-                  segment's basis. otherwise rotation limits do not work on the
-                  local transform of the segment itself. */
-               Mat4CpyMat4(rootmat, pchan->parent->pose_mat);
-       else
-               Mat4One(rootmat);
-       VECCOPY(rootmat[3], pchan->pose_head);
-       
-       Mat4MulMat4 (imat, rootmat, ob->obmat);
-       Mat4Invert (goalinv, imat);
-       
-       for (target=tree->targets.first; target; target=target->next) {
-               float polepos[3];
-               int poleconstrain= 0;
-               
-               data= (bKinematicConstraint*)target->con->data;
-               
-               /* 1.0=ctime, we pass on object for auto-ik (owner-type here is object, even though
-                * strictly speaking, it is a posechannel)
-                */
-               get_constraint_target_matrix(target->con, 0, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
-               
-               /* and set and transform goal */
-               Mat4MulMat4(goal, rootmat, goalinv);
-               
-               VECCOPY(goalpos, goal[3]);
-               Mat3CpyMat4(goalrot, goal);
-               
-               /* same for pole vector target */
-               if(data->poletar) {
-                       get_constraint_target_matrix(target->con, 1, CONSTRAINT_OBTYPE_OBJECT, ob, rootmat, 1.0);
-                       
-                       if(data->flag & CONSTRAINT_IK_SETANGLE) {
-                               /* don't solve IK when we are setting the pole angle */
-                               break;
-                       }
-                       else {
-                               Mat4MulMat4(goal, rootmat, goalinv);
-                               VECCOPY(polepos, goal[3]);
-                               poleconstrain= 1;
-
-                               /* for pole targets, we blend the result of the ik solver
-                                * instead of the target position, otherwise we can't get
-                                * a smooth transition */
-                               resultblend= 1;
-                               resultinf= target->con->enforce;
-                               
-                               if(data->flag & CONSTRAINT_IK_GETANGLE) {
-                                       poleangledata= data;
-                                       data->flag &= ~CONSTRAINT_IK_GETANGLE;
-                               }
-                       }
-               }
-
-               /* do we need blending? */
-               if (!resultblend && target->con->enforce!=1.0f) {
-                       float q1[4], q2[4], q[4];
-                       float fac= target->con->enforce;
-                       float mfac= 1.0f-fac;
-                       
-                       pchan= tree->pchan[target->tip];
-                       
-                       /* end effector in world space */
-                       Mat4CpyMat4(end_pose, pchan->pose_mat);
-                       VECCOPY(end_pose[3], pchan->pose_tail);
-                       Mat4MulSerie(world_pose, goalinv, ob->obmat, end_pose, 0, 0, 0, 0, 0);
-                       
-                       /* blend position */
-                       goalpos[0]= fac*goalpos[0] + mfac*world_pose[3][0];
-                       goalpos[1]= fac*goalpos[1] + mfac*world_pose[3][1];
-                       goalpos[2]= fac*goalpos[2] + mfac*world_pose[3][2];
-                       
-                       /* blend rotation */
-                       Mat3ToQuat(goalrot, q1);
-                       Mat4ToQuat(world_pose, q2);
-                       QuatInterpol(q, q1, q2, mfac);
-                       QuatToMat3(q, goalrot);
-               }
-               
-               iktarget= iktree[target->tip];
-               
-               if(data->weight != 0.0f) {
-                       if(poleconstrain)
-                               IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos,
-                                       polepos, data->poleangle*(float)M_PI/180.0f, (poleangledata == data));
-                       IK_SolverAddGoal(solver, iktarget, goalpos, data->weight);
-               }
-               if((data->flag & CONSTRAINT_IK_ROT) && (data->orientweight != 0.0f))
-                       if((data->flag & CONSTRAINT_IK_AUTO)==0)
-                               IK_SolverAddGoalOrientation(solver, iktarget, goalrot,
-                                       data->orientweight);
-       }
-
-       /* solve */
-       IK_Solve(solver, 0.0f, tree->iterations);
-
-       if(poleangledata)
-               poleangledata->poleangle= IK_SolverGetPoleAngle(solver)*180.0f/(float)M_PI;
-
-       IK_FreeSolver(solver);
-
-       /* gather basis changes */
-       tree->basis_change= MEM_mallocN(sizeof(float[3][3])*tree->totchannel, "ik basis change");
-       if(hasstretch)
-               ikstretch= MEM_mallocN(sizeof(float)*tree->totchannel, "ik stretch");
-       
-       for(a=0; a<tree->totchannel; a++) {
-               IK_GetBasisChange(iktree[a], tree->basis_change[a]);
-               
-               if(hasstretch) {
-                       /* have to compensate for scaling received from parent */
-                       float parentstretch, stretch;
-                       
-                       pchan= tree->pchan[a];
-                       parentstretch= (tree->parent[a] >= 0)? ikstretch[tree->parent[a]]: 1.0f;
-                       
-                       if(tree->stretch && (pchan->ikstretch > 0.0f)) {
-                               float trans[3], length;
-                               
-                               IK_GetTranslationChange(iktree[a], trans);
-                               length= pchan->bone->length*VecLength(pchan->pose_mat[1]);
-                               
-                               ikstretch[a]= (length == 0.0f)? 1.0f: (trans[1]+length)/length;
-                       }
-                       else
-                               ikstretch[a] = 1.0f;
-                       
-                       stretch= (parentstretch == 0.0f)? 1.0f: ikstretch[a]/parentstretch;
-                       
-                       VecMulf(tree->basis_change[a][0], stretch);
-                       VecMulf(tree->basis_change[a][1], stretch);
-                       VecMulf(tree->basis_change[a][2], stretch);
-               }
-
-               if(resultblend && resultinf!=1.0f) {
-                       Mat3One(identity);
-                       Mat3BlendMat3(tree->basis_change[a], identity,
-                               tree->basis_change[a], resultinf);
-               }
-               
-               IK_FreeSegment(iktree[a]);
-       }
-       
-       MEM_freeN(iktree);
-       if(ikstretch) MEM_freeN(ikstretch);
-}
-
-void free_posetree(PoseTree *tree)
-{
-       BLI_freelistN(&tree->targets);
-       if(tree->pchan) MEM_freeN(tree->pchan);
-       if(tree->parent) MEM_freeN(tree->parent);
-       if(tree->basis_change) MEM_freeN(tree->basis_change);
-       MEM_freeN(tree);
-}
-
 /* ********************** THE POSE SOLVER ******************* */
 
 
@@ -1981,10 +1586,14 @@ void chan_calc_mat(bPoseChannel *chan)
        /* get scaling matrix */
        SizeToMat3(chan->size, smat);
        
-       /* 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);
+       /* rotations may either be quats, eulers (with various rotation orders), or axis-angle */
+       if (chan->rotmode > 0) {
+               /* euler rotations (will cause gimble lock, but this can be alleviated a bit with rotation orders) */
+               EulOToMat3(chan->eul, chan->rotmode, rmat);
+       }
+       else if (chan->rotmode == PCHAN_ROT_AXISANGLE) {
+               /* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */
+               AxisAngleToMat3(&chan->quat[1], chan->quat[0], rmat);
        }
        else {
                /* quats are normalised before use to eliminate scaling issues */
@@ -2003,41 +1612,6 @@ void chan_calc_mat(bPoseChannel *chan)
        }
 }
 
-/* transform from bone(b) to bone(b+1), store in chan_mat */
-static void make_dmats(bPoseChannel *pchan)
-{
-       if (pchan->parent) {
-               float iR_parmat[4][4];
-               Mat4Invert(iR_parmat, pchan->parent->pose_mat);
-               Mat4MulMat4(pchan->chan_mat,  pchan->pose_mat, iR_parmat);      // delta mat
-       }
-       else Mat4CpyMat4(pchan->chan_mat, pchan->pose_mat);
-}
-
-/* applies IK matrix to pchan, IK is done separated */
-/* formula: pose_mat(b) = pose_mat(b-1) * diffmat(b-1, b) * ik_mat(b) */
-/* to make this work, the diffmats have to be precalculated! Stored in chan_mat */
-static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3])   // nr = to detect if this is first bone
-{
-       float vec[3], ikmat[4][4];
-       
-       Mat4CpyMat3(ikmat, ik_mat);
-       
-       if (pchan->parent)
-               Mat4MulSerie(pchan->pose_mat, pchan->parent->pose_mat, pchan->chan_mat, ikmat, NULL, NULL, NULL, NULL, NULL);
-       else 
-               Mat4MulMat4(pchan->pose_mat, ikmat, pchan->chan_mat);
-
-       /* calculate head */
-       VECCOPY(pchan->pose_head, pchan->pose_mat[3]);
-       /* calculate tail */
-       VECCOPY(vec, pchan->pose_mat[1]);
-       VecMulf(vec, pchan->bone->length);
-       VecAddf(pchan->pose_tail, pchan->pose_head, vec);
-
-       pchan->flag |= POSE_DONE;
-}
-
 /* NLA strip modifiers */
 static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseChannel *pchan)
 {
@@ -2163,7 +1737,7 @@ 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 */
-static void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime)
+void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime)
 {
        Bone *bone, *parbone;
        bPoseChannel *parchan;
@@ -2207,7 +1781,7 @@ static void where_is_pose_bone(Scene *scene, Object *ob, bPoseChannel *pchan, fl
                        Mat4MulSerie(pchan->pose_mat, tmat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL);
                }
                else if(bone->flag & BONE_NO_SCALE) {
-                       float orthmat[4][4], vec[3];
+                       float orthmat[4][4];
                        
                        /* get the official transform, but we only use the vector from it (optimize...) */
                        Mat4MulSerie(pchan->pose_mat, parchan->pose_mat, offs_bone, pchan->chan_mat, NULL, NULL, NULL, NULL, NULL);
@@ -2303,48 +1877,27 @@ void where_is_pose (Scene *scene, Object *ob)
        else {
                Mat4Invert(ob->imat, ob->obmat);        // imat is needed 
 
-               /* 1. construct the PoseTrees, clear flags */
+               /* 1. clear flags */
                for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
-                       pchan->flag &= ~(POSE_DONE|POSE_CHAIN);
-                       if(pchan->constflag & PCHAN_HAS_IK) // flag is set on editing constraints
-                               initialize_posetree(ob, pchan); // will attach it to root!
+                       pchan->flag &= ~(POSE_DONE|POSE_CHAIN|POSE_IKTREE);
                }
-               
-               /* 2. the main loop, channels are already hierarchical sorted from root to children */
+               /* 2. construct the IK tree */
+               BIK_initialize_tree(scene, ob, ctime);
+
+               /* 3. the main loop, channels are already hierarchical sorted from root to children */
                for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
                        
-                       /* 3. if we find an IK root, we handle it separated */
-                       if(pchan->iktree.first) {
-                               while(pchan->iktree.first) {
-                                       PoseTree *tree= pchan->iktree.first;
-                                       int a;
-                                       
-                                       /* 4. walk over the tree for regular solving */
-                                       for(a=0; a<tree->totchannel; a++) {
-                                               if(!(tree->pchan[a]->flag & POSE_DONE)) // successive trees can set the flag
-                                                       where_is_pose_bone(scene, ob, tree->pchan[a], ctime);
-                                       }
-                                       /* 5. execute the IK solver */
-                                       execute_posetree(ob, tree);
-                                       
-                                       /* 6. apply the differences to the channels, 
-                                                 we need to calculate the original differences first */
-                                       for(a=0; a<tree->totchannel; a++)
-                                               make_dmats(tree->pchan[a]);
-                                       
-                                       for(a=0; a<tree->totchannel; a++)
-                                               /* sets POSE_DONE */
-                                               where_is_ik_bone(tree->pchan[a], tree->basis_change[a]);
-                                       
-                                       /* 7. and free */
-                                       BLI_remlink(&pchan->iktree, tree);
-                                       free_posetree(tree);
-                               }
+                       /* 4. if we find an IK root, we handle it separated */
+                       if(pchan->flag & POSE_IKTREE) {
+                               BIK_execute_tree(scene, ob, pchan, ctime);
                        }
+                       /* 5. otherwise just call the normal solver */
                        else if(!(pchan->flag & POSE_DONE)) {
                                where_is_pose_bone(scene, ob, pchan, ctime);
                        }
                }
+               /* 6. release the IK tree */
+               BIK_release_tree(scene, ob, ctime);
        }
                
        /* calculating deform matrices */