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
This commit is contained in:
parent
dfa1c7e554
commit
df445cc571
Notes:
blender-bot
2023-02-14 06:00:51 +01:00
Referenced by issue #82455, The conversion of roll to matrix breaks in some cases
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue