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:
authorGaia Clary <gaiaclary>2020-11-21 13:28:44 +0300
committerAlexander Gavrilov <angavrilov@gmail.com>2021-10-20 12:58:19 +0300
commitdf445cc571bd1cf7fab4c5c8474f5e185a757fe2 (patch)
tree2f8c039e8a16ca7db3bb3e00df4ceb8039a0285f
parentdfa1c7e554fcc3ddd40780fb8555cdd6e90eaba3 (diff)
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
-rw-r--r--source/blender/blenkernel/intern/armature.c17
1 files changed, 8 insertions, 9 deletions
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;