Two new IK features.

1) Target-less IK

If you add an IK constraint without a target set (no object or bone target),
it now can be grabbed and moved with IK, using its own Bone tip or root as
target itself. This way you can use IK for posing, without having the IK
executed while it animates or while a Pose is being solved for real IK.

After grabbing "Target-less IK", it applies the resulted motion in the
pose-channels, which then can be used to insert keypositions.

The Target-less IK bone can still be rotated without IK, also its chain
can be edited as usual.

UI: The CTRL+I menu gives this as an option too. In the 3D window it is
drawn with orangish color.

Note that IK is not resistant to non-uniform scaling yet.

2) Auto-IK

When the option "Automatic IK" is set, in Edit Buttons Armature Panel,
it creates automatic temporal Target-less IK for the Bone you grab or
translate.

The rules are:

- it only works when a single Bone is selected
- if the Bone is a root bone (no parent), it adds IK to the end of the
  chain(s)
- otherwise it adds the IK to the active Bone
- the temporal IK chain only consists of connected Bones.

This method is still a bit experimental. Maybe it should become a special
grabbing option (like SHIFT+G in Pose Mode). It also only works OK for rigs
that fit for it well... when a rig already is fully setup with IK it can't
do much good. :)
This commit is contained in:
2005-10-30 13:50:42 +00:00
parent b7a465b437
commit ea8b08c2cc
11 changed files with 434 additions and 107 deletions

View File

@@ -292,6 +292,10 @@ void update_pose_constraint_flags(bPose *pose)
bKinematicConstraint *data = (bKinematicConstraint*)con->data;
pchan->constflag |= PCHAN_HAS_IK;
if(data->tar==NULL || (data->tar->type==OB_ARMATURE && data->subtarget[0]==0))
pchan->constflag |= PCHAN_HAS_TARGET;
/* negative rootbone = recalc rootbone index. used in do_versions */
if(data->rootbone<0) {
data->rootbone= 0;

View File

@@ -986,7 +986,7 @@ void armature_rebuild_pose(Object *ob, bArmature *arm)
/* allocates PoseTree, and links that to root bone/channel */
/* note; if we got this working, it can become static too? */
/* 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;
@@ -1001,11 +1001,16 @@ static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip)
if(con->type==CONSTRAINT_TYPE_KINEMATIC) break;
}
if(con==NULL) return;
if(con->flag & CONSTRAINT_DISABLE) return; // not sure...
data=(bKinematicConstraint*)con->data;
if(data->tar==NULL) return;
if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0) return;
/* two types of targets */
if(data->flag & CONSTRAINT_IK_AUTO);
else {
if(con->flag & CONSTRAINT_DISABLE) return; /* checked in editconstraint.c */
if(data->tar==NULL) return;
if(data->tar->type==OB_ARMATURE && data->subtarget[0]==0) return;
}
/* exclude tip from chain? */
if(!(data->flag & CONSTRAINT_IK_TIP))
@@ -1232,8 +1237,8 @@ static void execute_posetree(Object *ob, PoseTree *tree)
for(target=tree->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);
/* 1.0=ctime, we pass on object for auto-ik<69> */
get_constraint_target_matrix(target->con, TARGET_BONE, ob, rootmat, size, 1.0);
/* and set and transform goal */
Mat4MulMat4(goal, rootmat, goalinv);

View File

@@ -748,7 +748,7 @@ static void constraint_target_to_mat4 (Object *ob, const char *substring, float
/* called during solve_constraints */
/* also for make_parent, to find correct inverse of "follow path" */
/* warning, ownerdata is void... is not Bone anymore, but posechannel */
/* warning, ownerdata is void... is not Bone anymore, but PoseChannel or Object */
short get_constraint_target_matrix (bConstraint *con, short ownertype, void* ownerdata, float mat[][4], float size[3], float ctime)
{
short valid=0;
@@ -908,6 +908,20 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
valid=1;
}
else if (data->flag & CONSTRAINT_IK_AUTO) {
Object *ob= ownerdata;
if(ob==NULL)
Mat4One(mat);
else {
float vec[3];
/* move grabtarget into world space */
VECCOPY(vec, data->grabtarget);
Mat4MulVecfl(ob->obmat, vec);
Mat4CpyMat4(mat, ob->obmat);
VECCOPY(mat[3], vec);
}
}
else
Mat4One (mat);
}