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:
-rw-r--r--source/blender/blenkernel/intern/armature.c63
1 files changed, 30 insertions, 33 deletions
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index fb885527cce..b5d3a04acb8 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -2156,50 +2156,50 @@ void mat3_vec_to_roll(const float mat[3][3], const float vec[3], float *r_roll)
*/
void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_mat[3][3])
{
-#define THETA_THRESHOLD_NEGY 1.0e-9f
-#define THETA_THRESHOLD_NEGY_CLOSE 1.0e-5f
+ const float THETA_SAFE = 1.0e-5f; /* theta above this value are always safe to use. */
+ const float THETA_CRITICAL = 1.0e-9f; /* above this is safe under certain conditions. */
- float theta;
+ const float x = nor[0];
+ const float y = nor[1];
+ const float z = nor[2];
+
+ const float theta = 1.0f + y;
+ const float theta_alt = x * x + z * z;
float rMatrix[3][3], bMatrix[3][3];
BLI_ASSERT_UNIT_V3(nor);
- theta = 1.0f + nor[1];
-
- /* With old algo, 1.0e-13f caused T23954 and T31333, 1.0e-6f caused T27675 and T30438,
- * so using 1.0e-9f as best compromise.
- *
- * New algo is supposed much more precise, since less complex computations are performed,
- * but it uses two different threshold values...
- *
- * Note: When theta is close to zero, we have to check we do have non-null X/Z components as well
- * (due to float precision errors, we can have nor = (0.0, 0.99999994, 0.0)...).
+ /* When theta is close to zero (nor is aligned close to negative Y Axis),
+ * we have to check we do have non-null X/Z components as well.
+ * Also, due to float precision errors, nor can be (0.0, -0.99999994, 0.0) which results
+ * in theta being close to zero. This will cause problems when theta is used as divisor.
*/
- if (theta > THETA_THRESHOLD_NEGY_CLOSE || ((nor[0] || nor[2]) && theta > THETA_THRESHOLD_NEGY)) {
- /* nor is *not* -Y.
+ if (theta > THETA_SAFE || ((x || z) && theta > THETA_CRITICAL)) {
+ /* nor is *not* aligned to negative Y-axis (0,-1,0).
* We got these values for free... so be happy with it... ;)
*/
- bMatrix[0][1] = -nor[0];
- bMatrix[1][0] = nor[0];
- bMatrix[1][1] = nor[1];
- bMatrix[1][2] = nor[2];
- bMatrix[2][1] = -nor[2];
- if (theta > THETA_THRESHOLD_NEGY_CLOSE) {
- /* If nor is far enough from -Y, apply the general case. */
- bMatrix[0][0] = 1 - nor[0] * nor[0] / theta;
- bMatrix[2][2] = 1 - nor[2] * nor[2] / theta;
- bMatrix[2][0] = bMatrix[0][2] = -nor[0] * nor[2] / theta;
+
+ bMatrix[0][1] = -x;
+ bMatrix[1][0] = x;
+ bMatrix[1][1] = y;
+ bMatrix[1][2] = z;
+ bMatrix[2][1] = -z;
+
+ if (theta > THETA_SAFE) {
+ /* nor differs significantly from negative Y axis (0,-1,0): apply the general case. */
+ bMatrix[0][0] = 1 - x * x / theta;
+ bMatrix[2][2] = 1 - z * z / theta;
+ bMatrix[2][0] = bMatrix[0][2] = -x * z / theta;
}
else {
- /* If nor is too close to -Y, apply the special case. */
- theta = nor[0] * nor[0] + nor[2] * nor[2];
- bMatrix[0][0] = (nor[0] + nor[2]) * (nor[0] - nor[2]) / -theta;
+ /* nor is close to negative Y axis (0,-1,0): apply the special case. */
+ bMatrix[0][0] = (x + z) * (x - z) / -theta_alt;
bMatrix[2][2] = -bMatrix[0][0];
- bMatrix[2][0] = bMatrix[0][2] = 2.0f * nor[0] * nor[2] / theta;
+ bMatrix[2][0] = bMatrix[0][2] = 2.0f * x * z / theta_alt;
}
}
else {
- /* If nor is -Y, simple symmetry by Z axis. */
+ /* nor is very close to negative Y axis (0,-1,0): use simple symmetry by Z axis. */
unit_m3(bMatrix);
bMatrix[0][0] = bMatrix[1][1] = -1.0;
}
@@ -2209,9 +2209,6 @@ void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_m
/* Combine and output result */
mul_m3_m3m3(r_mat, rMatrix, bMatrix);
-
-#undef THETA_THRESHOLD_NEGY
-#undef THETA_THRESHOLD_NEGY_CLOSE
}
void vec_roll_to_mat3(const float vec[3], const float roll, float r_mat[3][3])