Rigging Goodies: Spline IK Constraint

At last, this commit introduces the Spline IK Constraint to Blender. Spline IK is a constraint that makes n bones follow the shape of a specified curve. 

Simply add a chain of bones, add a curve, add a Spline IK Constraint to the tip bone and set the number of bones in the chain to make it work. Or, try the following test file:
http://download.blender.org/ftp/incoming/250_splineik_spine01.blend

Screenshots of this in action (as proof):
http://download.blender.org/ftp/incoming/b250_splineik_001_before.png
http://download.blender.org/ftp/incoming/b250_splineik_001_after.png

I've implemented this in a similar way to how standard IK solvers are done. However, this code is currently not an IK plugin, since I imagine that it would be useful to be able to combine the 2 types of IK. This can be easily changed though :)

Finally, a few notes on what to expect still:
* Constraint blending currently doesn't affect this. Getting that to work correctly will take a bit more work still.
* Options for not affecting the root joint (to make it easier to attach the chain to a stump or whatever), and non-uniform scaling options have yet to be added. I've marked the places where they can be added though
* Control over the twisting of the chain still needs investigation. 

Have fun!
This commit is contained in:
2009-11-01 11:29:40 +00:00
parent cb45db0336
commit 2068eaf1b7
16 changed files with 590 additions and 72 deletions

View File

@@ -327,7 +327,7 @@ static void test_constraints (Object *owner, const char substring[])
/* clear disabled-flag first */
curcon->flag &= ~CONSTRAINT_DISABLE;
if (curcon->type == CONSTRAINT_TYPE_KINEMATIC) {
bKinematicConstraint *data = curcon->data;
@@ -395,6 +395,26 @@ static void test_constraints (Object *owner, const char substring[])
if (data->lockflag+3==data->trackflag)
curcon->flag |= CONSTRAINT_DISABLE;
}
else if (curcon->type == CONSTRAINT_TYPE_SPLINEIK) {
bSplineIKConstraint *data = curcon->data;
/* if the number of points does not match the amount required by the chain length,
* free the points array and request a rebind...
*/
if ( (data->points == NULL) ||
(!(data->flag & CONSTRAINT_SPLINEIK_NO_ROOT) && (data->numpoints != data->chainlen+1)) ||
( (data->flag & CONSTRAINT_SPLINEIK_NO_ROOT) && (data->numpoints != data->chainlen)) )
{
/* free the points array */
if (data->points) {
MEM_freeN(data->points);
data->points = NULL;
}
/* clear the bound flag, forcing a rebind next time this is evaluated */
data->flag &= ~CONSTRAINT_SPLINEIK_BOUND;
}
}
/* Check targets for constraints */
if (cti && cti->get_constraint_targets) {
@@ -414,7 +434,7 @@ static void test_constraints (Object *owner, const char substring[])
}
/* target checks for specific constraints */
if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) {
if (ELEM3(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO, CONSTRAINT_TYPE_SPLINEIK)) {
if (ct->tar) {
if (ct->tar->type != OB_CURVE) {
ct->tar= NULL;
@@ -855,7 +875,7 @@ static int pose_constraints_clear_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans)
{
free_constraints(&pchan->constraints);
pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_CONST);
pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_SPLINEIK|PCHAN_HAS_CONST);
}
CTX_DATA_END;
@@ -947,6 +967,7 @@ static short get_new_constraint_target(bContext *C, int con_type, Object **tar_o
/* curve-based constraints - set the only_curve and only_ob flags */
case CONSTRAINT_TYPE_CLAMPTO:
case CONSTRAINT_TYPE_FOLLOWPATH:
case CONSTRAINT_TYPE_SPLINEIK:
only_curve= 1;
only_ob= 1;
add= 0;
@@ -1070,6 +1091,10 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
BKE_report(op->reports, RPT_ERROR, "IK Constraint can only be added to Bones.");
return OPERATOR_CANCELLED;
}
if ( (type == CONSTRAINT_TYPE_SPLINEIK) && ((!pchan) || (list != &pchan->constraints)) ) {
BKE_report(op->reports, RPT_ERROR, "Spline IK Constraint can only be added to Bones.");
return OPERATOR_CANCELLED;
}
/* create a new constraint of the type requried, and add it to the active/given constraints list */
con = add_new_constraint(type);
@@ -1119,6 +1144,7 @@ static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase
}
/* do type-specific tweaking to the constraint settings */
// TODO: does action constraint need anything here - i.e. spaceonce?
switch (type) {
case CONSTRAINT_TYPE_CHILDOF:
{