From b48c514db87d360ddfcadfcde582c0cae9344d6c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 6 Nov 2006 23:51:37 +0000 Subject: [PATCH] Added an option in the IK constraint to disable stretching, useful in rigs with layered IK constraints. Also removed the tolerance setting, this value wasn't used in the solver anymore. --- source/blender/blenkernel/BKE_armature.h | 2 +- source/blender/blenkernel/intern/armature.c | 12 ++++++------ source/blender/blenkernel/intern/constraint.c | 4 ++-- source/blender/blenloader/intern/readfile.c | 7 +++++++ source/blender/makesdna/DNA_constraint_types.h | 7 ++++--- source/blender/python/api2_2x/Constraint.c | 14 +++++++------- source/blender/src/buttons_object.c | 17 ++++++++++------- 7 files changed, 37 insertions(+), 26 deletions(-) diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 1ce5f7d0f03..684e69e7694 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -63,8 +63,8 @@ typedef struct PoseTree int *parent; /* and their parents */ int totchannel; /* number of pose channels */ float (*basis_change)[3][3]; /* basis change result from solver */ - float tolerance; /* tolerance from the constraint */ int iterations; /* iterations from the constraint */ + int stretch; /* disable stretching */ } PoseTree; /* Core armature functionality */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 570a9d3d589..4ea02565b9b 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1118,9 +1118,9 @@ static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip) /* make new tree */ tree= MEM_callocN(sizeof(PoseTree), "posetree"); - tree->tolerance= data->tolerance; 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"); @@ -1134,8 +1134,8 @@ static void initialize_posetree(struct Object *ob, bPoseChannel *pchan_tip) BLI_addtail(&pchan_root->iktree, tree); } else { - tree->tolerance= MIN2(tree->tolerance, data->tolerance); 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); @@ -1216,7 +1216,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) if((pchan->ikflag & BONE_IK_NO_ZDOF) == 0) flag |= IK_ZDOF; - if(pchan->ikstretch > 0.0) { + if(tree->stretch && (pchan->ikstretch > 0.0)) { flag |= IK_TRANS_YDOF; hasstretch = 1; } @@ -1281,7 +1281,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) IK_SetStiffness(seg, IK_Y, pchan->stiffness[1]); IK_SetStiffness(seg, IK_Z, pchan->stiffness[2]); - if(pchan->ikstretch > 0.0) { + if(tree->stretch && (pchan->ikstretch > 0.0)) { float ikstretch = pchan->ikstretch*pchan->ikstretch; IK_SetStiffness(seg, IK_TRANS_Y, MIN2(1.0-ikstretch, 0.99)); IK_SetLimit(seg, IK_TRANS_Y, 0.001, 1e10); @@ -1352,7 +1352,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) } /* solve */ - IK_Solve(solver, tree->tolerance, tree->iterations); + IK_Solve(solver, 0.0f, tree->iterations); IK_FreeSolver(solver); /* gather basis changes */ @@ -1370,7 +1370,7 @@ static void execute_posetree(Object *ob, PoseTree *tree) pchan= tree->pchan[a]; parentstretch= (tree->parent[a] >= 0)? ikstretch[tree->parent[a]]: 1.0; - if(pchan->ikstretch > 0.0) { + if(tree->stretch && (pchan->ikstretch > 0.0)) { float trans[3], length; IK_GetTranslationChange(iktree[a], trans); diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index d78dd31fb60..351f4e84a6b 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -563,10 +563,10 @@ void *new_constraint_data (short type) bKinematicConstraint *data; data = MEM_callocN(sizeof(bKinematicConstraint), "kinematicConstraint"); - data->tolerance = (float)0.001; data->weight= (float)1.0; + data->orientweight= (float)1.0; data->iterations = 500; - data->flag= CONSTRAINT_IK_TIP; + data->flag= CONSTRAINT_IK_TIP|CONSTRAINT_IK_STRETCH|CONSTRAINT_IK_POS; result = data; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 39ba28912fd..1ce1f2c7237 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5764,6 +5764,13 @@ static void do_versions(FileData *fd, Library *lib, Main *main) data->flag&=~MINMAX_STICKY; } } + else if (curcon->type == CONSTRAINT_TYPE_KINEMATIC){ + bKinematicConstraint *data = curcon->data; + if (!(data->flag & CONSTRAINT_IK_POS)) { + data->flag |= CONSTRAINT_IK_POS; + data->flag |= CONSTRAINT_IK_STRETCH; + } + } } } } diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 8b8f8ae0f72..aa9625bd31b 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -62,16 +62,15 @@ typedef struct bConstraint{ /* Single-target subobject constraints */ typedef struct bKinematicConstraint{ Object *tar; - float tolerance; /* Acceptable distance from target */ short iterations; /* Maximum number of iterations to try */ short flag; /* Like CONSTRAINT_IK_TIP */ - int rootbone, pad; /* index to rootbone, if zero go all the way to mother bone */ + int rootbone; /* index to rootbone, if zero go all the way to mother bone */ char subtarget[32]; /* String to specify sub-object target */ float weight; /* Weight of goal in IK tree */ float orientweight; /* Amount of rotation a target applies on chain */ float grabtarget[3]; /* for target-less IK */ - float pad2; + int pad; } bKinematicConstraint; typedef struct bTrackToConstraint{ @@ -277,6 +276,8 @@ typedef struct bSizeLimitConstraint{ #define CONSTRAINT_IK_ROT 2 #define CONSTRAINT_IK_AUTO 4 #define CONSTRAINT_IK_TEMP 8 +#define CONSTRAINT_IK_STRETCH 16 +#define CONSTRAINT_IK_POS 32 /* MinMax (floor) flags */ #define MINMAX_STICKY 0x01 diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c index 2657ed51a72..e8a0566c89e 100644 --- a/source/blender/python/api2_2x/Constraint.c +++ b/source/blender/python/api2_2x/Constraint.c @@ -67,7 +67,7 @@ enum constraint_constants { EXPP_CONSTR_MINZ = TRACK_nZ, EXPP_CONSTR_TARGET = 100, - EXPP_CONSTR_TOLERANCE, + EXPP_CONSTR_STRETCH, EXPP_CONSTR_ITERATIONS, EXPP_CONSTR_BONE, EXPP_CONSTR_CHAINLEN, @@ -390,8 +390,8 @@ static PyObject *kinematic_getter( BPy_Constraint * self, int type ) return Object_CreatePyObject( con->tar ); case EXPP_CONSTR_BONE: return PyString_FromString( con->subtarget ); - case EXPP_CONSTR_TOLERANCE: - return PyFloat_FromDouble( (double)con->tolerance ); + case EXPP_CONSTR_STRETCH: + return PyBool_FromLong( (long)( con->flag & CONSTRAINT_IK_STRETCH ) ) ; case EXPP_CONSTR_ITERATIONS: return PyInt_FromLong( (long)con->iterations ); case EXPP_CONSTR_CHAINLEN: @@ -432,8 +432,8 @@ static int kinematic_setter( BPy_Constraint *self, int type, PyObject *value ) return 0; } - case EXPP_CONSTR_TOLERANCE: - return EXPP_setFloatClamped( value, &con->tolerance, 0.0001, 1.0 ); + case EXPP_CONSTR_STRETCH: + return EXPP_setBitfield( value, &con->flag, CONSTRAINT_IK_STRETCH, 'h' ); case EXPP_CONSTR_ITERATIONS: return EXPP_setIValueClamped( value, &con->iterations, 1, 10000, 'h' ); case EXPP_CONSTR_CHAINLEN: @@ -1829,8 +1829,8 @@ static PyObject *M_Constraint_SettingsDict( void ) PyConstant_Insert( d, "TARGET", PyInt_FromLong( EXPP_CONSTR_TARGET ) ); - PyConstant_Insert( d, "TOLERANCE", - PyInt_FromLong( EXPP_CONSTR_TOLERANCE ) ); + PyConstant_Insert( d, "STRETCH", + PyInt_FromLong( EXPP_CONSTR_STRETCH ) ); PyConstant_Insert( d, "ITERATIONS", PyInt_FromLong( EXPP_CONSTR_ITERATIONS ) ); PyConstant_Insert( d, "BONE", diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 8f05e20af0c..1dbd0a653cb 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -757,7 +757,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s { bKinematicConstraint *data = con->data; - height = 108; + height = 111; uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,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, ""); @@ -776,14 +776,17 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s strcpy (data->subtarget, ""); uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, CONSTRAINT_IK_TIP, B_CONSTRAINT_TEST, "Use Tip", *xco, *yco-64, 142, 19, &data->flag, 0, 0, 0, 0, "Include Bone's tip als last element in Chain"); - uiDefButI(block, NUM, B_CONSTRAINT_TEST, "ChainLen:", *xco+142, *yco-64,143,19, &data->rootbone, 0, 255, 0, 0, "If not zero, the amount of bones in this chain"); + uiDefButBitS(block, TOG, CONSTRAINT_IK_TIP, B_CONSTRAINT_TEST, "Use Tip", *xco, *yco-64, 137, 19, &data->flag, 0, 0, 0, 0, "Include Bone's tip als last element in Chain"); + uiDefButI(block, NUM, B_CONSTRAINT_TEST, "ChainLen:", *xco, *yco-84,137,19, &data->rootbone, 0, 255, 0, 0, "If not zero, the amount of bones in this chain"); uiBlockBeginAlign(block); - uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "PosW ", *xco, *yco-86, 142, 19, &data->weight, 0.01, 1.0, 2, 2, "For Tree-IK: weight of position control for this target"); - uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "RotW ", *xco+142, *yco-86, 143, 19, &data->orientweight, 0.01, 1.0, 2, 2, "For Tree-IK: Weight of orientation control for this target"); - uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Tolerance:", *xco, *yco-106, 142, 19, &data->tolerance, 0.0001f, 1.0, 0, 0, "Maximum distance to target after solving"); - uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco+142, *yco-106, 143, 19, &data->iterations, 1, 10000, 0, 0, "Maximum number of solving iterations"); + uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "PosW ", *xco+147, *yco-64, 137, 19, &data->weight, 0.01, 1.0, 2, 2, "For Tree-IK: weight of position control for this target"); + uiDefButF(block, NUMSLI, B_CONSTRAINT_TEST, "RotW ", *xco+147, *yco-84, 137, 19, &data->orientweight, 0.01, 1.0, 2, 2, "For Tree-IK: Weight of orientation control for this target"); + + uiBlockBeginAlign(block); + uiDefButS(block, NUM, B_CONSTRAINT_TEST, "Iterations:", *xco, *yco-109, 137, 19, &data->iterations, 1, 10000, 0, 0, "Maximum number of solving iterations"); + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG, CONSTRAINT_IK_STRETCH, B_CONSTRAINT_TEST, "Stretch", *xco+147, *yco-109,137,19, &data->flag, 0, 0, 0, 0, "Enable IK stretching"); } break;