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:
authorCampbell Barton <ideasman42@gmail.com>2010-12-07 04:56:32 +0300
committerCampbell Barton <ideasman42@gmail.com>2010-12-07 04:56:32 +0300
commit48614fbc2af024d613845b03d632e544f8127261 (patch)
tree41442fc6f5fe2b4ccef4f627429f740774abcdf9 /source/blender/blenlib/intern/math_rotation.c
parentfe0f78a66978f52eac94199baffc577cbf7c1123 (diff)
Added an assert() check for normalized quats which exposed a number of bugs where normalized quat was incorrectly assumed.
This would have made bug #25003 very simple to find. - Objects had their quats normalized when calculating their matrix, this is inconstant with pose bones and isn't useful for animation. Also it wasn't normalizing the delta rotation so these would give bad rotations. - Converting between rotation modes BKE_rotMode_change_values() assumed normal length quat. changing quat to euler rotation for eg could change the bone. - Clear rotation and transform were not normalizing the quat when 4d loc was disabled on quat rotation, corrected and also made it so the quat scale is restored after conversion so animations curves dont jump. There is 1 case in mat3_to_quat_is_ok() where quat_to_mat3 on an unnormalized quat is needed, for this I had to add an ugly static function quat_to_mat3_no_assert(), but overall its worthwhile IMHO to be able to find incorrect use of rotation conversion.
Diffstat (limited to 'source/blender/blenlib/intern/math_rotation.c')
-rw-r--r--source/blender/blenlib/intern/math_rotation.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c
index 5f6f7ac54d9..a3e57605ad4 100644
--- a/source/blender/blenlib/intern/math_rotation.c
+++ b/source/blender/blenlib/intern/math_rotation.c
@@ -31,6 +31,9 @@
/******************************** Quaternions ********************************/
+/* used to test is a quat is not normalized */
+#define QUAT_EPSILON 0.00001
+
void unit_qt(float *q)
{
q[0]= 1.0f;
@@ -144,7 +147,8 @@ void mul_fac_qt_fl(float *q, const float fac)
mul_v3_fl(q+1, si);
}
-void quat_to_mat3(float m[][3], const float q[4])
+/* skip error check, currently only needed by mat3_to_quat_is_ok */
+static void quat_to_mat3_no_assert(float m[][3], const float q[4])
{
double q0, q1, q2, q3, qda,qdb,qdc,qaa,qab,qac,qbb,qbc,qcc;
@@ -176,10 +180,23 @@ void quat_to_mat3(float m[][3], const float q[4])
m[2][2]= (float)(1.0-qaa-qbb);
}
+
+void quat_to_mat3(float m[][3], const float q[4])
+{
+ /* throw an error if the quat isn't normalized */
+ float f;
+ assert((f=dot_qtqt(q, q))==0.0 || (fabs(f-1.0) < QUAT_EPSILON));
+
+ quat_to_mat3_no_assert(m, q);
+}
+
void quat_to_mat4(float m[][4], const float q[4])
{
double q0, q1, q2, q3, qda,qdb,qdc,qaa,qab,qac,qbb,qbc,qcc;
+ /* throw an error if the quat isn't normalized */
+ assert((q0=dot_qtqt(q, q))==0.0 || (fabs(q0-1.0) < QUAT_EPSILON));
+
q0= M_SQRT2 * q[0];
q1= M_SQRT2 * q[1];
q2= M_SQRT2 * q[2];
@@ -300,7 +317,7 @@ void mat3_to_quat_is_ok(float q[4], float wmat[3][3])
q1[3]= -nor[2]*si;
/* rotate back x-axis from mat, using inverse q1 */
- quat_to_mat3( matr,q1);
+ quat_to_mat3_no_assert( matr,q1);
invert_m3_m3(matn, matr);
mul_m3_v3(matn, mat[0]);
@@ -318,7 +335,7 @@ void mat3_to_quat_is_ok(float q[4], float wmat[3][3])
}
-void normalize_qt(float *q)
+float normalize_qt(float *q)
{
float len;
@@ -330,6 +347,14 @@ void normalize_qt(float *q)
q[1]= 1.0f;
q[0]= q[2]= q[3]= 0.0f;
}
+
+ return len;
+}
+
+float normalize_qt_qt(float r[4], const float q[4])
+{
+ copy_qt_qt(r, q);
+ return normalize_qt(r);
}
/* note: expects vectors to be normalized */
@@ -619,7 +644,10 @@ void axis_angle_to_quat(float q[4], const float axis[3], float angle)
void quat_to_axis_angle(float axis[3], float *angle, const float q[4])
{
float ha, si;
-
+
+ /* throw an error if the quat isn't normalized */
+ assert((ha=dot_qtqt(q, q))==0.0 || (fabs(ha-1.0) < QUAT_EPSILON));
+
/* calculate angle/2, and sin(angle/2) */
ha= (float)acos(q[0]);
si= (float)sin(ha);
@@ -925,7 +953,7 @@ void mat4_to_eul(float *eul,float tmat[][4])
void quat_to_eul(float *eul, const float quat[4])
{
float mat[3][3];
-
+
quat_to_mat3(mat,quat);
mat3_to_eul(eul,mat);
}