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:
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
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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/
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue