refactor vec_roll_to_mat3_normalized() for clarity
the function vec_roll_to_mat3_normalized() has a bug as described in T82455. This Differential is only for refactoring the code such that it becomes more clear what the function does and how the bug can be fixed. This differential is supposed to not introduce any functional changes. Reviewed By: sybren Differential Revision: https://developer.blender.org/D9410
This commit is contained in:
parent
4efd87d56b
commit
12f394ece7
|
@ -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])
|
||||
|
|
Loading…
Reference in New Issue