Fix T39210: Grid Fill is generating mesh that's inconsistent with selected edge loops

Issue was in BLI's rotation_between_vecs_to_quat(), which did not handled correctly cases where both vectors are colinear.

Patch by Campbell Barton and me.

Issue originaly tracked down by Yan Shi, many thanks!
This commit is contained in:
Bastien Montagne 2014-03-16 16:31:19 +01:00
parent caf8684b50
commit 0e9084d5ec
Notes: blender-bot 2023-02-14 10:59:10 +01:00
Referenced by issue #39210, Grid Fill is generating mesh that's inconsistent with selected edge loops
6 changed files with 89 additions and 30 deletions

View File

@ -304,8 +304,10 @@ float form_factor_hemi_poly(float p[3], float n[3],
float v1[3], float v2[3], float v3[3], float v4[3]);
bool axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3]);
void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3]);
float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3]);
MINLINE float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3]) ATTR_WARN_UNUSED_RESULT;
MINLINE int axis_dominant_v3_single(const float vec[3]);
MINLINE int max_axis_v3(const float vec[3]);
MINLINE int min_axis_v3(const float vec[3]);

View File

@ -253,6 +253,7 @@ void project_v3_v3v3(float r[3], const float p[3], const float n[3]);
void project_v3_plane(float v[3], const float n[3], const float p[3]);
void reflect_v3_v3v3(float r[3], const float v[3], const float n[3]);
void ortho_basis_v3v3_v3(float r1[3], float r2[3], const float a[3]);
void ortho_v3_v3(float p[3], const float v[3]);
void bisect_v3_v3v3v3(float r[3], const float a[3], const float b[3], const float c[3]);
void rotate_v3_v3v3fl(float v[3], const float p[3], const float axis[3], const float angle);
void rotate_normalized_v3_v3v3fl(float v[3], const float p[3], const float axis[3], const float angle);

View File

@ -2131,31 +2131,6 @@ bool axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3])
}
}
/* get the 2 dominant axis values, 0==X, 1==Y, 2==Z */
void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3])
{
const float xn = fabsf(axis[0]);
const float yn = fabsf(axis[1]);
const float zn = fabsf(axis[2]);
if (zn >= xn && zn >= yn) { *r_axis_a = 0; *r_axis_b = 1; }
else if (yn >= xn && yn >= zn) { *r_axis_a = 0; *r_axis_b = 2; }
else { *r_axis_a = 1; *r_axis_b = 2; }
}
/* same as axis_dominant_v3 but return the max value */
float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3])
{
const float xn = fabsf(axis[0]);
const float yn = fabsf(axis[1]);
const float zn = fabsf(axis[2]);
if (zn >= xn && zn >= yn) { *r_axis_a = 0; *r_axis_b = 1; return zn; }
else if (yn >= xn && yn >= zn) { *r_axis_a = 0; *r_axis_b = 2; return yn; }
else { *r_axis_a = 1; *r_axis_b = 2; return xn; }
}
/****************************** Interpolation ********************************/
static float tri_signed_area(const float v1[3], const float v2[3], const float v3[3], const int i, const int j)

View File

@ -155,6 +155,41 @@ MINLINE void madd_sh_shfl(float r[9], const float sh[9], const float f)
add_sh_shsh(r, r, tmp);
}
/* get the 2 dominant axis values, 0==X, 1==Y, 2==Z */
MINLINE void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3])
{
const float xn = fabsf(axis[0]);
const float yn = fabsf(axis[1]);
const float zn = fabsf(axis[2]);
if (zn >= xn && zn >= yn) { *r_axis_a = 0; *r_axis_b = 1; }
else if (yn >= xn && yn >= zn) { *r_axis_a = 0; *r_axis_b = 2; }
else { *r_axis_a = 1; *r_axis_b = 2; }
}
/* same as axis_dominant_v3 but return the max value */
MINLINE float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3])
{
const float xn = fabsf(axis[0]);
const float yn = fabsf(axis[1]);
const float zn = fabsf(axis[2]);
if (zn >= xn && zn >= yn) { *r_axis_a = 0; *r_axis_b = 1; return zn; }
else if (yn >= xn && yn >= zn) { *r_axis_a = 0; *r_axis_b = 2; return yn; }
else { *r_axis_a = 1; *r_axis_b = 2; return xn; }
}
/* get the single dominant axis value, 0==X, 1==Y, 2==Z */
MINLINE int axis_dominant_v3_single(const float vec[3])
{
const float x = fabsf(vec[0]);
const float y = fabsf(vec[1]);
const float z = fabsf(vec[2]);
return ((x > y) ?
((x > z) ? 0 : 2) :
((y > z) ? 1 : 2));
}
MINLINE int max_axis_v3(const float vec[3])
{
const float x = vec[0];

View File

@ -404,13 +404,29 @@ float normalize_qt_qt(float r[4], const float q[4])
void rotation_between_vecs_to_quat(float q[4], const float v1[3], const float v2[3])
{
float axis[3];
float angle;
cross_v3_v3v3(axis, v1, v2);
angle = angle_normalized_v3v3(v1, v2);
if (normalize_v3(axis) > FLT_EPSILON) {
float angle;
axis_angle_to_quat(q, axis, angle);
angle = angle_normalized_v3v3(v1, v2);
axis_angle_normalized_to_quat(q, axis, angle);
}
else {
/* degenerate case */
if (dot_v3v3(v1, v2) > 0.0f) {
/* Same vectors, zero rotation... */
unit_qt(q);
}
else {
/* Colinear but opposed vectors, 180 rotation... */
ortho_v3_v3(axis, v1);
axis_angle_to_quat(q, axis, (float)M_PI);
}
}
}
void rotation_between_quats_to_quat(float q[4], const float q1[4], const float q2[4])

View File

@ -514,6 +514,36 @@ void ortho_basis_v3v3_v3(float v1[3], float v2[3], const float v[3])
}
}
/**
* Calculates \a p - a perpendicular vector to \a v
*
* \note return vector won't maintain same length.
*/
void ortho_v3_v3(float p[3], const float v[3])
{
const int axis = axis_dominant_v3_single(v);
BLI_assert(p != v);
switch (axis) {
case 0:
p[0] = -v[1] - v[2];
p[1] = v[0];
p[2] = v[0];
break;
case 1:
p[0] = v[1];
p[1] = -v[0] - v[2];
p[2] = v[1];
break;
case 2:
p[0] = v[2];
p[1] = v[2];
p[2] = -v[0] - v[1];
break;
}
}
/* Rotate a point p by angle theta around an arbitrary axis r
* http://local.wasp.uwa.edu.au/~pbourke/geometry/
*/