Rotation constraint update.
Small fix, but results are at least less frustrating now. It uses the "compatible euler" function from inserting key positions here, preventing euler values to be constrainted that differ weirdly. I've tried several other approaches to get a definite rotate constraint, but only constraining a single axes seems to me impossible magic still...
This commit is contained in:
@@ -1447,14 +1447,16 @@ static void do_local_constraint(bPoseChannel *pchan, bConstraint *con)
|
||||
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;
|
||||
float eul[3], eult[3], euln[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);
|
||||
VECCOPY(euln, eul);
|
||||
if(data->flag & ROTLIKE_X) euln[0]= fac*eult[0] + (1.0f-fac)*eul[0];
|
||||
if(data->flag & ROTLIKE_Y) euln[1]= fac*eult[1] + (1.0f-fac)*eul[1];
|
||||
if(data->flag & ROTLIKE_Z) euln[2]= fac*eult[2] + (1.0f-fac)*eul[2];
|
||||
compatible_eul(eul, euln);
|
||||
EulToQuat(euln, pchan->quat);
|
||||
}
|
||||
else {
|
||||
QuatInterpol(pchan->quat, pchan->quat, pchant->quat, con->enforce);
|
||||
|
||||
@@ -1137,6 +1137,7 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
|
||||
if(!(data->flag & ROTLIKE_X)) eul[0]= obeul[0];
|
||||
if(!(data->flag & ROTLIKE_Y)) eul[1]= obeul[1];
|
||||
if(!(data->flag & ROTLIKE_Z)) eul[2]= obeul[2];
|
||||
compatible_eul(eul, obeul);
|
||||
EulToMat3(eul, tmat);
|
||||
}
|
||||
|
||||
|
||||
@@ -155,6 +155,8 @@ Mat3ToEul(
|
||||
float *eul
|
||||
);
|
||||
|
||||
void compatible_eul(float *eul, float *oldrot);
|
||||
|
||||
/**
|
||||
* @section Quaternion arithmetic routines
|
||||
*/
|
||||
|
||||
@@ -2347,8 +2347,75 @@ void euler_rot(float *beul, float ang, char axis)
|
||||
|
||||
}
|
||||
|
||||
/* exported to transform.c */
|
||||
void compatible_eul(float *eul, float *oldrot)
|
||||
{
|
||||
float dx, dy, dz;
|
||||
|
||||
/* correct differences of about 360 degrees first */
|
||||
|
||||
dx= eul[0] - oldrot[0];
|
||||
dy= eul[1] - oldrot[1];
|
||||
dz= eul[2] - oldrot[2];
|
||||
|
||||
while( fabs(dx) > 5.1) {
|
||||
if(dx > 0.0) eul[0] -= 2.0*M_PI; else eul[0]+= 2.0*M_PI;
|
||||
dx= eul[0] - oldrot[0];
|
||||
}
|
||||
while( fabs(dy) > 5.1) {
|
||||
if(dy > 0.0) eul[1] -= 2.0*M_PI; else eul[1]+= 2.0*M_PI;
|
||||
dy= eul[1] - oldrot[1];
|
||||
}
|
||||
while( fabs(dz) > 5.1 ) {
|
||||
if(dz > 0.0) eul[2] -= 2.0*M_PI; else eul[2]+= 2.0*M_PI;
|
||||
dz= eul[2] - oldrot[2];
|
||||
}
|
||||
|
||||
/* is 1 of the axis rotations larger than 180 degrees and the other small? NO ELSE IF!! */
|
||||
if( fabs(dx) > 3.2 && fabs(dy)<1.6 && fabs(dz)<1.6 ) {
|
||||
if(dx > 0.0) eul[0] -= 2.0*M_PI; else eul[0]+= 2.0*M_PI;
|
||||
}
|
||||
if( fabs(dy) > 3.2 && fabs(dz)<1.6 && fabs(dx)<1.6 ) {
|
||||
if(dy > 0.0) eul[1] -= 2.0*M_PI; else eul[1]+= 2.0*M_PI;
|
||||
}
|
||||
if( fabs(dz) > 3.2 && fabs(dx)<1.6 && fabs(dy)<1.6 ) {
|
||||
if(dz > 0.0) eul[2] -= 2.0*M_PI; else eul[2]+= 2.0*M_PI;
|
||||
}
|
||||
|
||||
/* this return was there from ancient days... but why! probably because the code sucks :)
|
||||
*/
|
||||
return;
|
||||
|
||||
/* calc again */
|
||||
dx= eul[0] - oldrot[0];
|
||||
dy= eul[1] - oldrot[1];
|
||||
dz= eul[2] - oldrot[2];
|
||||
|
||||
/* special case, tested for x-z */
|
||||
|
||||
if( (fabs(dx) > 3.1 && fabs(dz) > 1.5 ) || ( fabs(dx) > 1.5 && fabs(dz) > 3.1 ) ) {
|
||||
if(dx > 0.0) eul[0] -= M_PI; else eul[0]+= M_PI;
|
||||
if(eul[1] > 0.0) eul[1]= M_PI - eul[1]; else eul[1]= -M_PI - eul[1];
|
||||
if(dz > 0.0) eul[2] -= M_PI; else eul[2]+= M_PI;
|
||||
|
||||
}
|
||||
else if( (fabs(dx) > 3.1 && fabs(dy) > 1.5 ) || ( fabs(dx) > 1.5 && fabs(dy) > 3.1 ) ) {
|
||||
if(dx > 0.0) eul[0] -= M_PI; else eul[0]+= M_PI;
|
||||
if(dy > 0.0) eul[1] -= M_PI; else eul[1]+= M_PI;
|
||||
if(eul[2] > 0.0) eul[2]= M_PI - eul[2]; else eul[2]= -M_PI - eul[2];
|
||||
}
|
||||
else if( (fabs(dy) > 3.1 && fabs(dz) > 1.5 ) || ( fabs(dy) > 1.5 && fabs(dz) > 3.1 ) ) {
|
||||
if(eul[0] > 0.0) eul[0]= M_PI - eul[0]; else eul[0]= -M_PI - eul[0];
|
||||
if(dy > 0.0) eul[1] -= M_PI; else eul[1]+= M_PI;
|
||||
if(dz > 0.0) eul[2] -= M_PI; else eul[2]+= M_PI;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ******************************************** */
|
||||
|
||||
void SizeToMat3( float *size, float mat[][3])
|
||||
{
|
||||
mat[0][0]= size[0];
|
||||
|
||||
@@ -74,7 +74,6 @@ void apply_object(void);
|
||||
|
||||
/* old transform */
|
||||
void apply_keyb_grid(float *val, float fac1, float fac2, float fac3, int invert);
|
||||
void compatible_eul(float *eul, float *oldrot);
|
||||
void headerprint(char *str);
|
||||
/* used for old game engine collision optimize */
|
||||
int cylinder_intersect_test(void);
|
||||
|
||||
@@ -3472,72 +3472,6 @@ void apply_keyb_grid(float *val, float fac1, float fac2, float fac3, int invert)
|
||||
}
|
||||
}
|
||||
|
||||
/* exported to transform.c */
|
||||
void compatible_eul(float *eul, float *oldrot)
|
||||
{
|
||||
float dx, dy, dz;
|
||||
|
||||
/* correct differences of about 360 degrees first */
|
||||
|
||||
dx= eul[0] - oldrot[0];
|
||||
dy= eul[1] - oldrot[1];
|
||||
dz= eul[2] - oldrot[2];
|
||||
|
||||
while( fabs(dx) > 5.1) {
|
||||
if(dx > 0.0) eul[0] -= 2.0*M_PI; else eul[0]+= 2.0*M_PI;
|
||||
dx= eul[0] - oldrot[0];
|
||||
}
|
||||
while( fabs(dy) > 5.1) {
|
||||
if(dy > 0.0) eul[1] -= 2.0*M_PI; else eul[1]+= 2.0*M_PI;
|
||||
dy= eul[1] - oldrot[1];
|
||||
}
|
||||
while( fabs(dz) > 5.1 ) {
|
||||
if(dz > 0.0) eul[2] -= 2.0*M_PI; else eul[2]+= 2.0*M_PI;
|
||||
dz= eul[2] - oldrot[2];
|
||||
}
|
||||
|
||||
/* is 1 of the axis rotations larger than 180 degrees and the other small? NO ELSE IF!! */
|
||||
if( fabs(dx) > 3.2 && fabs(dy)<1.6 && fabs(dz)<1.6 ) {
|
||||
if(dx > 0.0) eul[0] -= 2.0*M_PI; else eul[0]+= 2.0*M_PI;
|
||||
}
|
||||
if( fabs(dy) > 3.2 && fabs(dz)<1.6 && fabs(dx)<1.6 ) {
|
||||
if(dy > 0.0) eul[1] -= 2.0*M_PI; else eul[1]+= 2.0*M_PI;
|
||||
}
|
||||
if( fabs(dz) > 3.2 && fabs(dx)<1.6 && fabs(dy)<1.6 ) {
|
||||
if(dz > 0.0) eul[2] -= 2.0*M_PI; else eul[2]+= 2.0*M_PI;
|
||||
}
|
||||
|
||||
/* this return was there from ancient days... but why! probably because the code sucks :)
|
||||
*/
|
||||
return;
|
||||
|
||||
/* calc again */
|
||||
dx= eul[0] - oldrot[0];
|
||||
dy= eul[1] - oldrot[1];
|
||||
dz= eul[2] - oldrot[2];
|
||||
|
||||
/* special case, tested for x-z */
|
||||
|
||||
if( (fabs(dx) > 3.1 && fabs(dz) > 1.5 ) || ( fabs(dx) > 1.5 && fabs(dz) > 3.1 ) ) {
|
||||
if(dx > 0.0) eul[0] -= M_PI; else eul[0]+= M_PI;
|
||||
if(eul[1] > 0.0) eul[1]= M_PI - eul[1]; else eul[1]= -M_PI - eul[1];
|
||||
if(dz > 0.0) eul[2] -= M_PI; else eul[2]+= M_PI;
|
||||
|
||||
}
|
||||
else if( (fabs(dx) > 3.1 && fabs(dy) > 1.5 ) || ( fabs(dx) > 1.5 && fabs(dy) > 3.1 ) ) {
|
||||
if(dx > 0.0) eul[0] -= M_PI; else eul[0]+= M_PI;
|
||||
if(dy > 0.0) eul[1] -= M_PI; else eul[1]+= M_PI;
|
||||
if(eul[2] > 0.0) eul[2]= M_PI - eul[2]; else eul[2]= -M_PI - eul[2];
|
||||
}
|
||||
else if( (fabs(dy) > 3.1 && fabs(dz) > 1.5 ) || ( fabs(dy) > 1.5 && fabs(dz) > 3.1 ) ) {
|
||||
if(eul[0] > 0.0) eul[0]= M_PI - eul[0]; else eul[0]= -M_PI - eul[0];
|
||||
if(dy > 0.0) eul[1] -= M_PI; else eul[1]+= M_PI;
|
||||
if(dz > 0.0) eul[2] -= M_PI; else eul[2]+= M_PI;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int cylinder_intersect_test(void)
|
||||
{
|
||||
EditMesh *em = G.editMesh;
|
||||
|
||||
Reference in New Issue
Block a user