Commit: e2cb81aa51281df363606382a82aaa06430e3788
Author: Gaia Clary
Date:   Sat Nov 21 13:28:44 2020 +0300
Branches: temp-angavrilov-roll-precision
https://developer.blender.org/rBe2cb81aa51281df363606382a82aaa06430e3788

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 e8a3db11219..d05a3611508 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;

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to