Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_armature.h18
-rw-r--r--source/blender/blenkernel/bad_level_call_stubs/stubs.c37
-rw-r--r--source/blender/blenkernel/intern/action.c4
-rw-r--r--source/blender/blenkernel/intern/armature.c299
-rw-r--r--source/blender/blenkernel/intern/constraint.c1
-rw-r--r--source/blender/blenloader/intern/readfile.c20
-rw-r--r--source/blender/makesdna/DNA_action_types.h20
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h7
-rw-r--r--source/blender/src/buttons_editing.c50
-rw-r--r--source/blender/src/buttons_object.c7
10 files changed, 346 insertions, 117 deletions
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index d177edfce09..84d87b28037 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -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 */
diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
index 04371fbb0d0..aa5748ceb89 100644
--- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c
+++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c
@@ -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)
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 5af1cc34860..a3c7060a731 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -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;
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index dabc4fcf359..0d516e1036e 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -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);
}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 7501957af11..5940c16eccb 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -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;
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 1ef78b2eb7d..7bf2706956a 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -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) {
diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h
index 844b1d638fe..edc78a90260 100644
--- a/source/blender/makesdna/DNA_action_types.h
+++ b/source/blender/makesdna/DNA_action_types.h
@@ -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
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 7a1c899edb5..e8895e942d4 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -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
diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c
index b8e7cc0738d..adaef66ba64 100644
--- a/source/blender/src/buttons_editing.c
+++ b/source/blender/src/buttons_editing.c
@@ -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
}
}
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index 834f3d79e9a..7a1ce9463db 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -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: