IK Solver:
* Rename Legacy to Standard, it's not being deprecated as far as I know. * Make option to toggle off Location solving work with Standard. * Make it converge a bit better in some cases by enforcing a minimum number of iterations before giving up. * Move IK solver choice out of bone panel, it's an armature level setting and should be set there.
This commit is contained in:
@@ -377,7 +377,7 @@ bool IK_QJacobianSolver::Solve(
|
|||||||
norm = maxnorm;
|
norm = maxnorm;
|
||||||
|
|
||||||
// check for convergence
|
// check for convergence
|
||||||
if (norm < 1e-3) {
|
if (norm < 1e-3 && iterations > 10) {
|
||||||
solved = true;
|
solved = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -239,7 +239,7 @@ class DATA_PT_ghost(ArmatureButtonsPanel, Panel):
|
|||||||
|
|
||||||
|
|
||||||
class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel):
|
class DATA_PT_iksolver_itasc(ArmatureButtonsPanel, Panel):
|
||||||
bl_label = "iTaSC parameters"
|
bl_label = "Inverse Kinematics"
|
||||||
bl_options = {'DEFAULT_CLOSED'}
|
bl_options = {'DEFAULT_CLOSED'}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -244,7 +244,6 @@ class BONE_PT_inverse_kinematics(BoneButtonsPanel, Panel):
|
|||||||
pchan = ob.pose.bones[bone.name]
|
pchan = ob.pose.bones[bone.name]
|
||||||
|
|
||||||
row = layout.row()
|
row = layout.row()
|
||||||
row.prop(ob.pose, "ik_solver")
|
|
||||||
|
|
||||||
active = pchan.is_in_ik_chain
|
active = pchan.is_in_ik_chain
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ class ConstraintButtonsPanel():
|
|||||||
layout.prop(con, "ik_type")
|
layout.prop(con, "ik_type")
|
||||||
getattr(self, 'IK_' + con.ik_type)(context, layout, con)
|
getattr(self, 'IK_' + con.ik_type)(context, layout, con)
|
||||||
else:
|
else:
|
||||||
# Legacy IK constraint
|
# Standard IK constraint
|
||||||
self.target_template(layout, con)
|
self.target_template(layout, con)
|
||||||
layout.prop(con, "pole_target")
|
layout.prop(con, "pole_target")
|
||||||
|
|
||||||
@@ -151,17 +151,27 @@ class ConstraintButtonsPanel():
|
|||||||
col.prop(con, "iterations")
|
col.prop(con, "iterations")
|
||||||
col.prop(con, "chain_count")
|
col.prop(con, "chain_count")
|
||||||
|
|
||||||
col.label(text="Weight:")
|
|
||||||
col.prop(con, "weight", text="Position", slider=True)
|
|
||||||
sub = col.column()
|
|
||||||
sub.active = con.use_rotation
|
|
||||||
sub.prop(con, "orient_weight", text="Rotation", slider=True)
|
|
||||||
|
|
||||||
col = split.column()
|
col = split.column()
|
||||||
col.prop(con, "use_tail")
|
col.prop(con, "use_tail")
|
||||||
col.prop(con, "use_stretch")
|
col.prop(con, "use_stretch")
|
||||||
col.separator()
|
|
||||||
col.prop(con, "use_rotation")
|
layout.label(text="Weight:")
|
||||||
|
|
||||||
|
split = layout.split()
|
||||||
|
col = split.column()
|
||||||
|
row = col.row(align=True)
|
||||||
|
row.prop(con, "use_location", text="")
|
||||||
|
sub = row.row()
|
||||||
|
sub.active = con.use_location
|
||||||
|
sub.prop(con, "weight", text="Position", slider=True)
|
||||||
|
|
||||||
|
col = split.column()
|
||||||
|
row = col.row(align=True)
|
||||||
|
row.prop(con, "use_rotation", text="")
|
||||||
|
sub = row.row()
|
||||||
|
sub.active = con.use_rotation
|
||||||
|
sub.prop(con, "orient_weight", text="Rotation", slider=True)
|
||||||
|
|
||||||
|
|
||||||
def IK_COPY_POSE(self, context, layout, con):
|
def IK_COPY_POSE(self, context, layout, con):
|
||||||
self.target_template(layout, con)
|
self.target_template(layout, con)
|
||||||
|
|||||||
@@ -512,7 +512,7 @@ const char *BKE_pose_ikparam_get_name(bPose *pose)
|
|||||||
{
|
{
|
||||||
if (pose) {
|
if (pose) {
|
||||||
switch (pose->iksolver) {
|
switch (pose->iksolver) {
|
||||||
case IKSOLVER_LEGACY:
|
case IKSOLVER_STANDARD:
|
||||||
return NULL;
|
return NULL;
|
||||||
case IKSOLVER_ITASC:
|
case IKSOLVER_ITASC:
|
||||||
return "bItasc";
|
return "bItasc";
|
||||||
@@ -587,7 +587,7 @@ void BKE_pose_ikparam_init(bPose *pose)
|
|||||||
BKE_pose_itasc_init(itasc);
|
BKE_pose_itasc_init(itasc);
|
||||||
pose->ikparam = itasc;
|
pose->ikparam = itasc;
|
||||||
break;
|
break;
|
||||||
case IKSOLVER_LEGACY:
|
case IKSOLVER_STANDARD:
|
||||||
default:
|
default:
|
||||||
pose->ikparam = NULL;
|
pose->ikparam = NULL;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -379,6 +379,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
|
|||||||
|
|
||||||
copy_v3_v3(goalpos, goal[3]);
|
copy_v3_v3(goalpos, goal[3]);
|
||||||
copy_m3_m4(goalrot, goal);
|
copy_m3_m4(goalrot, goal);
|
||||||
|
normalize_m3(goalrot);
|
||||||
|
|
||||||
/* same for pole vector target */
|
/* same for pole vector target */
|
||||||
if (data->poletar) {
|
if (data->poletar) {
|
||||||
@@ -433,7 +434,7 @@ static void execute_posetree(struct Scene *scene, Object *ob, PoseTree *tree)
|
|||||||
|
|
||||||
iktarget = iktree[target->tip];
|
iktarget = iktree[target->tip];
|
||||||
|
|
||||||
if (data->weight != 0.0f) {
|
if ((data->flag & CONSTRAINT_IK_POS) && data->weight != 0.0f) {
|
||||||
if (poleconstrain)
|
if (poleconstrain)
|
||||||
IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos,
|
IK_SolverSetPoleVectorConstraint(solver, iktarget, goalpos,
|
||||||
polepos, data->poleangle, (poleangledata == data));
|
polepos, data->poleangle, (poleangledata == data));
|
||||||
|
|||||||
@@ -372,7 +372,7 @@ typedef enum ePose_Flags {
|
|||||||
|
|
||||||
/* bPose->iksolver and bPose->ikparam->iksolver */
|
/* bPose->iksolver and bPose->ikparam->iksolver */
|
||||||
typedef enum ePose_IKSolverType {
|
typedef enum ePose_IKSolverType {
|
||||||
IKSOLVER_LEGACY = 0,
|
IKSOLVER_STANDARD = 0,
|
||||||
IKSOLVER_ITASC = 1
|
IKSOLVER_ITASC = 1
|
||||||
} ePose_IKSolverType;
|
} ePose_IKSolverType;
|
||||||
|
|
||||||
|
|||||||
@@ -614,7 +614,7 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna)
|
|||||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
|
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE);
|
prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE);
|
||||||
RNA_def_property_range(prop, 1, 10000);
|
RNA_def_property_range(prop, 0, 10000);
|
||||||
RNA_def_property_ui_text(prop, "Iterations", "Maximum number of solving iterations");
|
RNA_def_property_ui_text(prop, "Iterations", "Maximum number of solving iterations");
|
||||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||||
|
|
||||||
|
|||||||
@@ -675,7 +675,7 @@ static void rna_def_bone_group(BlenderRNA *brna)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static EnumPropertyItem prop_iksolver_items[] = {
|
static EnumPropertyItem prop_iksolver_items[] = {
|
||||||
{IKSOLVER_LEGACY, "LEGACY", 0, "Legacy", "Original IK solver"},
|
{IKSOLVER_STANDARD, "LEGACY", 0, "Standard", "Original IK solver"},
|
||||||
{IKSOLVER_ITASC, "ITASC", 0, "iTaSC", "Multi constraint, stateful IK solver"},
|
{IKSOLVER_ITASC, "ITASC", 0, "iTaSC", "Multi constraint, stateful IK solver"},
|
||||||
{0, NULL, 0, NULL, NULL}
|
{0, NULL, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
@@ -1126,7 +1126,7 @@ static void rna_def_pose_itasc(BlenderRNA *brna)
|
|||||||
|
|
||||||
prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE);
|
prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE);
|
||||||
RNA_def_property_int_sdna(prop, NULL, "numiter");
|
RNA_def_property_int_sdna(prop, NULL, "numiter");
|
||||||
RNA_def_property_range(prop, 1.f, 1000.f);
|
RNA_def_property_range(prop, 0, 1000);
|
||||||
RNA_def_property_ui_text(prop, "Iterations",
|
RNA_def_property_ui_text(prop, "Iterations",
|
||||||
"Maximum number of iterations for convergence in case of reiteration");
|
"Maximum number of iterations for convergence in case of reiteration");
|
||||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Itasc_update");
|
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Itasc_update");
|
||||||
@@ -1221,8 +1221,7 @@ static void rna_def_pose_ikparam(BlenderRNA *brna)
|
|||||||
RNA_def_property_enum_sdna(prop, NULL, "iksolver");
|
RNA_def_property_enum_sdna(prop, NULL, "iksolver");
|
||||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||||
RNA_def_property_enum_items(prop, prop_iksolver_items);
|
RNA_def_property_enum_items(prop, prop_iksolver_items);
|
||||||
RNA_def_property_ui_text(prop, "IK Solver",
|
RNA_def_property_ui_text(prop, "IK Solver", "IK solver for which these parameters are defined");
|
||||||
"IK solver for which these parameters are defined, 0 for Legacy, 1 for iTaSC");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pose.bone_groups */
|
/* pose.bone_groups */
|
||||||
@@ -1285,8 +1284,7 @@ static void rna_def_pose(BlenderRNA *brna)
|
|||||||
RNA_def_property_enum_sdna(prop, NULL, "iksolver");
|
RNA_def_property_enum_sdna(prop, NULL, "iksolver");
|
||||||
RNA_def_property_enum_funcs(prop, NULL, "rna_Pose_ik_solver_set", NULL);
|
RNA_def_property_enum_funcs(prop, NULL, "rna_Pose_ik_solver_set", NULL);
|
||||||
RNA_def_property_enum_items(prop, prop_iksolver_items);
|
RNA_def_property_enum_items(prop, prop_iksolver_items);
|
||||||
RNA_def_property_ui_text(prop, "IK Solver",
|
RNA_def_property_ui_text(prop, "IK Solver", "Selection of IK solver for IK chain");
|
||||||
"Selection of IK solver for IK chain, current choice is 0 for Legacy, 1 for iTaSC");
|
|
||||||
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_ik_solver_update");
|
RNA_def_property_update(prop, NC_OBJECT | ND_POSE, "rna_Pose_ik_solver_update");
|
||||||
|
|
||||||
prop = RNA_def_property(srna, "ik_param", PROP_POINTER, PROP_NONE);
|
prop = RNA_def_property(srna, "ik_param", PROP_POINTER, PROP_NONE);
|
||||||
|
|||||||
Reference in New Issue
Block a user