Fix T100874: improve uv unwrap of degenerate geometry
Provide reasonable defaults for UV unwrap for triangles with zero area: * Three vertices are arranged in a line. * Two vertices are at the same 3D location. * All three vertices are at the same 3D location. Change fixes quads / ngons which have triangulations with zero area. Change fixes both "Angle Based" method and "Conformal" method. Differential Revision: https://developer.blender.org/D15922
This commit is contained in:
parent
c9a8380426
commit
94e211ced9
Notes:
blender-bot
2023-02-14 00:06:52 +01:00
Referenced by issue #100874, **UW unwrap** unwraps UVs incorrectly
|
@ -307,12 +307,70 @@ static float p_vec2_angle(const float v1[2], const float v2[2], const float v3[2
|
|||
{
|
||||
return angle_v2v2v2(v1, v2, v3);
|
||||
}
|
||||
|
||||
/* Angles close to 0 or 180 degrees cause rows filled with zeros in the linear_solver.
|
||||
* The matrix will then be rank deficient and / or have poor conditioning.
|
||||
* => Reduce the maximum angle to 179 degrees, and spread the remainder to the other angles.
|
||||
*/
|
||||
static void fix_large_angle(const float v_fix[3],
|
||||
const float v1[3],
|
||||
const float v2[3],
|
||||
float *r_fix,
|
||||
float *r_a1,
|
||||
float *r_a2)
|
||||
{
|
||||
const float max_angle = (float)M_PI * (179.0f / 180.0f);
|
||||
const float fix_amount = *r_fix - max_angle;
|
||||
if (fix_amount < 0.0f) {
|
||||
return; /* angle is reasonable, i.e. less than 179 degrees. */
|
||||
}
|
||||
|
||||
/* The triangle is probably degenerate, or close to it.
|
||||
* Without loss of generality, transform the triangle such that
|
||||
* v_fix == { 0, s}, *r_fix = 180 degrees
|
||||
* v1 == {-x1, 0}, *r_a1 = 0
|
||||
* v2 == { x2, 0}, *r_a2 = 0
|
||||
*
|
||||
* With `s = 0`, `x1 > 0`, `x2 > 0`
|
||||
*
|
||||
* Now make `s` a small number and do some math:
|
||||
* tan(*r_a1) = s / x1
|
||||
* tan(*r_a2) = s / x2
|
||||
*
|
||||
* Remember that `tan = sin / cos`, `sin(s) ~= s` and `cos(s) = 1`
|
||||
*
|
||||
* Rearrange to obtain:
|
||||
* *r_a1 = fix_amount * x2 / (x1 + x2)
|
||||
* *r_a2 = fix_amount * x1 / (x1 + x2)
|
||||
*/
|
||||
|
||||
const float dist_v1 = len_v3v3(v_fix, v1);
|
||||
const float dist_v2 = len_v3v3(v_fix, v2);
|
||||
const float sum = dist_v1 + dist_v2;
|
||||
const float weight = (sum > 1e-20f) ? dist_v2 / sum : 0.5f;
|
||||
|
||||
/* Ensure sum of angles in triangle is unchanged. */
|
||||
*r_fix -= fix_amount;
|
||||
*r_a1 += fix_amount * weight;
|
||||
*r_a2 += fix_amount * (1.0f - weight);
|
||||
}
|
||||
|
||||
static void p_triangle_angles(
|
||||
const float v1[3], const float v2[3], const float v3[3], float *r_a1, float *r_a2, float *r_a3)
|
||||
{
|
||||
*r_a1 = p_vec_angle(v3, v1, v2);
|
||||
*r_a2 = p_vec_angle(v1, v2, v3);
|
||||
*r_a3 = (float)M_PI - *r_a2 - *r_a1;
|
||||
*r_a3 = p_vec_angle(v2, v3, v1);
|
||||
|
||||
/* Fix for degenerate geometry e.g. v1 = sum(v2 + v3). See T100874 */
|
||||
fix_large_angle(v1, v2, v3, r_a1, r_a2, r_a3);
|
||||
fix_large_angle(v2, v3, v1, r_a2, r_a3, r_a1);
|
||||
fix_large_angle(v3, v1, v2, r_a3, r_a1, r_a2);
|
||||
|
||||
/* Workaround for degenerate geometry, e.g. v1 == v2 == v3. */
|
||||
*r_a1 = max_ff(*r_a1, 0.001f);
|
||||
*r_a2 = max_ff(*r_a2, 0.001f);
|
||||
*r_a3 = max_ff(*r_a3, 0.001f);
|
||||
}
|
||||
|
||||
static void p_face_angles(PFace *f, float *r_a1, float *r_a2, float *r_a3)
|
||||
|
@ -2266,7 +2324,6 @@ using PAbfSystem = struct PAbfSystem {
|
|||
float *bAlpha, *bTriangle, *bInterior;
|
||||
float *lambdaTriangle, *lambdaPlanar, *lambdaLength;
|
||||
float (*J2dt)[3], *bstar, *dstar;
|
||||
float minangle, maxangle;
|
||||
};
|
||||
|
||||
static void p_abf_setup_system(PAbfSystem *sys)
|
||||
|
@ -2294,9 +2351,6 @@ static void p_abf_setup_system(PAbfSystem *sys)
|
|||
for (i = 0; i < sys->ninterior; i++) {
|
||||
sys->lambdaLength[i] = 1.0;
|
||||
}
|
||||
|
||||
sys->minangle = 1.0 * M_PI / 180.0;
|
||||
sys->maxangle = (float)M_PI - sys->minangle;
|
||||
}
|
||||
|
||||
static void p_abf_free_system(PAbfSystem *sys)
|
||||
|
@ -2707,25 +2761,6 @@ static bool p_chart_abf_solve(PChart *chart)
|
|||
e3 = e2->next;
|
||||
p_face_angles(f, &a1, &a2, &a3);
|
||||
|
||||
if (a1 < sys.minangle) {
|
||||
a1 = sys.minangle;
|
||||
}
|
||||
else if (a1 > sys.maxangle) {
|
||||
a1 = sys.maxangle;
|
||||
}
|
||||
if (a2 < sys.minangle) {
|
||||
a2 = sys.minangle;
|
||||
}
|
||||
else if (a2 > sys.maxangle) {
|
||||
a2 = sys.maxangle;
|
||||
}
|
||||
if (a3 < sys.minangle) {
|
||||
a3 = sys.minangle;
|
||||
}
|
||||
else if (a3 > sys.maxangle) {
|
||||
a3 = sys.maxangle;
|
||||
}
|
||||
|
||||
sys.alpha[e1->u.id] = sys.beta[e1->u.id] = a1;
|
||||
sys.alpha[e2->u.id] = sys.beta[e2->u.id] = a2;
|
||||
sys.alpha[e3->u.id] = sys.beta[e3->u.id] = a3;
|
||||
|
|
Loading…
Reference in New Issue