[Bf-blender-cvs] [df445cc571b] master: Fix T82455: vec_roll_to_mat3_normalized returns NaN when nor close to -Y.

Gaia Clary noreply at git.blender.org
Wed Oct 20 11:58:33 CEST 2021


Commit: df445cc571bd1cf7fab4c5c8474f5e185a757fe2
Author: Gaia Clary
Date:   Sat Nov 21 13:28:44 2020 +0300
Branches: master
https://developer.blender.org/rBdf445cc571bd1cf7fab4c5c8474f5e185a757fe2

Fix T82455: vec_roll_to_mat3_normalized returns NaN when nor close to -Y.

In this case theta is completely unsafe to use, so a different
threshold based on x and z has to be used to avoid division by zero.

Ref D9551

===================================================================

M	source/blender/blenkernel/intern/armature.c

===================================================================

diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index a60cba3c892..a266718dcfc 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -2240,15 +2240,16 @@ 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])
 {
-  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. */
+  const float SAFE_THRESHOLD = 1.0e-5f;     /* theta above this value has good enough precision. */
+  const float CRITICAL_THRESHOLD = 1.0e-9f; /* above this is safe under certain conditions. */
+  const float THRESHOLD_SQUARED = CRITICAL_THRESHOLD * CRITICAL_THRESHOLD;
 
   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;
+  const float theta = 1.0f + y;          /* remapping Y from [-1,+1] to [0,2]. */
+  const float theta_alt = x * x + z * z; /* Helper value for matrix calculations.*/
   float rMatrix[3][3], bMatrix[3][3];
 
   BLI_ASSERT_UNIT_V3(nor);
@@ -2258,10 +2259,8 @@ void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_m
    * 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_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... ;)
-     */
+  if (theta > SAFE_THRESHOLD || (theta > CRITICAL_THRESHOLD && theta_alt > THRESHOLD_SQUARED)) {
+    /* nor is *not* aligned to negative Y-axis (0,-1,0). */
 
     bMatrix[0][1] = -x;
     bMatrix[1][0] = x;
@@ -2269,7 +2268,7 @@ void vec_roll_to_mat3_normalized(const float nor[3], const float roll, float r_m
     bMatrix[1][2] = z;
     bMatrix[2][1] = -z;
 
-    if (theta > THETA_SAFE) {
+    if (theta > SAFE_THRESHOLD) {
       /* 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;



More information about the Bf-blender-cvs mailing list