Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2009-09-12 09:06:28 +0400
committerJoshua Leung <aligorith@gmail.com>2009-09-12 09:06:28 +0400
commit83074d0b3758c1b2d2811974726d4dd33f3034da (patch)
tree6ef4208631de9435d71cdd29637ee9ca329f6e68
parentf0eb02a36b5a04d18a1a587b1e36419daa6a6f23 (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
-rw-r--r--source/blender/blenkernel/intern/armature.c2
-rw-r--r--source/blender/blenlib/BLI_arithb.h21
-rw-r--r--source/blender/blenlib/intern/arithb.c89
-rw-r--r--source/blender/editors/animation/keyingsets.c2
-rw-r--r--source/blender/editors/armature/editarmature.c1
-rw-r--r--source/blender/editors/armature/poseobject.c29
-rw-r--r--source/blender/editors/transform/transform.c12
-rw-r--r--source/blender/editors/transform/transform_conversions.c4
-rw-r--r--source/blender/makesrna/intern/rna_pose.c36
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 */