New Constraint option for Pose: "Local" Copy Location/Rotation.

The locality is restricted to action or user-transform only. Or as it goes
in the code now: by setting a constraint local, it executes the constraint
before it calculates the influence of Action or user transforms.

ALso note that this works in Evil Eulerians. Meaning that when you only
want to copy the X,Y or Z compenent of a euler, it can give unpredictable
results when the other euler values are set, this because euler axis
rotations work on top of each other.
This commit is contained in:
Ton Roosendaal
2005-11-16 14:32:57 +00:00
parent b474f95c84
commit 8c2c8bbfaa
5 changed files with 69 additions and 4 deletions

View File

@@ -1401,6 +1401,52 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3]) // nr = t
pchan->flag |= POSE_DONE;
}
static void do_local_constraint(bPoseChannel *pchan, bConstraint *con)
{
switch(con->type) {
case CONSTRAINT_TYPE_LOCLIKE:
{
bLocateLikeConstraint *data= con->data;
if(data->tar && data->subtarget[0]) {
bPoseChannel *pchant= get_pose_channel(data->tar->pose, data->subtarget);
if(pchant) {
if (data->flag & LOCLIKE_X)
pchan->loc[0]= pchant->loc[0];
if (data->flag & LOCLIKE_Y)
pchan->loc[1]= pchant->loc[1];
if (data->flag & LOCLIKE_Z)
pchan->loc[2]= pchant->loc[2];
}
}
}
break;
case CONSTRAINT_TYPE_ROTLIKE:
{
bRotateLikeConstraint *data= con->data;
if(data->tar && data->subtarget[0]) {
bPoseChannel *pchant= get_pose_channel(data->tar->pose, data->subtarget);
if(pchant) {
if(data->flag != (ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z)) {
float eul[3], eult[3], fac= con->enforce;
QuatToEul(pchan->quat, eul);
QuatToEul(pchant->quat, eult);
if(data->flag & ROTLIKE_X) eul[0]= fac*eult[0] + (1.0f-fac)*eul[0];
if(data->flag & ROTLIKE_Y) eul[1]= fac*eult[1] + (1.0f-fac)*eul[1];
if(data->flag & ROTLIKE_Z) eul[2]= fac*eult[2] + (1.0f-fac)*eul[2];
EulToQuat(eul, pchan->quat);
}
else {
QuatInterpol(pchan->quat, pchan->quat, pchant->quat, con->enforce);
}
}
}
}
}
}
/* The main armature solver, does all constraints excluding IK */
/* pchan is validated, as having bone and parent pointer */
static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime)
@@ -1414,6 +1460,15 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime)
parbone= bone->parent;
parchan= pchan->parent;
/* Do local constraints, these only work on the channel data (loc rot size) */
if(pchan->constraints.first) {
bConstraint *con;
for(con=pchan->constraints.first; con; con= con->next) {
if(con->flag & CONSTRAINT_LOCAL)
do_local_constraint(pchan, con);
}
}
/* this gives a chan_mat with actions (ipos) results */
chan_calc_mat(pchan);

View File

@@ -1016,6 +1016,7 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
/* only called during solve_constraints */
/* bone constraints create a fake object to work on, then ob is a workob */
/* if ownerdata is set, it's the posechannel */
void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, void *ownerdata, float targetmat[][4])
{
float M_oldmat[4][4];

View File

@@ -1574,7 +1574,9 @@ void solve_constraints (Object *ob, short obtype, void *obdata, float ctime)
if (con->type==CONSTRAINT_TYPE_KINEMATIC) continue;
// and this we can skip completely
if (con->flag & CONSTRAINT_DISABLE) continue;
// local constraints are handled in armature.c only
if (con->flag & CONSTRAINT_LOCAL) continue;
/* Clear accumulators if necessary*/
if (clear) {
clear= 0;

View File

@@ -191,6 +191,9 @@ typedef struct bStretchToConstraint{
/* flags 0x2 and 0x8 were used in past, skip this */
/* to indicate which Ipo should be shown, maybe for 3d access later too */
#define CONSTRAINT_ACTIVE 0x10
/* only for Pose, evaluates constraints in posechannel local space */
#define CONSTRAINT_LOCAL 0x20
/* bConstraintChannel.flag */
#define CONSTRAINT_CHANNEL_SELECT 0x01

View File

@@ -638,6 +638,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* Draw XYZ toggles */
uiBlockBeginAlign(block);
if (arm)
uiDefButBitS(block, TOG, CONSTRAINT_LOCAL, B_CONSTRAINT_TEST, "Local", *xco+((width/2)-98), *yco-64, 50, 18, &con->flag, 0, 24, 0, 0, "Work on a Pose's local transform");
but=uiDefButBitI(block, TOG, LOCLIKE_X, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
but=uiDefButBitI(block, TOG, LOCLIKE_Y, B_CONSTRAINT_TEST, "Y", *xco+((width/2)-16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
but=uiDefButBitI(block, TOG, LOCLIKE_Z, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
@@ -672,9 +674,11 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
/* Draw XYZ toggles */
uiBlockBeginAlign(block);
but=uiDefButBitI(block, TOG, ROTLIKE_X, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
but=uiDefButBitI(block, TOG, ROTLIKE_Y, B_CONSTRAINT_TEST, "Y", *xco+((width/2)-16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
but=uiDefButBitI(block, TOG, ROTLIKE_Z, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
if (arm)
uiDefButBitS(block, TOG, CONSTRAINT_LOCAL, B_CONSTRAINT_TEST, "Local", *xco+((width/2)-98), *yco-64, 50, 18, &con->flag, 0, 24, 0, 0, "Work on a Pose's local transform");
uiDefButBitI(block, TOG, ROTLIKE_X, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
uiDefButBitI(block, TOG, ROTLIKE_Y, B_CONSTRAINT_TEST, "Y", *xco+((width/2)-16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
uiDefButBitI(block, TOG, ROTLIKE_Z, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
uiBlockEndAlign(block);
}
break;