=== [ #5094 ] TrackTo Constraint with an animatable "up" direction ===

Patch by Matthew Plough: This adds an option to the Track To constraint to use the target's Z axis for Up axis reference instead of the global Z axis.

Off by default for backward compat.
This commit is contained in:
Martin Poirier
2006-12-03 18:38:51 +00:00
parent 953cd28b67
commit 4a2eceff20
3 changed files with 101 additions and 2 deletions

View File

@@ -886,6 +886,93 @@ static void constraint_target_to_mat4 (Object *ob, const char *substring, float
}
}
/* stupid little cross product function, 0:x, 1:y, 2:z axes */
static int basis_cross(int n, int m)
{
if(n-m == 1) return 1;
if(n-m == -1) return -1;
if(n-m == 2) return -1;
if(n-m == -2) return 1;
else return 0;
}
static void vectomat(float *vec, float *target_up, short axis, short upflag, short flags, float m[][3])
{
float n[3];
float u[3]; /* vector specifying the up axis */
float proj[3];
float right[3];
float sign = 1;
float neg = -1;
int back_index, up_index, right_index;
VecCopyf(n, vec);
if(Normalise(n) == 0.0) {
n[0] = 0.0;
n[1] = 0.0;
n[2] = 1.0;
}
if(axis > 2) axis -= 3;
else VecMulf(n,-1);
/* n specifies the transformation of the track axis */
if(flags & TARGET_Z_UP) {
/* target Z axis is the global up axis */
u[0] = target_up[0];
u[1] = target_up[1];
u[2] = target_up[2];
}
else {
/* world Z axis is the global up axis */
u[0] = 0;
u[1] = 0;
u[2] = 1;
}
/* project the up vector onto the plane specified by n */
Projf(proj, u, n); /* first u onto n... */
VecSubf(proj, u, proj); /* then onto the plane */
/* proj specifies the transformation of the up axis */
if(Normalise(proj) == 0.0) { /* degenerate projection */
proj[0] = 0.0;
proj[1] = 1.0;
proj[2] = 0.0;
}
/* normalised cross product of n and proj specifies transformation of the right axis */
Crossf(right, proj, n);
Normalise(right);
if(axis != upflag) {
right_index = 3 - axis - upflag;
neg = (float) basis_cross(axis, upflag);
/* account for up direction, track direction */
m[right_index][0] = neg * right[0];
m[right_index][1] = neg * right[1];
m[right_index][2] = neg * right[2];
m[upflag][0] = proj[0];
m[upflag][1] = proj[1];
m[upflag][2] = proj[2];
m[axis][0] = n[0];
m[axis][1] = n[1];
m[axis][2] = n[2];
}
else {
m[0][0]= m[1][1]= m[2][2]= 1.0;
m[0][1]= m[0][2]= m[0][3]= 0.0;
m[1][0]= m[1][2]= m[1][3]= 0.0;
m[2][0]= m[2][1]= m[2][3]= 0.0;
}
}
/* called during solve_constraints */
/* also for make_parent, to find correct inverse of "follow path" */
/* warning, ownerdata is void... is not Bone anymore, but PoseChannel or Object */
@@ -1371,8 +1458,9 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
VecSubf(vec, ob->obmat[3], targetmat[3]);
quat= vectoquat(vec, (short)data->reserved1, (short)data->reserved2);
QuatToMat3(quat, totmat);
vectomat(vec, targetmat[2],
(short)data->reserved1, (short)data->reserved2,
data->flags, totmat);
Mat4CpyMat4(tmat, ob->obmat);

View File

@@ -77,6 +77,8 @@ typedef struct bTrackToConstraint{
Object *tar;
int reserved1; /* I'll be using reserved1 and reserved2 as Track and Up flags, not sure if that's what they were intented for anyway. Not sure either if it would create backward incompatibility if I were to rename them. - theeth*/
int reserved2;
int flags;
int pad;
char subtarget[32];
} bTrackToConstraint;
@@ -282,6 +284,9 @@ typedef struct bRigidBodyJointConstraint{
#define TRACK_nY 0x04
#define TRACK_nZ 0x05
/* bTrackToConstraint->flags */
#define TARGET_Z_UP 0x01
#define VOLUME_XZ 0x00
#define VOLUME_X 0x01
#define VOLUME_Z 0x02

View File

@@ -816,6 +816,12 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
strcpy (data->subtarget, "");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Align:", *xco+5, *yco-42, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
uiDefButBitI(block, TOG, 1, B_CONSTRAINT_TEST, "TargetZ", *xco+60, *yco-42, 50, 18, &data->flags, 0, 1, 0, 0, "Target Z axis, not world Z axis, will constrain up direction");
uiBlockEndAlign(block);
uiBlockBeginAlign(block);
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "To:", *xco+12, *yco-64, 25, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");