diff options
author | Joshua Leung <aligorith@gmail.com> | 2009-09-12 09:06:28 +0400 |
---|---|---|
committer | Joshua Leung <aligorith@gmail.com> | 2009-09-12 09:06:28 +0400 |
commit | 83074d0b3758c1b2d2811974726d4dd33f3034da (patch) | |
tree | 6ef4208631de9435d71cdd29637ee9ca329f6e68 /source | |
parent | f0eb02a36b5a04d18a1a587b1e36419daa6a6f23 (diff) |
2.5 - More work on Axis-Angle Rotations
* Added a few new methods for axis-angle conversions, and used these instead of manually performing those steps elsewhere
* Axis-angles to other representations now get their axes normalised to make sure that odd scaling doesn't occur.
* Made a few more tools work with axis-angles properly
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_arithb.h | 21 | ||||
-rw-r--r-- | source/blender/blenlib/intern/arithb.c | 89 | ||||
-rw-r--r-- | source/blender/editors/animation/keyingsets.c | 2 | ||||
-rw-r--r-- | source/blender/editors/armature/editarmature.c | 1 | ||||
-rw-r--r-- | source/blender/editors/armature/poseobject.c | 29 | ||||
-rw-r--r-- | source/blender/editors/transform/transform.c | 12 | ||||
-rw-r--r-- | source/blender/editors/transform/transform_conversions.c | 4 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_pose.c | 36 |
9 files changed, 149 insertions, 47 deletions
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 0c18817f8be..c880925aa94 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1993,7 +1993,7 @@ void chan_calc_mat(bPoseChannel *chan) } else if (chan->rotmode == PCHAN_ROT_AXISANGLE) { /* axis-angle - stored in quaternion data, but not really that great for 3D-changing orientations */ - VecRotToMat3(&chan->quat[1], chan->quat[0], rmat); + AxisAngleToMat3(&chan->quat[1], chan->quat[0], rmat); } else { /* quats are normalised before use to eliminate scaling issues */ diff --git a/source/blender/blenlib/BLI_arithb.h b/source/blender/blenlib/BLI_arithb.h index 71604758b80..8eb4d5972e3 100644 --- a/source/blender/blenlib/BLI_arithb.h +++ b/source/blender/blenlib/BLI_arithb.h @@ -342,8 +342,6 @@ void Mat4AddMat4(float m1[][4], float m2[][4], float m3[][4]); void VecUpMat3old(float *vec, float mat[][3], short axis); void VecUpMat3(float *vec, float mat[][3], short axis); -void VecRotToMat3(float *vec, float phi, float mat[][3]); -void VecRotToMat4(float *vec, float phi, float mat[][4]); void VecCopyf(float *v1, float *v2); int VecLen(int *v1, int *v2); @@ -376,10 +374,23 @@ void Vec2Subf(float *v, float *v1, float *v2); void Vec2Copyf(float *v1, float *v2); void Vec2Lerpf(float *target, float *a, float *b, float t); -void AxisAngleToQuat(float *q, float *axis, float angle); -void QuatToAxisAngle(float *q, float *axis, float *angle); +void AxisAngleToQuat(float q[4], float axis[3], float angle); +void QuatToAxisAngle(float q[4], float axis[3], float *angle); +void AxisAngleToEulO(float axis[3], float angle, float eul[3], short order); +void EulOToAxisAngle(float eul[3], short order, float axis[3], float *angle); +void AxisAngleToMat3(float axis[3], float angle, float mat[3][3]); +void AxisAngleToMat4(float axis[3], float angle, float mat[4][4]); +void Mat3ToAxisAngle(float mat[3][3], float axis[3], float *angle); +void Mat4ToAxisAngle(float mat[4][4], float axis[3], float *angle); + +void Mat3ToVecRot(float mat[3][3], float axis[3], float *angle); +void Mat4ToVecRot(float mat[4][4], float axis[3], float *angle); +void VecRotToMat3(float *vec, float phi, float mat[][3]); +void VecRotToMat4(float *vec, float phi, float mat[][4]); + void RotationBetweenVectorsToQuat(float *q, float v1[3], float v2[3]); void vectoquat(float *vec, short axis, short upflag, float *q); +void Mat3ToQuat_is_ok(float wmat[][3], float *q); void VecReflect(float *out, float *v1, float *v2); void VecBisect3(float *v, float *v1, float *v2, float *v3); @@ -460,8 +471,6 @@ void VecStar(float mat[][3],float *vec); short EenheidsMat(float mat[][3]); -void Mat3ToQuat_is_ok(float wmat[][3], float *q); - void i_ortho(float left, float right, float bottom, float top, float nearClip, float farClip, float matrix[][4]); void i_polarview(float dist, float azimuth, float incidence, float twist, float Vm[][4]); void i_translate(float Tx, float Ty, float Tz, float mat[][4]); diff --git a/source/blender/blenlib/intern/arithb.c b/source/blender/blenlib/intern/arithb.c index 96056ba7783..1839380f953 100644 --- a/source/blender/blenlib/intern/arithb.c +++ b/source/blender/blenlib/intern/arithb.c @@ -3278,7 +3278,7 @@ void Mat3ToCompatibleEul(float mat[][3], float *eul, float *oldrot) /* ************ AXIS ANGLE *************** */ /* Axis angle to Quaternions */ -void AxisAngleToQuat(float *q, float *axis, float angle) +void AxisAngleToQuat(float q[4], float axis[3], float angle) { float nor[3]; float si; @@ -3315,6 +3315,90 @@ void QuatToAxisAngle(float q[4], float axis[3], float *angle) axis[2]= q[3] / si; } +/* Axis Angle to Euler Rotation */ +void AxisAngleToEulO(float axis[3], float angle, float eul[3], short order) +{ + float q[4]; + + /* use quaternions as intermediate representation for now... */ + AxisAngleToQuat(q, axis, angle); + QuatToEulO(q, eul, order); +} + +/* Euler Rotation to Axis Angle */ +void EulOToAxisAngle(float eul[3], short order, float axis[3], float *angle) +{ + float q[4]; + + /* use quaternions as intermediate representation for now... */ + EulOToQuat(eul, order, q); + QuatToAxisAngle(q, axis, angle); +} + +/* axis angle to 3x3 matrix - safer version (normalisation of axis performed) */ +void AxisAngleToMat3(float axis[3], float angle, float mat[3][3]) +{ + float nor[3]; + + /* normalise the axis first (to remove unwanted scaling) */ + VecCopyf(nor, axis); + Normalize(nor); + + /* now convert this to a 3x3 matrix */ + VecRotToMat3(nor, angle, mat); +} + +/* axis angle to 4x4 matrix - safer version (normalisation of axis performed) */ +void AxisAngleToMat4(float axis[3], float angle, float mat[4][4]) +{ + float nor[3]; + + /* normalise the axis first (to remove unwanted scaling) */ + VecCopyf(nor, axis); + Normalize(nor); + + /* now convert this to a 4x4 matrix */ + VecRotToMat4(nor, angle, mat); +} + +/* 3x3 matrix to axis angle (alias around the other call) */ +void Mat3ToAxisAngle(float mat[3][3], float axis[3], float *angle) +{ + /* note different order of calling args... */ + Mat3ToVecRot(axis, angle, mat); +} + +/* 4x4 matrix to axis angle (alias around the other call) */ +void Mat4ToAxisAngle(float mat[4][4], float axis[3], float *angle) +{ + /* note different order of calling args... */ + Mat4ToVecRot(axis, angle, mat); +} + +/* ************ AXIS ANGLE (unchecked) *************** */ + +/* 3x3 matrix to axis angle */ +void Mat3ToVecRot(float mat[3][3], float axis[3], float *angle) +{ + float q[4]; + + /* use quaternions as intermediate representation */ + // TODO: it would be nicer to go straight there... + Mat3ToQuat(mat, q); + QuatToAxisAngle(q, axis, angle); +} + +/* 4x4 matrix to axis angle */ +void Mat4ToVecRot(float mat[4][4], float axis[3], float *angle) +{ + float q[4]; + + /* use quaternions as intermediate representation */ + // TODO: it would be nicer to go straight there... + Mat4ToQuat(mat, q); + QuatToAxisAngle(q, axis, angle); +} + /* axis angle to 3x3 matrix */ void VecRotToMat3(float *vec, float phi, float mat[][3]) { @@ -3339,7 +3423,6 @@ void VecRotToMat3(float *vec, float phi, float mat[][3]) mat[2][0]= vz*vx*(1.0f-co)+vy*si; mat[2][1]= vy*vz*(1.0f-co)-vx*si; mat[2][2]= vz2+co*(1.0f-vz2); - } /* axis angle to 4x4 matrix */ @@ -3374,6 +3457,8 @@ void VecRotToQuat(float *vec, float phi, float *quat) } } +/* ************ VECTORS *************** */ + /* Returns a vector bisecting the angle at v2 formed by v1, v2 and v3 */ void VecBisect3(float *out, float *v1, float *v2, float *v3) { diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index 2639d49b5be..60efcce4e73 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -1177,7 +1177,7 @@ int modify_keyframes (bContext *C, ListBase *dsources, bAction *act, KeyingSet * /* if this path is exactly "rotation", and the rotation mode is set to eulers, * use "euler_rotation" instead so that rotations will be keyed correctly */ - if (strcmp(ksp->rna_path, "rotation")==0 && (cks->pchan->rotmode)) + if (strcmp(ksp->rna_path, "rotation")==0 && (cks->pchan->rotmode > 0)) BLI_dynstr_append(pathds, "euler_rotation"); else BLI_dynstr_append(pathds, ksp->rna_path); diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 3b6c9e9d13d..e2293b65878 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -4865,6 +4865,7 @@ static int pose_clear_rot_exec(bContext *C, wmOperator *op) eul[0]= eul[1]= eul[2]= 0.0f; + // TODO: for 4 channel rotations, we need special flags for those too... if (pchan->protectflag & OB_LOCK_ROTX) eul[0]= oldeul[0]; if (pchan->protectflag & OB_LOCK_ROTY) diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 9a404e24e12..b473b9ee226 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -1009,12 +1009,25 @@ static int pose_paste_exec (bContext *C, wmOperator *op) } } else if (pchan->rotmode > 0) { - /* quat to euler */ - QuatToEulO(chan->quat, pchan->eul, pchan->rotmode); + /* quat/axis-angle to euler */ + if (chan->rotmode == PCHAN_ROT_AXISANGLE) + AxisAngleToEulO(&chan->quat[1], chan->quat[0], pchan->eul, pchan->rotmode); + else + QuatToEulO(chan->quat, pchan->eul, pchan->rotmode); + } + else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + /* quat/euler to axis angle */ + if (chan->rotmode > 0) + EulOToAxisAngle(chan->eul, chan->rotmode, &pchan->quat[1], &pchan->quat[0]); + else + QuatToAxisAngle(chan->quat, &pchan->quat[1], &pchan->quat[0]); } else { - /* euler to quat */ - EulOToQuat(chan->eul, chan->rotmode, pchan->quat); + /* euler/axis-angle to quat */ + if (chan->rotmode > 0) + EulOToQuat(chan->eul, chan->rotmode, pchan->quat); + else + AxisAngleToQuat(pchan->quat, &chan->quat[1], chan->quat[0]); } /* paste flipped pose? */ @@ -1026,6 +1039,14 @@ static int pose_paste_exec (bContext *C, wmOperator *op) pchan->eul[1] *= -1; pchan->eul[2] *= -1; } + else if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { + float eul[3]; + + AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], eul, EULER_ORDER_DEFAULT); + eul[1]*= -1; + eul[2]*= -1; + EulOToAxisAngle(eul, EULER_ORDER_DEFAULT, &pchan->quat[1], &pchan->quat[0]); + } else { float eul[3]; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 6405e87c4c0..467f5c59e3d 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1614,7 +1614,8 @@ static void protectedQuaternionBits(short protectflag, float *quat, float *oldqu { /* quaternions get limited with euler... */ /* this function only does the delta rotation */ - + + // FIXME: need special checks for quality here... if(protectflag) { float eul[3], oldeul[3], quat1[4]; @@ -2686,12 +2687,13 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short QuatMul(td->ext->quat, quat, iquat); - /* this function works on end result */ - protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); - /* make temp copy (since stored in same place) */ - QuatCopy(quat, td->ext->quat); + QuatCopy(quat, td->ext->quat); // this is just a 4d vector copying function QuatToAxisAngle(quat, &td->ext->quat[1], &td->ext->quat[0]); + + /* this function works on end result */ + // TODO: we really need a specialised version of this for axis-angle that doesn't try to do quats... + protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); } else { float eulmat[3][3]; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index e0d058f160f..6386c0d4eb7 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -509,6 +509,8 @@ static short apply_targetless_ik(Object *ob) /* rotation */ if (parchan->rotmode > 0) Mat3ToEulO(rmat3, parchan->eul, parchan->rotmode); + else if (parchan->rotmode == PCHAN_ROT_AXISANGLE) + Mat3ToAxisAngle(rmat3, &parchan->quat[1], &parchan->quat[0]); else Mat3ToQuat(rmat3, parchan->quat); @@ -517,6 +519,8 @@ static short apply_targetless_ik(Object *ob) if (data->flag & CONSTRAINT_IK_STRETCH) { if (parchan->rotmode > 0) EulOToMat3(parchan->eul, parchan->rotmode, qrmat); + else if (parchan->rotmode == PCHAN_ROT_AXISANGLE) + AxisAngleToMat3(&parchan->quat[1], parchan->quat[0], qrmat); else QuatToMat3(parchan->quat, qrmat); diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 0a88b084307..d143c94ebb1 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -115,14 +115,9 @@ static void rna_PoseChannel_euler_rotation_get(PointerRNA *ptr, float *value) { bPoseChannel *pchan= ptr->data; - if(pchan->rotmode == PCHAN_ROT_AXISANGLE) { - float m[3][3]; - - /* go through a 3x3 matrix */ - VecRotToMat3(&pchan->quat[1], pchan->quat[0], m); - Mat3ToEul(m, value); - } - else if(pchan->rotmode == PCHAN_ROT_QUAT) /* default XYZ eulers when using axis-angle... */ + if(pchan->rotmode == PCHAN_ROT_AXISANGLE) /* default XYZ eulers */ + AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], value, EULER_ORDER_DEFAULT); + else if(pchan->rotmode == PCHAN_ROT_QUAT) /* default XYZ eulers */ QuatToEul(pchan->quat, value); else VECCOPY(value, pchan->eul); @@ -133,14 +128,9 @@ static void rna_PoseChannel_euler_rotation_set(PointerRNA *ptr, const float *val { bPoseChannel *pchan= ptr->data; - if(pchan->rotmode == PCHAN_ROT_AXISANGLE) { /* default XYZ eulers when using axis-angle... */ - float q[4]; - - /* convert to temp quat, then to axis angle (since stored in same var) */ - EulToQuat((float *)value, q); - QuatToAxisAngle(q, &pchan->quat[1], &pchan->quat[0]); - } - else if(pchan->rotmode == PCHAN_ROT_QUAT) /* default XYZ eulers when using quats... */ + if(pchan->rotmode == PCHAN_ROT_AXISANGLE) /* default XYZ eulers */ + EulOToAxisAngle((float *)value, EULER_ORDER_DEFAULT, &pchan->quat[1], &pchan->quat[0]); + else if(pchan->rotmode == PCHAN_ROT_QUAT) /* default XYZ eulers */ EulToQuat((float*)value, pchan->quat); else VECCOPY(pchan->eul, value); @@ -177,13 +167,7 @@ static void rna_PoseChannel_rotation_mode_set(PointerRNA *ptr, int value) if (value > 0) { /* to euler */ if (pchan->rotmode == PCHAN_ROT_AXISANGLE) { /* axis-angle to euler */ - float m[3][3]; - - /* convert to 3x3 matrix, then to euler - * - axis angle is stored in quats - */ - VecRotToMat3(&pchan->quat[1], pchan->quat[0], m); - Mat3ToEulO(m, pchan->eul, value); + AxisAngleToEulO(&pchan->quat[1], pchan->quat[0], pchan->eul, value); } else if (pchan->rotmode == PCHAN_ROT_QUAT) { /* quat to euler */ @@ -209,11 +193,7 @@ static void rna_PoseChannel_rotation_mode_set(PointerRNA *ptr, int value) else { /* to axis-angle */ if (pchan->rotmode > 0) { /* euler to axis angle */ - float q[4]; - - /* convert to temp quat, then to axis angle (since stored in same var) */ - EulOToQuat(pchan->eul, pchan->rotmode, q); - QuatToAxisAngle(q, &pchan->quat[1], &pchan->quat[0]); + EulOToAxisAngle(pchan->eul, pchan->rotmode, &pchan->quat[1], &pchan->quat[0]); } else if (pchan->rotmode == PCHAN_ROT_QUAT) { /* quat to axis angle */ |