Third and last commit for Brecht's IK work.
authorTon Roosendaal <ton@blender.org>
Sat, 27 Aug 2005 12:48:45 +0000 (12:48 +0000)
committerTon Roosendaal <ton@blender.org>
Sat, 27 Aug 2005 12:48:45 +0000 (12:48 +0000)
Full logs for changes will be added later. Worth to note now;
- support for 'tree IK' added
- DOF and stiffness per IK bone (in pose only)
- Orientation IK support (target rotates -> chain follows)

This is still WIP. Buttons might change, button ranges will change, and the
way 'IK groups' are working will change. You can play with this, but don't
expect saved files to work still by end of this day! :)

source/blender/blenkernel/BKE_armature.h
source/blender/blenkernel/bad_level_call_stubs/stubs.c
source/blender/blenkernel/intern/action.c
source/blender/blenkernel/intern/armature.c
source/blender/blenkernel/intern/constraint.c
source/blender/blenloader/intern/readfile.c
source/blender/makesdna/DNA_action_types.h
source/blender/makesdna/DNA_constraint_types.h
source/blender/src/buttons_editing.c
source/blender/src/buttons_object.c

index d177edf..84d87b2 100644 (file)
@@ -46,19 +46,23 @@ struct Mesh;
 struct PoseChain;
 struct ListBase;
 
+typedef struct PoseTarget
+{
+       struct PoseTarget *next, *prev;
+       struct bConstraint *con;
+       int tip;
+} PoseTarget;
+
 typedef struct PoseChain
 {
        struct PoseChain *next, *prev;  // hurms
        struct bPoseChannel     **pchanchain;
-       struct bConstraint *con;
-       struct Bone *root, *target;
-       struct bPose *pose;
-       int totchannel;
-       float   goal[3];
+       struct ListBase targets;
+       int             totchannel;
+       float   (*basis_change)[3][3];
+       char    group[32];
        float   tolerance;
        int             iterations;
-       float   goalinv[4][4];
-       struct IK_Chain_Extern *solver;
 } PoseChain;
 
 /*     Core armature functionality */
index 04371fb..aa5748c 100644 (file)
@@ -170,33 +170,24 @@ void BPY_do_all_scripts (short int event){}
 
 /* IKsolver stubs */
 #include "IK_solver.h"
-extern int IK_LoadChain(IK_Chain_ExternPtr chain,IK_Segment_ExternPtr segments, int num_segs)
-{
-       return 0;
-}
 
-extern int IK_SolveChain(
-       IK_Chain_ExternPtr chain,
-       float goal[3],
-       float tolerance,
-       int max_iterations,
-       float max_angle_change, 
-       IK_Segment_ExternPtr output
-       )
-{
-       return 0;
-}
+IK_Segment *IK_CreateSegment(int flag) { return 0; }
+void IK_FreeSegment(IK_Segment *seg) {}
 
-extern void IK_FreeChain(IK_Chain_ExternPtr chain)
-{
-       ;
-}
+void IK_SetParent(IK_Segment *seg, IK_Segment *parent) {}
+void IK_SetTransform(IK_Segment *seg, float start[3], float rest_basis[][3], float basis[][3], float length) {}
+void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3]) {}
+void IK_GetTranslationChange(IK_Segment *seg, float *translation_change) {};
+void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lower, float upper) {};
+void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness) {};
 
+IK_Solver *IK_CreateSolver(IK_Segment *root) { return 0; }
+void IK_FreeSolver(IK_Solver *solver) {};
 
-extern IK_Chain_ExternPtr IK_CreateChain(void)
-{
-       return 0;
-}
+void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float weight) {}
+void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[][3], float weight) {}
+void IK_SolverAddCenterOfMass(IK_Solver *solver, IK_Segment *root, float goal[3], float weight) {}
+int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations) { return 0; }
 
 /* exotic.c */
 int BPY_call_importloader(char *name)
index 5af1cc3..a3c7060 100644 (file)
@@ -207,6 +207,10 @@ bPoseChannel *verify_pose_channel(bPose* pose, const char* name)
        chan->size[0] = chan->size[1] = chan->size[2] = 1.0F;
        Mat3One(chan->ik_mat);
        
+       chan->limitmin[0]= chan->limitmin[1]= chan->limitmin[2]= -180.0f;
+       chan->limitmax[0]= chan->limitmax[1]= chan->limitmax[2]= 180.0f;
+       chan->stiffness[0]= chan->stiffness[1]= chan->stiffness[2]= 1.0f;
+       
        BLI_addtail (&pose->chanbase, chan);
        
        return chan;
index dabc4fc..0d516e1 100644 (file)
@@ -967,15 +967,17 @@ void armature_rebuild_pose(Object *ob, bArmature *arm)
 /* ********************** THE IK SOLVER ******************* */
 
 
+
 /* allocates PoseChain, and links that to root bone/channel */
 /* note; if we got this working, it can become static too? */
 static void initialize_posechain(struct Object *ob, bPoseChannel *pchan_tip)
 {
-       bPoseChannel *curchan, *pchan_root=NULL, *chanlist[256];
+       bPoseChannel *curchan, *pchan_root=NULL, *chanlist[256], **oldchan;
        PoseChain *chain;
+       PoseTarget *target;
        bConstraint *con;
        bKinematicConstraint *data;
-       int a, segcount= 0;
+       int a, segcount= 0, size, newsize;
        
        /* find IK constraint, and validate it */
        for(con= pchan_tip->constraints.first; con; con= con->next) {
@@ -1006,75 +1008,128 @@ static void initialize_posechain(struct Object *ob, bPoseChannel *pchan_tip)
                        break;
        }
        if (!segcount) return;
-       
+
        /* setup the chain data */
-       chain = MEM_callocN(sizeof(PoseChain), "posechain");
-       chain->totchannel= segcount;
-       chain->solver = IK_CreateChain();
-       chain->con= con;
-       
-       chain->iterations = data->iterations;
-       chain->tolerance = data->tolerance;
-       
-       chain->pchanchain= MEM_callocN(segcount*sizeof(void *), "channel chain");
-       for(a=0; a<segcount; a++) {
-               chain->pchanchain[a]= chanlist[segcount-a-1];
+       chain = NULL;
+
+       /* if part of group, look for existing chain */
+       if(strlen(data->group) > 0)
+               for(chain= pchan_root->chain.first; chain; chain= chain->next)
+                       if(strcmp(data->group, chain->group)==0) break;
+
+       /* create a target */
+       target= MEM_callocN(sizeof(PoseTarget), "posetarget");
+       target->con= con;
+
+       if(chain==NULL) {
+               /* make new chain */
+               chain= MEM_callocN(sizeof(PoseChain), "posechain");
+
+               strcpy(chain->group, data->group);
+               chain->tolerance= data->tolerance;
+               chain->iterations= data->iterations;
+               chain->totchannel= segcount;
+               
+               chain->pchanchain= MEM_callocN(segcount*sizeof(void *), "channel chain");
+               for(a=0; a<segcount; a++)
+                       chain->pchanchain[a]= chanlist[segcount-a-1];
+
+               target->tip= segcount-1;
+               
+               /* AND! link the chain to the root */
+               BLI_addtail(&pchan_root->chain, chain);
        }
-       
-       /* AND! link the chain to the root */
-       BLI_addtail(&pchan_root->chain, chain);
+       else {
+               chain->tolerance= MIN2(chain->tolerance, data->tolerance);
+               chain->iterations= MAX2(data->iterations, chain->iterations);
+
+               /* skip common pose channels and add remaining*/
+               size= MIN2(segcount, chain->totchannel);
+               for(a=0; a<size && chain->pchanchain[a]==chanlist[segcount-a-1]; a++);
+
+               segcount= segcount-a;
+
+               target->tip= chain->totchannel + segcount - 1;
+
+               if (segcount > 0) {
+                       /* resize array */
+                       newsize= chain->totchannel + segcount;
+                       oldchan= chain->pchanchain;
+
+                       chain->pchanchain= MEM_callocN(newsize*sizeof(void*), "channel chain");
+                       memcpy(chain->pchanchain, oldchan, sizeof(void*)*chain->totchannel);
+                       MEM_freeN(oldchan);
+
+                       /* add new pose channels at the end, in reverse order */
+                       for(a=0; a<segcount; a++)
+                               chain->pchanchain[chain->totchannel+a]= chanlist[segcount-a-1];
+
+                       chain->totchannel= newsize;
+               }
+
+               /* move chain to end of list, for correct evaluation order */
+               BLI_remlink(&pchan_root->chain, chain);
+               BLI_addtail(&pchan_root->chain, chain);
+       }
+
+       /* add target to the chain */
+       BLI_addtail(&chain->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_posechain(Object *ob, PoseChain *chain)
 {
-       IK_Segment_Extern       *segs;
-       bPoseChannel *pchan;
        float R_parmat[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 size[3];
-       int curseg;
-       
-       /* first set the goal inverse transform, assuming the root of chain was done ok! */
-       pchan= chain->pchanchain[0];
-       Mat4One(rootmat);
-       VECCOPY(rootmat[3], pchan->pose_head);
-       
-       Mat4MulMat4 (imat, rootmat, ob->obmat);
-       Mat4Invert (chain->goalinv, imat);
-       
-       /* and set and transform goal */
-       get_constraint_target_matrix(chain->con, TARGET_BONE, NULL, rootmat, size, 1.0);   // 1.0=ctime
-       VECCOPY (chain->goal, rootmat[3]);
-       /* do we need blending? */
-       if(chain->con->enforce!=1.0) {
-               float vec[3];
-               float fac= chain->con->enforce;
-               float mfac= 1.0-fac;
-               
-               pchan= chain->pchanchain[chain->totchannel-1];  // last bone
-               VECCOPY(vec, pchan->pose_tail);
-               Mat4MulVecfl(ob->obmat, vec);                                   // world space
-               chain->goal[0]= fac*chain->goal[0] + mfac*vec[0];
-               chain->goal[1]= fac*chain->goal[1] + mfac*vec[1];
-               chain->goal[2]= fac*chain->goal[2] + mfac*vec[2];
-       }
-       Mat4MulVecfl (chain->goalinv, chain->goal);
-       
-       /* Now we construct the IK segments */
-       segs = MEM_callocN (sizeof(IK_Segment_Extern)*chain->totchannel, "iksegments");
+       float goal[4][4], goalinv[4][4];
+       float size[3], bonesize[3], irest_basis[3][3], full_basis[3][3];
+       float length, basis[3][3], rest_basis[3][3], start[3];
+       int a, b, flag;
+       bPoseChannel *pchan;
+       IK_Segment *seg, *parent, **ikchain, *iktarget;
+       IK_Solver *solver;
+       PoseTarget *target;
+       bKinematicConstraint *data;
+       Bone *bone;
+
+       if (chain->totchannel == 0)
+               return;
+
+       ikchain= MEM_mallocN(sizeof(void*)*chain->totchannel, "ik chain");
+
+       for(a=0; a<chain->totchannel; a++) {
+               pchan= chain->pchanchain[a];
+               bone = pchan->bone;
+
+               /* set DoF flag */
+               flag= 0;
+               if((pchan->ikflag & BONE_IK_NO_XDOF) == 0)
+                       flag |= IK_XDOF;
+               if((pchan->ikflag & BONE_IK_NO_YDOF) == 0)
+                       flag |= IK_YDOF;
+               if((pchan->ikflag & BONE_IK_NO_ZDOF) == 0)
+                       flag |= IK_ZDOF;
+
+               seg= ikchain[a]= IK_CreateSegment(flag);
+
+               /* find parent */
+               if(a == 0)
+                       parent= NULL;
+               else {
+                       for(b=a-1; chain->pchanchain[b]!=pchan->parent; b--);
+                       parent= ikchain[b];
+               }
+
+               IK_SetParent(seg, parent);
        
-       for (curseg=0; curseg<chain->totchannel; curseg++){
-               
-               pchan= chain->pchanchain[curseg];
-               
-               /* Get the matrix that transforms from prevbone into this bone */
+               /* get the matrix that transforms from prevbone into this bone */
                Mat3CpyMat4(R_bonemat, pchan->pose_mat);
                
-               if (pchan->parent && (pchan->bone->flag & BONE_IK_TOPARENT)) {
+               if(pchan->parent && (bone->flag & BONE_IK_TOPARENT)) {
                        Mat3CpyMat4(R_parmat, pchan->parent->pose_mat);
                }
                else
@@ -1082,33 +1137,116 @@ static void execute_posechain(Object *ob, PoseChain *chain)
                
                Mat3Inv(iR_parmat, R_parmat);
                
-               /* Mult and Copy the matrix into the basis and transpose (IK lib likes it) */
-               Mat3MulMat3((void *)segs[curseg].basis, iR_parmat, R_bonemat);
-               Mat3Transp((void *)segs[curseg].basis);
-               
-               /* Fill out the IK segment */
-               segs[curseg].length = pchan->bone->length; 
+               /* gather transformations for this IK segment */
+               start[0]= start[1]= start[2]= 0.0;
+
+               /* change length based on bone size */
+               Mat3ToSize(R_bonemat, bonesize);
+               length= bone->length*bonesize[1];
+
+               Mat3CpyMat3(rest_basis, bone->bone_mat);
+
+               /* compute basis with rest_basis removed */
+               Mat3Inv(irest_basis, rest_basis);
+               Mat3MulMat3(full_basis, iR_parmat, R_bonemat);
+               Mat3MulMat3(basis, irest_basis, full_basis);
+
+               /* basis must be pure rotation, size was extracted for length already */
+               Mat3Ortho(rest_basis);
+               Mat3Ortho(basis);
+
+               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]);
        }
+
+       solver= IK_CreateSolver(ikchain[0]);
+
+       /* set solver goals */
+
+       /* first set the goal inverse transform, assuming the root of chain was done ok! */
+       pchan= chain->pchanchain[0];
+       Mat4One(rootmat);
+       VECCOPY(rootmat[3], pchan->pose_head);
        
-       /*      Solve the chain */
-       
-       IK_LoadChain(chain->solver, segs, chain->totchannel);
-       
-       IK_SolveChain(chain->solver, chain->goal, chain->tolerance,  
-                                 chain->iterations,  0.1f, chain->solver->segments);
+       Mat4MulMat4 (imat, rootmat, ob->obmat);
+       Mat4Invert (goalinv, imat);
        
+       for(target=chain->targets.first; target; target=target->next) {
+               data= (bKinematicConstraint*)target->con->data;
+
+               /* 1.0=ctime */
+               get_constraint_target_matrix(target->con, TARGET_BONE, NULL, rootmat, size, 1.0);
+
+               /* and set and transform goal */
+               Mat4MulMat4(goal, rootmat, goalinv);
+
+               VECCOPY(goalpos, goal[3]);
+               Mat3CpyMat4(goalrot, goal);
+
+               /* do we need blending? */
+               if(target->con->enforce!=1.0) {
+                       float vec[3], q1[4], q2[4], q[4];
+                       float fac= target->con->enforce;
+                       float mfac= 1.0-fac;
+                       
+                       pchan= chain->pchanchain[target->tip];
+
+                       /* blend position */
+                       VECCOPY(vec, pchan->pose_tail);
+                       Mat4MulVecfl(ob->obmat, vec); // world space
+                       Mat4MulVecfl(goalinv, vec);
+                       goalpos[0]= fac*goalpos[0] + mfac*vec[0];
+                       goalpos[1]= fac*goalpos[1] + mfac*vec[1];
+                       goalpos[2]= fac*goalpos[2] + mfac*vec[2];
+
+                       /* blend rotation */
+                       Mat3ToQuat(goalrot, q1);
+                       Mat3CpyMat4(R_bonemat, pchan->pose_mat);
+                       Mat3ToQuat(R_bonemat, q2);
+                       QuatInterpol(q, q1, q2, mfac);
+                       QuatToMat3(q, goalrot);
+               }
+
+               iktarget= ikchain[target->tip];
+
+               /*IK_SolverAddCenterOfMass(solver, ikchain[0], goalpos, data->weight);*/
+
+               if(data->weight != 0.0)
+                       IK_SolverAddGoal(solver, iktarget, goalpos, data->weight);
+               if((data->flag & KINEMATIC_ORIENTATION) && (data->orientweight != 0.0))
+                       IK_SolverAddGoalOrientation(solver, iktarget, goalrot, data->orientweight);
+       }
+
+       /* solve */
+       IK_Solve(solver, chain->tolerance, chain->iterations);
+       IK_FreeSolver(solver);
+
+       /* gather basis changes */
+       chain->basis_change= MEM_mallocN(sizeof(float[3][3])*chain->totchannel, "ik basis change");
+
+       for(a=0; a<chain->totchannel; a++) {
+               IK_GetBasisChange(ikchain[a], chain->basis_change[a]);
+               IK_FreeSegment(ikchain[a]);
+       }
        
-       /* not yet free! */
+       MEM_freeN(ikchain);
 }
 
 void free_posechain (PoseChain *chain)
 {
-       if (chain->solver) {
-               MEM_freeN (chain->solver->segments);
-               chain->solver->segments = NULL;
-               IK_FreeChain(chain->solver);
-       }
+       BLI_freelistN(&chain->targets);
        if(chain->pchanchain) MEM_freeN(chain->pchanchain);
+       if(chain->basis_change) MEM_freeN(chain->basis_change);
        MEM_freeN(chain);
 }
 
@@ -1325,16 +1463,19 @@ void where_is_pose (Object *ob)
                                                        if(!(chain->pchanchain[a]->flag & POSE_DONE))   // successive chains can set the flag
                                                                where_is_pose_bone(ob, chain->pchanchain[a]);
                                                }
-                                               /* 5. execute the IK solver */
-                                               execute_posechain(ob, chain);   // calculates 3x3 difference matrices
+                                               /* 5. execute the IK solver, applying differences to
+                                                       the channels and setting POSE_DONE */
+                                               execute_posechain(ob, chain);
+                                               
                                                /* 6. apply the differences to the channels, we calculate the original differences first */
                                                for(a=0; a<chain->totchannel; a++)
                                                        make_dmats(chain->pchanchain[a]);
+                                               
                                                for(a=0; a<chain->totchannel; a++)
-                                                       where_is_ik_bone(chain->pchanchain[a], (void *)chain->solver->segments[a].basis_change);
-                                                       // (sets POSE_DONE)
+                                                       /* sets POSE_DONE */
+                                                       where_is_ik_bone(chain->pchanchain[a], chain->basis_change[a]);
                                                
-                                               /* 6. and free */
+                                               /* 7. and free */
                                                BLI_remlink(&pchan->chain, chain);
                                                free_posechain(chain);
                                        }
index 7501957..5940c16 100644 (file)
@@ -485,6 +485,7 @@ void *new_constraint_data (short type)
                        data = MEM_callocN(sizeof(bKinematicConstraint), "kinematicConstraint");
 
                        data->tolerance = (float)0.001;
+                       data->weight= (float)1.0;
                        data->iterations = 500;
                        data->flag= CONSTRAINT_IK_TIP;
                        
index 1ef78b2..7bf2706 100644 (file)
@@ -4904,6 +4904,26 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
 
                                ob->softflag &= ~OB_SB_ENABLE;
                        }
+                       if(ob->pose) {
+                               bPoseChannel *pchan;
+                               bConstraint *con;
+                               for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+                                       if (pchan->stiffness[0] == 0.0f) {
+                                               pchan->stiffness[0]= pchan->stiffness[1]= pchan->stiffness[2]= 1.0;
+                                               pchan->limitmin[0]= pchan->limitmin[1]= pchan->limitmin[2]= -180.0f;
+                                               pchan->limitmax[0]= pchan->limitmax[1]= pchan->limitmax[2]= 180.0f;
+                                               
+                                               for(con= pchan->constraints.first; con; con= con->next) {
+                                                       if(con->type == CONSTRAINT_TYPE_KINEMATIC) {
+                                                               bKinematicConstraint *data = (bKinematicConstraint*)con->data;
+                                                               data->weight = 1.0f;
+                                                               data->orientweight = 0.0f;
+                                                               data->flag &= ~KINEMATIC_ORIENTATION;
+                                                       }       
+                                               }
+                                       }
+                               }
+                       }
                }
                
                for(arm=main->armature.first; arm; arm= arm->id.next) {
index 844b1d6..edc78a9 100644 (file)
@@ -47,7 +47,8 @@ typedef struct bPoseChannel {
        
        short                           flag;           /* dynamic, for detecting transform changes */
        short                           constflag;  /* for quick detecting which constraints affect this channel */
-       int                                     pad;
+       short                           ikflag;         /* settings for IK bones */
+       short                           pad;
        
        struct Bone                     *bone;          /* set on read file or rebuild pose */
        struct bPoseChannel *parent;    /* set on read file or rebuild pose */
@@ -65,7 +66,10 @@ typedef struct bPoseChannel {
        
        float           pose_head[3];           /* actually pose_mat[3] */
        float           pose_tail[3];           /* also used for drawing help lines... */
-       int pad1;
+       
+       float           limitmin[3], limitmax[3];       /* DOF constraint */
+       float           stiffness[3];                           /* DOF stiffness */
+       
 } bPoseChannel;
 
 
@@ -135,11 +139,21 @@ enum      {
        POSE_KEY                =       0x1000
 };
 
-/* Pose Channel constflag (constraint detection) */
+/* PoseChannel constflag (constraint detection) */
 #define PCHAN_HAS_IK           1
 #define PCHAN_HAS_CONST                2
        /* only used for drawing Posemode, not stored in channel */
 #define PCHAN_HAS_ACTION       4
 
+/* PoseChannel->ikflag */
+#define                BONE_IK_NO_XDOF 1
+#define                BONE_IK_NO_YDOF 2
+#define                BONE_IK_NO_ZDOF 4
+
+#define                BONE_IK_XLIMIT  8
+#define                BONE_IK_YLIMIT  16
+#define                BONE_IK_ZLIMIT  32
+
+
 #endif
 
index 7a1c899..e8895e9 100644 (file)
@@ -67,7 +67,9 @@ typedef struct bKinematicConstraint{
        short           flag;                   /* Like IK to Tip */
        char            subtarget[32];  /* String to specify sub-object target */
 
-
+       char            group[32];              /* Name of group */
+       float           weight;                 /* Weight of goal in IK group */
+       float           orientweight;
 } bKinematicConstraint;
 
 typedef struct bTrackToConstraint{
@@ -212,7 +214,8 @@ typedef struct bStretchToConstraint{
 #define PLANE_Z                0x02
 
 /* bKinematicConstraint->flag */
-#define CONSTRAINT_IK_TIP              1
+#define CONSTRAINT_IK_TIP                      1
+#define KINEMATIC_ORIENTATION          2
 
 #endif
 
index b8e7cc0..adaef66 100644 (file)
@@ -2280,7 +2280,7 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm)
        bPoseChannel *pchan;
        Bone            *curBone;
        int                     bx=148, by=180;
-       int                     index;
+       int                     index, zerodof, zerolimit;
        
        /* Draw the bone name block */
        
@@ -2320,7 +2320,53 @@ static void editing_panel_pose_bones(Object *ob, bArmature *arm)
                        uiDefButBitI(block, TOG, BONE_HIDDEN_P, REDRAWVIEW3D, "Hide",   bx+245,by-38,88,18, &curBone->flag, 0, 0, 0, 0, "Toggles display of this bone in Pose Mode");
                        uiBlockEndAlign(block);
                        
-                       by-=60;
+                       zerodof = 1;
+                       zerolimit = 1;
+                       
+                       uiBlockBeginAlign(block);
+                       uiDefButBitS(block, TOG, BONE_IK_NO_XDOF, B_ARM_RECALCDATA, "No X DoF", bx-10,by-60,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable X DoF for IK");
+                       if ((pchan->ikflag & BONE_IK_NO_XDOF)==0) {
+                               uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff X:", bx-10, by-80, 114, 19, &pchan->stiffness[0], 1.0, 100.0, 10.0f, 2.0f, "Resistance to bending for X axis");
+                               uiDefButBitS(block, TOG, BONE_IK_XLIMIT, B_ARM_RECALCDATA, "Limit X", bx-10,by-100,114,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over X axis");
+                               if ((pchan->ikflag & BONE_IK_XLIMIT)) {
+                                       uiDefButF(block, NUM, B_ARM_RECALCDATA, "Min X:", bx-10, by-120, 114, 19, &pchan->limitmin[0], -180.0f, 180.0f, 10.0f, 0.0f, "Minimum X limit");
+                                       uiDefButF(block, NUM, B_ARM_RECALCDATA, "Max X:", bx-10, by-140, 114, 19, &pchan->limitmax[0], -180.0f, 180.0f, 10.0f, 0.0f, "Maximum X limit");
+                                       zerolimit = 0;
+                               }
+                               zerodof = 0;
+                       }
+                       uiBlockEndAlign(block);
+                       
+                       uiBlockBeginAlign(block);
+                       uiDefButBitS(block, TOG, BONE_IK_NO_YDOF, B_ARM_RECALCDATA, "No Y DoF", bx+104,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Y DoF for IK");
+                       if ((pchan->ikflag & BONE_IK_NO_YDOF)==0) {
+                               uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff Y:", bx+104, by-80, 114, 19, &pchan->stiffness[1], 1.0, 100.0, 10.0f, 2.0f, "Resistance to bending for Y axis");
+                               uiDefButBitS(block, TOG, BONE_IK_YLIMIT, B_ARM_RECALCDATA, "Limit Y", bx+104,by-100,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over Y axis");
+                               if ((pchan->ikflag & BONE_IK_YLIMIT)) {
+                                       uiDefButF(block, NUM, B_ARM_RECALCDATA, "Min Y:", bx+104, by-120, 113, 19, &pchan->limitmin[1], -180.0f, 180.0f, 10.0f, 0.0f, "Minimum Y limit");
+                                       uiDefButF(block, NUM, B_ARM_RECALCDATA, "Max Y:", bx+104, by-140, 113, 19, &pchan->limitmax[1], -180.0f, 180.0f, 10.0f, 0.0f, "Maximum Y limit");
+                                       zerolimit = 0;
+                               }
+                               zerodof = 0;
+                       }
+                       uiBlockEndAlign(block);
+                       
+                       uiBlockBeginAlign(block);
+                       uiDefButBitS(block, TOG, BONE_IK_NO_ZDOF, B_ARM_RECALCDATA, "No Z DoF", bx+217,by-60,113,19, &pchan->ikflag, 0.0, 0.0, 0.0, 0.0, "Disable Z DoF for IK");
+                       if ((pchan->ikflag & BONE_IK_NO_ZDOF)==0) {
+                               uiDefButF(block, NUM, B_ARM_RECALCDATA, "Stiff Z:", bx+217, by-80, 114, 19, &pchan->stiffness[2], 1.0, 100.0, 10.0f, 2.0f, "Resistance to bending for Z axis");
+                               uiDefButBitS(block, TOG, BONE_IK_ZLIMIT, B_ARM_RECALCDATA, "Limit Z", bx+217,by-100,113,19, &pchan->flag, 0.0, 0.0, 0.0, 0.0, "Limit rotation over Z axis");
+                               if ((pchan->flag & BONE_IK_ZLIMIT)) {
+                                       uiDefButF(block, NUM, B_ARM_RECALCDATA, "Min Z:", bx+217, by-120, 113, 19, &pchan->limitmin[2], -180.0f, 180.0f, 10.0f, 0.0f, "Minimum Z limit");
+                                       uiDefButF(block, NUM, B_ARM_RECALCDATA, "Max Z:", bx+217, by-140, 113, 19, &pchan->limitmax[2], -180.0f, 180.0f, 10.0f, 0.0f, "Maximum Z limit");
+                                       zerolimit = 0;
+                               }
+                               zerodof = 0;
+                       }
+                       uiBlockEndAlign(block);
+                       
+                       by -= (zerodof)? 82: (zerolimit)? 122: 162;
+                       
                        if(by < -200) break;    // for time being... extreme long panels are very slow
                }
        }
index 834f3d7..7a1ce94 100644 (file)
@@ -585,7 +585,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                bKinematicConstraint *data = con->data;
                                bArmature *arm;
                                
-                               height = 66;
+                               height = 108;
                                uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+30,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
                                
                                uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
@@ -608,6 +608,11 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco+((width/2)+3), *yco-64, 120, 18, &data->iterations, 1, 10000, 0.0, 0.0, "Maximum number of solving iterations"); 
                                uiBlockEndAlign(block);
                                
+                               uiDefBut(block, TEX, B_CONSTRAINT_TEST, "IK group:", *xco+((width/2)-117), *yco-86,120,18, &data->group, 0, 24, 0, 0, "IK group name");
+                               uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "Weight ", *xco+((width/2)+3), *yco-86, 120, 18, &data->weight, 0.0, 1.0, 0.0, 0.0, "Weight of position control for this target");
+                               
+                               uiDefButBitS(block, TOG, KINEMATIC_ORIENTATION, B_CONSTRAINT_TEST, "Orientation", *xco+((width/2)-117), *yco-108,120,18, &data->flag, 0, 0, 0, 0, "Follow orientation of target");
+                               uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "Weight ", *xco+((width/2)+3), *yco-108, 120, 18, &data->orientweight, 0.0, 1.0, 0.0, 0.0, "Weight of orientation control for this target");
                        }
                        break;
                case CONSTRAINT_TYPE_TRACKTO: