Spline IK: UI/Scaling Tweaks
* Renamed "Keep Max Length" to "Y Scaling" which has the opposite meaning * Improved the way that Y-Scaling off behaves. Most of the time, bones that do not fit on the curve are now "blended off" their default rotations instead of being scaled to zero. * Added option to offset an entire chain by moving the root bone of the chain. This is named "Chain Offset"
This commit is contained in:
@@ -602,11 +602,11 @@ class ConstraintButtonsPanel(bpy.types.Panel):
|
||||
col.itemL(text="Spline Fitting:")
|
||||
col.itemR(con, "chain_length")
|
||||
col.itemR(con, "even_divisions")
|
||||
#col.itemR(con, "affect_root") # XXX: this is not that useful yet
|
||||
col.itemR(con, "chain_offset")
|
||||
|
||||
col = layout.column()
|
||||
col.itemL(text="Chain Scaling:")
|
||||
col.itemR(con, "keep_max_length")
|
||||
col.itemR(con, "y_scaling")
|
||||
col.itemR(con, "xz_scaling_mode")
|
||||
|
||||
|
||||
|
||||
@@ -1707,7 +1707,7 @@ static void splineik_init_tree_from_pchan(Object *ob, bPoseChannel *pchan_tip)
|
||||
*/
|
||||
if ((ikData->flag & CONSTRAINT_SPLINEIK_EVENSPLITS) || (totLength == 0.0f)) {
|
||||
/* 1) equi-spaced joints */
|
||||
ikData->points[i]= segmentLen;
|
||||
ikData->points[i]= ikData->points[i-1] - segmentLen;
|
||||
}
|
||||
else {
|
||||
/* 2) to find this point on the curve, we take a step from the previous joint
|
||||
@@ -1811,9 +1811,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
|
||||
{
|
||||
bSplineIKConstraint *ikData= tree->ikData;
|
||||
float poseHead[3], poseTail[3], poseMat[4][4];
|
||||
float splineVec[3], scaleFac;
|
||||
float rad, radius=1.0f;
|
||||
float vec[4], dir[3];
|
||||
float splineVec[3], scaleFac, radius=1.0f;
|
||||
|
||||
/* firstly, calculate the bone matrix the standard way, since this is needed for roll control */
|
||||
where_is_pose_bone(scene, ob, pchan, ctime);
|
||||
@@ -1821,24 +1819,41 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
|
||||
VECCOPY(poseHead, pchan->pose_head);
|
||||
VECCOPY(poseTail, pchan->pose_tail);
|
||||
|
||||
/* step 1a: get xyz positions for the tail endpoint of the bone */
|
||||
if ( where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad) ) {
|
||||
/* convert the position to pose-space, then store it */
|
||||
mul_m4_v3(ob->imat, vec);
|
||||
VECCOPY(poseTail, vec);
|
||||
/* step 1: determine the positions for the endpoints of the bone */
|
||||
{
|
||||
float vec[4], dir[3], rad;
|
||||
float tailBlendFac= 1.0f;
|
||||
|
||||
/* set the new radius */
|
||||
radius= rad;
|
||||
}
|
||||
|
||||
/* step 1b: get xyz positions for the head endpoint of the bone */
|
||||
if ( where_on_path(ikData->tar, tree->points[index+1], vec, dir, NULL, &rad) ) {
|
||||
/* store the position, and convert it to pose space */
|
||||
mul_m4_v3(ob->imat, vec);
|
||||
VECCOPY(poseHead, vec);
|
||||
/* determine if the bone should still be affected by SplineIK */
|
||||
if (tree->points[index+1] >= 1.0f) {
|
||||
/* spline doesn't affect the bone anymore, so done... */
|
||||
pchan->flag |= POSE_DONE;
|
||||
return;
|
||||
}
|
||||
else if ((tree->points[index] >= 1.0f) && (tree->points[index+1] < 1.0f)) {
|
||||
/* blending factor depends on the amount of the bone still left on the chain */
|
||||
tailBlendFac= (1.0f - tree->points[index+1]) / (tree->points[index] - tree->points[index+1]);
|
||||
}
|
||||
|
||||
/* set the new radius (it should be the average value) */
|
||||
radius = (radius+rad) / 2;
|
||||
/* tail endpoint */
|
||||
if ( where_on_path(ikData->tar, tree->points[index], vec, dir, NULL, &rad) ) {
|
||||
/* convert the position to pose-space, then store it */
|
||||
mul_m4_v3(ob->imat, vec);
|
||||
interp_v3_v3v3(poseTail, pchan->pose_tail, vec, tailBlendFac);
|
||||
|
||||
/* set the new radius */
|
||||
radius= rad;
|
||||
}
|
||||
|
||||
/* head endpoint */
|
||||
if ( where_on_path(ikData->tar, tree->points[index+1], vec, dir, NULL, &rad) ) {
|
||||
/* store the position, and convert it to pose space */
|
||||
mul_m4_v3(ob->imat, vec);
|
||||
VECCOPY(poseHead, vec);
|
||||
|
||||
/* set the new radius (it should be the average value) */
|
||||
radius = (radius+rad) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* step 2: determine the implied transform from these endpoints
|
||||
@@ -1918,8 +1933,16 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
|
||||
}
|
||||
}
|
||||
|
||||
/* step 5: set the location of the bone in the matrix */
|
||||
VECCOPY(poseMat[3], poseHead);
|
||||
/* step 5: set the location of the bone in the matrix
|
||||
* - when the 'no-root' option is affected, the chain can retain
|
||||
* the shape but be moved elsewhere
|
||||
*/
|
||||
if (ikData->flag & CONSTRAINT_SPLINEIK_NO_ROOT) {
|
||||
VECCOPY(poseMat[3], pchan->pose_head);
|
||||
}
|
||||
else {
|
||||
VECCOPY(poseMat[3], poseHead);
|
||||
}
|
||||
|
||||
/* finally, store the new transform */
|
||||
copy_m4_m4(pchan->pose_mat, poseMat);
|
||||
|
||||
@@ -1732,7 +1732,7 @@ static bAnimChannelType ACF_DSARM=
|
||||
acf_dsarm_icon, /* icon */
|
||||
|
||||
acf_generic_dataexpand_setting_valid, /* has setting */
|
||||
acf_dsarm_setting_flag, /* flag for setting */
|
||||
acf_dsarm_setting_flag, /* flag for setting */
|
||||
acf_dsarm_setting_ptr /* pointer for setting */
|
||||
};
|
||||
|
||||
@@ -1794,19 +1794,19 @@ static void *acf_dsntree_setting_ptr(bAnimListElem *ale, int setting, short *typ
|
||||
}
|
||||
}
|
||||
|
||||
/* metaball expander type define */
|
||||
/* node tree expander type define */
|
||||
static bAnimChannelType ACF_DSNTREE=
|
||||
{
|
||||
acf_generic_dataexpand_backdrop,/* backdrop */
|
||||
acf_generic_indention_1, /* indent level */
|
||||
acf_generic_basic_offset, /* offset */
|
||||
|
||||
acf_generic_idblock_name, /* name */
|
||||
acf_dsntree_icon, /* icon */
|
||||
|
||||
acf_generic_dataexpand_setting_valid, /* has setting */
|
||||
acf_dsntree_setting_flag, /* flag for setting */
|
||||
acf_dsntree_setting_ptr /* pointer for setting */
|
||||
acf_generic_dataexpand_backdrop,/* backdrop */
|
||||
acf_generic_indention_1, /* indent level */ // XXX this only works for compositing
|
||||
acf_generic_basic_offset, /* offset */
|
||||
|
||||
acf_generic_idblock_name, /* name */
|
||||
acf_dsntree_icon, /* icon */
|
||||
|
||||
acf_generic_dataexpand_setting_valid, /* has setting */
|
||||
acf_dsntree_setting_flag, /* flag for setting */
|
||||
acf_dsntree_setting_ptr /* pointer for setting */
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -351,9 +351,7 @@ static void test_constraints (Object *owner, const char substring[])
|
||||
/* 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)) )
|
||||
if ((data->points == NULL) || (data->numpoints != data->chainlen+1))
|
||||
{
|
||||
/* free the points array */
|
||||
if (data->points) {
|
||||
|
||||
@@ -1706,9 +1706,9 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
|
||||
// TODO: add access to the positions array to allow more flexible aligning?
|
||||
|
||||
/* settings */
|
||||
prop= RNA_def_property(srna, "affect_root", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_NO_ROOT);
|
||||
RNA_def_property_ui_text(prop, "Affect Root", "Include the root joint in the calculations.");
|
||||
prop= RNA_def_property(srna, "chain_offset", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_NO_ROOT);
|
||||
RNA_def_property_ui_text(prop, "Chain Offset", "Offset the entire chain relative to the root joint.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
prop= RNA_def_property(srna, "even_divisions", PROP_BOOLEAN, PROP_NONE);
|
||||
@@ -1716,9 +1716,9 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
|
||||
RNA_def_property_ui_text(prop, "Even Divisions", "Ignore the relative lengths of the bones when fitting to the curve.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
prop= RNA_def_property(srna, "keep_max_length", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_SCALE_LIMITED);
|
||||
RNA_def_property_ui_text(prop, "Keep Max Length", "Maintain the maximum length of the chain when spline is stretched.");
|
||||
prop= RNA_def_property(srna, "y_scaling", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_SCALE_LIMITED);
|
||||
RNA_def_property_ui_text(prop, "Y Scaling", "Stretch the Y axis of the bones to fit the curve.");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
prop= RNA_def_property(srna, "xz_scaling_mode", PROP_ENUM, PROP_NONE);
|
||||
|
||||
Reference in New Issue
Block a user