Spline IK: support changing individual bone length via Y scaling.
Previously Spline IK provided only two choices: either scale the length of the bone chain to fit the length of the curve, or don't scale the bone in the Y dimension at all (ignoring effects of actually fitting to the curve due to curvature and curve object scale). This patch adds a new option to use the pre-IK Y scale of the bones to adjust their length when fitted to the curve, allowing individual posing control over the length of the segments. Reviewers: brecht Differential Revision: https://developer.blender.org/D4687
This commit is contained in:
@@ -794,9 +794,9 @@ class ConstraintButtonsPanel:
|
|||||||
|
|
||||||
col = layout.column()
|
col = layout.column()
|
||||||
col.label(text="Chain Scaling:")
|
col.label(text="Chain Scaling:")
|
||||||
col.prop(con, "use_y_stretch")
|
|
||||||
col.prop(con, "use_curve_radius")
|
col.prop(con, "use_curve_radius")
|
||||||
|
|
||||||
|
layout.prop(con, "y_scale_mode")
|
||||||
layout.prop(con, "xz_scale_mode")
|
layout.prop(con, "xz_scale_mode")
|
||||||
|
|
||||||
if con.xz_scale_mode == 'VOLUME_PRESERVE':
|
if con.xz_scale_mode == 'VOLUME_PRESERVE':
|
||||||
|
@@ -230,7 +230,7 @@ static bool splineik_evaluate_init(tSplineIK_Tree *tree, tSplineIk_EvalState *st
|
|||||||
unit_m4(state->locrot_offset);
|
unit_m4(state->locrot_offset);
|
||||||
|
|
||||||
/* Apply corrections for sensitivity to scaling. */
|
/* Apply corrections for sensitivity to scaling. */
|
||||||
if ((ikData->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) && (tree->totlength != 0.0f)) {
|
if ((ikData->yScaleMode != CONSTRAINT_SPLINEIK_YS_FIT_CURVE) && (tree->totlength != 0.0f)) {
|
||||||
/* get the current length of the curve */
|
/* get the current length of the curve */
|
||||||
/* NOTE: this is assumed to be correct even after the curve was resized */
|
/* NOTE: this is assumed to be correct even after the curve was resized */
|
||||||
float splineLen = cache->path->totdist;
|
float splineLen = cache->path->totdist;
|
||||||
@@ -262,6 +262,12 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Object *ob, bPoseChanne
|
|||||||
float curveLen = tree->points[index] - tree->points[index + 1];
|
float curveLen = tree->points[index] - tree->points[index + 1];
|
||||||
float pointStart = state->curve_position;
|
float pointStart = state->curve_position;
|
||||||
float baseScale = 1.0f;
|
float baseScale = 1.0f;
|
||||||
|
|
||||||
|
if (ikData->yScaleMode == CONSTRAINT_SPLINEIK_YS_ORIGINAL) {
|
||||||
|
/* Carry over the bone Y scale to the curve range. */
|
||||||
|
baseScale = len_v3v3(poseHead, poseTail) / pchan->bone->length;
|
||||||
|
}
|
||||||
|
|
||||||
float pointEnd = pointStart + curveLen * baseScale * state->curve_scale;
|
float pointEnd = pointStart + curveLen * baseScale * state->curve_scale;
|
||||||
|
|
||||||
state->curve_position = pointEnd;
|
state->curve_position = pointEnd;
|
||||||
|
@@ -3959,6 +3959,8 @@ static void splineik_new_data(void *cdata)
|
|||||||
data->bulge = 1.0;
|
data->bulge = 1.0;
|
||||||
data->bulge_max = 1.0f;
|
data->bulge_max = 1.0f;
|
||||||
data->bulge_min = 1.0f;
|
data->bulge_min = 1.0f;
|
||||||
|
|
||||||
|
data->yScaleMode = CONSTRAINT_SPLINEIK_YS_FIT_CURVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void splineik_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
|
static void splineik_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
|
||||||
|
@@ -3140,6 +3140,23 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
if (!DNA_struct_elem_find(fd->filesdna, "bSplineIKConstraint", "short", "yScaleMode")) {
|
||||||
|
for (Object *ob = bmain->objects.first; ob; ob = ob->id.next) {
|
||||||
|
if (ob->pose) {
|
||||||
|
for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
|
||||||
|
for (bConstraint *con = pchan->constraints.first; con; con = con->next) {
|
||||||
|
if (con->type == CONSTRAINT_TYPE_SPLINEIK) {
|
||||||
|
bSplineIKConstraint *data = (bSplineIKConstraint *)con->data;
|
||||||
|
if ((data->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) == 0) {
|
||||||
|
data->yScaleMode = CONSTRAINT_SPLINEIK_YS_FIT_CURVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Versioning code until next subversion bump goes here. */
|
/* Versioning code until next subversion bump goes here. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -231,6 +231,9 @@ typedef struct bSplineIKConstraint {
|
|||||||
short flag;
|
short flag;
|
||||||
/** Method used for determining the x & z scaling of the bones. */
|
/** Method used for determining the x & z scaling of the bones. */
|
||||||
short xzScaleMode;
|
short xzScaleMode;
|
||||||
|
/** Method used for determining the y scaling of the bones. */
|
||||||
|
short yScaleMode;
|
||||||
|
short _pad[3];
|
||||||
|
|
||||||
/* volume preservation settings */
|
/* volume preservation settings */
|
||||||
float bulge;
|
float bulge;
|
||||||
@@ -879,8 +882,10 @@ typedef enum eSplineIK_Flags {
|
|||||||
CONSTRAINT_SPLINEIK_BOUND = (1 << 0),
|
CONSTRAINT_SPLINEIK_BOUND = (1 << 0),
|
||||||
/* root of chain is not influenced by the constraint */
|
/* root of chain is not influenced by the constraint */
|
||||||
CONSTRAINT_SPLINEIK_NO_ROOT = (1 << 1),
|
CONSTRAINT_SPLINEIK_NO_ROOT = (1 << 1),
|
||||||
|
#ifdef DNA_DEPRECATED
|
||||||
/* bones in the chain should not scale to fit the curve */
|
/* bones in the chain should not scale to fit the curve */
|
||||||
CONSTRAINT_SPLINEIK_SCALE_LIMITED = (1 << 2),
|
CONSTRAINT_SPLINEIK_SCALE_LIMITED = (1 << 2),
|
||||||
|
#endif
|
||||||
/* evenly distribute the bones along the path regardless of length */
|
/* evenly distribute the bones along the path regardless of length */
|
||||||
CONSTRAINT_SPLINEIK_EVENSPLITS = (1 << 3),
|
CONSTRAINT_SPLINEIK_EVENSPLITS = (1 << 3),
|
||||||
/* don't adjust the x and z scaling of the bones by the curve radius */
|
/* don't adjust the x and z scaling of the bones by the curve radius */
|
||||||
@@ -903,6 +908,16 @@ typedef enum eSplineIK_XZScaleModes {
|
|||||||
CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC = 3,
|
CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC = 3,
|
||||||
} eSplineIK_XZScaleModes;
|
} eSplineIK_XZScaleModes;
|
||||||
|
|
||||||
|
/* bSplineIKConstraint->yScaleMode */
|
||||||
|
typedef enum eSplineIK_YScaleModes {
|
||||||
|
/* no y scaling */
|
||||||
|
CONSTRAINT_SPLINEIK_YS_NONE = 0,
|
||||||
|
/* bones in the chain should be scaled to fit the length of the curve */
|
||||||
|
CONSTRAINT_SPLINEIK_YS_FIT_CURVE = 1,
|
||||||
|
/* bones in the chain should take their y scales from the original scaling */
|
||||||
|
CONSTRAINT_SPLINEIK_YS_ORIGINAL = 2,
|
||||||
|
} eSplineIK_YScaleModes;
|
||||||
|
|
||||||
/* bArmatureConstraint -> flag */
|
/* bArmatureConstraint -> flag */
|
||||||
typedef enum eArmature_Flags {
|
typedef enum eArmature_Flags {
|
||||||
/** use dual quaternion blending */
|
/** use dual quaternion blending */
|
||||||
|
@@ -2262,6 +2262,15 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
|
|||||||
{0, NULL, 0, NULL, NULL},
|
{0, NULL, 0, NULL, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const EnumPropertyItem splineik_y_scale_mode[] = {
|
||||||
|
{CONSTRAINT_SPLINEIK_YS_NONE, "NONE", 0, "None", "Don't scale in the Y axis"},
|
||||||
|
{CONSTRAINT_SPLINEIK_YS_FIT_CURVE, "FIT_CURVE", 0, "Fit Curve",
|
||||||
|
"Scale the bones to fit the entire length of the curve"},
|
||||||
|
{CONSTRAINT_SPLINEIK_YS_ORIGINAL, "BONE_ORIGINAL", 0, "Bone Original",
|
||||||
|
"Use the original Y scale of the bone"},
|
||||||
|
{0, NULL, 0, NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
srna = RNA_def_struct(brna, "SplineIKConstraint", "Constraint");
|
srna = RNA_def_struct(brna, "SplineIKConstraint", "Constraint");
|
||||||
RNA_def_struct_ui_text(srna, "Spline IK Constraint", "Align 'n' bones along a curve");
|
RNA_def_struct_ui_text(srna, "Spline IK Constraint", "Align 'n' bones along a curve");
|
||||||
RNA_def_struct_sdna_from(srna, "bSplineIKConstraint", "data");
|
RNA_def_struct_sdna_from(srna, "bSplineIKConstraint", "data");
|
||||||
@@ -2308,11 +2317,6 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
|
|||||||
"Ignore the relative lengths of the bones when fitting to the curve");
|
"Ignore the relative lengths of the bones when fitting to the curve");
|
||||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "use_y_stretch", PROP_BOOLEAN, PROP_NONE);
|
|
||||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_SCALE_LIMITED);
|
|
||||||
RNA_def_property_ui_text(prop, "Y Stretch", "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, "use_curve_radius", PROP_BOOLEAN, PROP_NONE);
|
prop = RNA_def_property(srna, "use_curve_radius", PROP_BOOLEAN, PROP_NONE);
|
||||||
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_NO_CURVERAD);
|
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_NO_CURVERAD);
|
||||||
RNA_def_property_ui_text(prop, "Use Curve Radius",
|
RNA_def_property_ui_text(prop, "Use Curve Radius",
|
||||||
@@ -2328,6 +2332,15 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
|
|||||||
"Method used for determining the scaling of the X and Z axes of the bones");
|
"Method used for determining the scaling of the X and Z axes of the bones");
|
||||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||||
|
|
||||||
|
/* y scaling mode */
|
||||||
|
prop = RNA_def_property(srna, "y_scale_mode", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_sdna(prop, NULL, "yScaleMode");
|
||||||
|
RNA_def_property_enum_items(prop, splineik_y_scale_mode);
|
||||||
|
RNA_def_property_ui_text(prop, "Y Scale Mode",
|
||||||
|
"Method used for determining the scaling of the Y axis of the bones, "
|
||||||
|
"on top of the shape and scaling of the curve itself");
|
||||||
|
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||||
|
|
||||||
/* volume presevation for "volumetric" scale mode */
|
/* volume presevation for "volumetric" scale mode */
|
||||||
prop = RNA_def_property(srna, "bulge", PROP_FLOAT, PROP_NONE);
|
prop = RNA_def_property(srna, "bulge", PROP_FLOAT, PROP_NONE);
|
||||||
RNA_def_property_range(prop, 0.0, 100.f);
|
RNA_def_property_range(prop, 0.0, 100.f);
|
||||||
|
Reference in New Issue
Block a user