iTaSC: Selection of constrained axis for CopyPose constraint

This commit implements more of the CopyPose capabilities in
Blender. It is now possible to select which axis will be
constrained in position and orientation to obtain
interesting effects. Another option selects if the axis
are relative to the end effector or to the target.

Unlocking a position axis means that the coordinate along
this axis is not constrained and can take any value.
Unlocking the Y axis of the End Effector produces an
'aiming' effect: the end effector is oriented towards
the target but without stretching.

Unlocking a rotation axis means that the end effector can
freely rotation along that axis. Unlocking the Y axis
produces a 'tangent' effect: the end effector aligns with
the Y axis of the target but can rotate along that axis.

A 'floor' effect is possible if the position Z axis of the
target is unlocked. More effects are possible an can be
combined.
This commit is contained in:
Benoit Bolsee 2009-10-14 18:51:00 +00:00
parent f579fe5681
commit 96d2dc7d09
4 changed files with 148 additions and 32 deletions

@ -50,6 +50,7 @@ class ConstraintButtonsPanel(bpy.types.Panel):
layout.item_pointerR(con, "subtarget", con.target, "vertex_groups", text="Vertex Group") layout.item_pointerR(con, "subtarget", con.target, "vertex_groups", text="Vertex Group")
def ik_template(self, layout, con): def ik_template(self, layout, con):
# only used for iTaSC
layout.itemR(con, "pole_target") layout.itemR(con, "pole_target")
if con.pole_target and con.pole_target.type == 'ARMATURE': if con.pole_target and con.pole_target.type == 'ARMATURE':
@ -60,14 +61,14 @@ class ConstraintButtonsPanel(bpy.types.Panel):
row.itemL() row.itemL()
row.itemR(con, "pole_angle") row.itemR(con, "pole_angle")
split = layout.split() split = layout.split(percentage=0.33)
col = split.column() col = split.column()
col.itemR(con, "tail") col.itemR(con, "tail")
col.itemR(con, "stretch") col.itemR(con, "stretch")
col = split.column() col = split.column()
col.itemR(con, "iterations")
col.itemR(con, "chain_length") col.itemR(con, "chain_length")
col.itemR(con, "targetless")
def CHILD_OF(self, context, layout, con): def CHILD_OF(self, context, layout, con):
self.target_template(layout, con) self.target_template(layout, con)
@ -115,11 +116,26 @@ class ConstraintButtonsPanel(bpy.types.Panel):
layout.itemR(con, "ik_type") layout.itemR(con, "ik_type")
getattr(self, "IK_"+con.ik_type)(context, layout, con) getattr(self, "IK_"+con.ik_type)(context, layout, con)
else: else:
self.IK_COPY_POSE(context, layout, con) # Legacy IK constraint
def IK_COPY_POSE(self, context, layout, con):
self.target_template(layout, con) self.target_template(layout, con)
self.ik_template(layout, con) layout.itemR(con, "pole_target")
if con.pole_target and con.pole_target.type == 'ARMATURE':
layout.item_pointerR(con, "pole_subtarget", con.pole_target.data, "bones", text="Bone")
if con.pole_target:
row = layout.row()
row.itemL()
row.itemR(con, "pole_angle")
split = layout.split()
col = split.column()
col.itemR(con, "tail")
col.itemR(con, "stretch")
col = split.column()
col.itemR(con, "iterations")
col.itemR(con, "chain_length")
split = layout.split() split = layout.split()
col = split.column() col = split.column()
@ -134,6 +150,41 @@ class ConstraintButtonsPanel(bpy.types.Panel):
sub.active = con.rotation sub.active = con.rotation
sub.itemR(con, "orient_weight", text="Rotation", slider=True) sub.itemR(con, "orient_weight", text="Rotation", slider=True)
def IK_COPY_POSE(self, context, layout, con):
self.target_template(layout, con)
self.ik_template(layout, con)
row = layout.row()
row.itemL(text="Axis Ref:")
row.itemR(con, "axis_reference", expand=True)
split = layout.split(percentage=0.33)
split.row().itemR(con, "position")
row = split.row()
row.itemR(con, "weight", text="Weight", slider=True)
row.active = con.position
split = layout.split(percentage=0.33)
row = split.row()
row.itemL(text="Lock:")
row = split.row()
row.itemR(con, "pos_lock_x", text="X")
row.itemR(con, "pos_lock_y", text="Y")
row.itemR(con, "pos_lock_z", text="Z")
split.active = con.position
split = layout.split(percentage=0.33)
split.row().itemR(con, "rotation")
row = split.row()
row.itemR(con, "orient_weight", text="Weight", slider=True)
row.active = con.rotation
split = layout.split(percentage=0.33)
row = split.row()
row.itemL(text="Lock:")
row = split.row()
row.itemR(con, "rot_lock_x", text="X")
row.itemR(con, "rot_lock_y", text="Y")
row.itemR(con, "rot_lock_z", text="Z")
split.active = con.rotation
def IK_DISTANCE(self, context, layout, con): def IK_DISTANCE(self, context, layout, con):
self.target_template(layout, con) self.target_template(layout, con)
self.ik_template(layout, con) self.ik_template(layout, con)
@ -610,20 +661,13 @@ class BONE_PT_inverse_kinematics(ConstraintButtonsPanel):
split.itemL() split.itemL()
if ob.pose.ik_solver == "ITASC": if ob.pose.ik_solver == "ITASC":
layout.itemL(text="Joint constraint:") row = layout.row()
split = layout.split(percentage=0.3) row.itemR(pchan, "ik_rot_control", text="Control Rotation")
row = split.row()
row.itemR(pchan, "ik_rot_control", text="Rotation")
row = split.row()
row.itemR(pchan, "ik_rot_weight", text="Weight", slider=True) row.itemR(pchan, "ik_rot_weight", text="Weight", slider=True)
row.active = pchan.ik_rot_control
# not supported yet # not supported yet
#split = layout.split(percentage=0.3) #row = layout.row()
#row = split.row() #row.itemR(pchan, "ik_lin_control", text="Joint Size")
#row.itemR(pchan, "ik_lin_control", text="Size")
#row = split.row()
#row.itemR(pchan, "ik_lin_weight", text="Weight", slider=True) #row.itemR(pchan, "ik_lin_weight", text="Weight", slider=True)
#row.active = pchan.ik_lin_control
class BONE_PT_iksolver_itasc(ConstraintButtonsPanel): class BONE_PT_iksolver_itasc(ConstraintButtonsPanel):
__label__ = "iTaSC parameters" __label__ = "iTaSC parameters"

@ -1417,10 +1417,22 @@ static IK_Scene* convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
switch (condata->type) { switch (condata->type) {
case CONSTRAINT_IK_COPYPOSE: case CONSTRAINT_IK_COPYPOSE:
controltype = 0; controltype = 0;
if ((condata->flag & CONSTRAINT_IK_ROT) && (condata->orientweight != 0.0)) if (condata->flag & CONSTRAINT_IK_ROT) {
controltype |= iTaSC::CopyPose::CTL_ROTATION; if (!(condata->flag & CONSTRAINT_IK_NO_ROT_X))
if ((condata->weight != 0.0)) controltype |= iTaSC::CopyPose::CTL_ROTATIONX;
controltype |= iTaSC::CopyPose::CTL_POSITION; if (!(condata->flag & CONSTRAINT_IK_NO_ROT_Y))
controltype |= iTaSC::CopyPose::CTL_ROTATIONY;
if (!(condata->flag & CONSTRAINT_IK_NO_ROT_Z))
controltype |= iTaSC::CopyPose::CTL_ROTATIONZ;
}
if (condata->flag & CONSTRAINT_IK_POS) {
if (!(condata->flag & CONSTRAINT_IK_NO_POS_X))
controltype |= iTaSC::CopyPose::CTL_POSITIONX;
if (!(condata->flag & CONSTRAINT_IK_NO_POS_Y))
controltype |= iTaSC::CopyPose::CTL_POSITIONY;
if (!(condata->flag & CONSTRAINT_IK_NO_POS_Z))
controltype |= iTaSC::CopyPose::CTL_POSITIONZ;
}
if (controltype) { if (controltype) {
iktarget->constraint = new iTaSC::CopyPose(controltype, controltype, bonelen); iktarget->constraint = new iTaSC::CopyPose(controltype, controltype, bonelen);
// set the gain // set the gain
@ -1432,6 +1444,9 @@ static IK_Scene* convert_tree(Scene *blscene, Object *ob, bPoseChannel *pchan)
iktarget->errorCallback = copypose_error; iktarget->errorCallback = copypose_error;
iktarget->controlType = controltype; iktarget->controlType = controltype;
// add the constraint // add the constraint
if (condata->flag & CONSTRAINT_IK_TARGETAXIS)
ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, iktarget->targetName, armname, "", ikscene->channels[iktarget->channel].tail);
else
ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, armname, iktarget->targetName, ikscene->channels[iktarget->channel].tail); ret = scene->addConstraintSet(iktarget->constraintName, iktarget->constraint, armname, iktarget->targetName, ikscene->channels[iktarget->channel].tail);
} }
break; break;

@ -502,6 +502,16 @@ typedef enum B_CONSTRAINTCHANNEL_FLAG {
#define CONSTRAINT_IK_POS 32 #define CONSTRAINT_IK_POS 32
#define CONSTRAINT_IK_SETANGLE 64 #define CONSTRAINT_IK_SETANGLE 64
#define CONSTRAINT_IK_GETANGLE 128 #define CONSTRAINT_IK_GETANGLE 128
/* limit axis */
#define CONSTRAINT_IK_NO_POS_X 256
#define CONSTRAINT_IK_NO_POS_Y 512
#define CONSTRAINT_IK_NO_POS_Z 1024
#define CONSTRAINT_IK_NO_ROT_X 2048
#define CONSTRAINT_IK_NO_ROT_Y 4096
#define CONSTRAINT_IK_NO_ROT_Z 8192
/* axis relative to target */
#define CONSTRAINT_IK_TARGETAXIS 16384
/* MinMax (floor) flags */ /* MinMax (floor) flags */
#define MINMAX_STICKY 0x01 #define MINMAX_STICKY 0x01

@ -87,6 +87,12 @@ EnumPropertyItem constraint_ik_type_items[] ={
{0, NULL, 0, NULL, NULL}, {0, NULL, 0, NULL, NULL},
}; };
EnumPropertyItem constraint_ik_axisref_items[] ={
{0, "BONE", 0, "Bone", ""},
{CONSTRAINT_IK_TARGETAXIS, "TARGET", 0, "Target", ""},
{0, NULL, 0, NULL, NULL},
};
#ifdef RNA_RUNTIME #ifdef RNA_RUNTIME
#include "BKE_action.h" #include "BKE_action.h"
@ -497,11 +503,52 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Use Tail", "Include bone's tail as last element in chain."); RNA_def_property_ui_text(prop, "Use Tail", "Include bone's tail as last element in chain.");
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, "axis_reference", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
RNA_def_property_enum_items(prop, constraint_ik_axisref_items);
RNA_def_property_ui_text(prop, "Axis Reference", "Constraint axis Lock options relative to Bone or Target reference");
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update");
prop= RNA_def_property(srna, "position", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_POS);
RNA_def_property_ui_text(prop, "Position", "Chain follows position of target.");
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_dependency_update");
prop= RNA_def_property(srna, "pos_lock_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_NO_POS_X);
RNA_def_property_ui_text(prop, "Lock X Pos", "Constraint position along X axis");
RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Constraint_dependency_update");
prop= RNA_def_property(srna, "pos_lock_y", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_NO_POS_Y);
RNA_def_property_ui_text(prop, "Lock Y Pos", "Constraint position along Y axis");
RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Constraint_dependency_update");
prop= RNA_def_property(srna, "pos_lock_z", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_NO_POS_Z);
RNA_def_property_ui_text(prop, "Lock Z Pos", "Constraint position along Z axis");
RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Constraint_dependency_update");
prop= RNA_def_property(srna, "rotation", PROP_BOOLEAN, PROP_NONE); prop= RNA_def_property(srna, "rotation", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_ROT); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_ROT);
RNA_def_property_ui_text(prop, "Rotation", "Chain follows rotation of target."); RNA_def_property_ui_text(prop, "Rotation", "Chain follows rotation of target.");
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, "rot_lock_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_NO_ROT_X);
RNA_def_property_ui_text(prop, "Lock X Rot", "Constraint rotation along X axis");
RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Constraint_dependency_update");
prop= RNA_def_property(srna, "rot_lock_y", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_NO_ROT_Y);
RNA_def_property_ui_text(prop, "Lock Y Rot", "Constraint rotation along Y axis");
RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Constraint_dependency_update");
prop= RNA_def_property(srna, "rot_lock_z", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", CONSTRAINT_IK_NO_ROT_Z);
RNA_def_property_ui_text(prop, "Lock Z Rot", "Constraint rotation along Z axis");
RNA_def_property_update(prop, NC_OBJECT|ND_POSE, "rna_Constraint_dependency_update");
prop= RNA_def_property(srna, "targetless", PROP_BOOLEAN, PROP_NONE); prop= RNA_def_property(srna, "targetless", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_AUTO); RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_IK_AUTO);
RNA_def_property_ui_text(prop, "Targetless", "Use targetless IK."); RNA_def_property_ui_text(prop, "Targetless", "Use targetless IK.");