Cleanup: Convert float to double during uv unwrap
buildbot/vdev-code-daily-coordinator Build done.
Details
buildbot/vdev-code-daily-coordinator Build done.
Details
`sinf(float_angle)` is sometimes producing different results on x86_64 cpus and apple silicon cpus. Convert to double precision to increase accuracy and consistency. Partial fix for #104513. More to come.
This commit is contained in:
parent
a684e61cbf
commit
0eba9e41bf
Notes:
blender-bot
2023-06-08 04:30:36 +02:00
Referenced by issue #107717, Lineart modifier crashes Blender
Referenced by issue #107829, How to handle difference in sinf/cosf for M1
Referenced by commit 9d25c4aaa6
, Fix #104513: UV packing produces different results on x86 vs apple silicon
|
@ -140,6 +140,8 @@ MINLINE float max_ffff(float a, float b, float c, float d);
|
|||
|
||||
MINLINE double min_dd(double a, double b);
|
||||
MINLINE double max_dd(double a, double b);
|
||||
MINLINE double min_ddd(double a, double b, double c);
|
||||
MINLINE double max_ddd(double a, double b, double c);
|
||||
|
||||
MINLINE int min_ii(int a, int b);
|
||||
MINLINE int max_ii(int a, int b);
|
||||
|
|
|
@ -545,6 +545,15 @@ MINLINE unsigned long long max_ulul(unsigned long long a, unsigned long long b)
|
|||
return (b < a) ? a : b;
|
||||
}
|
||||
|
||||
MINLINE double min_ddd(double a, double b, double c)
|
||||
{
|
||||
return min_dd(min_dd(a, b), c);
|
||||
}
|
||||
MINLINE double max_ddd(double a, double b, double c)
|
||||
{
|
||||
return max_dd(max_dd(a, b), c);
|
||||
}
|
||||
|
||||
MINLINE float min_fff(float a, float b, float c)
|
||||
{
|
||||
return min_ff(min_ff(a, b), c);
|
||||
|
|
|
@ -303,12 +303,12 @@ static PHashLink *phash_next(PHash *ph, PHashKey key, PHashLink *link)
|
|||
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)
|
||||
double *r_fix,
|
||||
double *r_a1,
|
||||
double *r_a2)
|
||||
{
|
||||
const float max_angle = float(M_PI) * (179.0f / 180.0f);
|
||||
const float fix_amount = *r_fix - max_angle;
|
||||
const double max_angle = M_PI * 179.0f / 180.0f;
|
||||
const double fix_amount = *r_fix - max_angle;
|
||||
if (fix_amount < 0.0f) {
|
||||
return; /* angle is reasonable, i.e. less than 179 degrees. */
|
||||
}
|
||||
|
@ -325,17 +325,17 @@ static void fix_large_angle(const float v_fix[3],
|
|||
* tan(*r_a1) = s / x1
|
||||
* tan(*r_a2) = s / x2
|
||||
*
|
||||
* Remember that `tan = sin / cos`, `sin(s) ~= s` and `cos(s) = 1`
|
||||
* Remember that `tan(angle) ~= angle`
|
||||
*
|
||||
* 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;
|
||||
const double dist_v1 = len_v3v3(v_fix, v1);
|
||||
const double dist_v2 = len_v3v3(v_fix, v2);
|
||||
const double sum = dist_v1 + dist_v2;
|
||||
const double weight = (sum > 1e-20f) ? dist_v2 / sum : 0.5f;
|
||||
|
||||
/* Ensure sum of angles in triangle is unchanged. */
|
||||
*r_fix -= fix_amount;
|
||||
|
@ -344,7 +344,7 @@ static void fix_large_angle(const float v_fix[3],
|
|||
}
|
||||
|
||||
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)
|
||||
const float v1[3], const float v2[3], const float v3[3], double *r_a1, double *r_a2, double *r_a3)
|
||||
{
|
||||
*r_a1 = angle_v3v3v3(v3, v1, v2);
|
||||
*r_a2 = angle_v3v3v3(v1, v2, v3);
|
||||
|
@ -356,12 +356,12 @@ static void p_triangle_angles(
|
|||
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);
|
||||
*r_a1 = max_dd(*r_a1, 0.001f);
|
||||
*r_a2 = max_dd(*r_a2, 0.001f);
|
||||
*r_a3 = max_dd(*r_a3, 0.001f);
|
||||
}
|
||||
|
||||
static void p_face_angles(PFace *f, float *r_a1, float *r_a2, float *r_a3)
|
||||
static void p_face_angles(PFace *f, double *r_a1, double *r_a2, double *r_a3)
|
||||
{
|
||||
PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
|
||||
PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
|
||||
|
@ -2315,12 +2315,14 @@ static void p_abf_free_system(PAbfSystem *sys)
|
|||
|
||||
static void p_abf_compute_sines(PAbfSystem *sys)
|
||||
{
|
||||
int i;
|
||||
float *sine = sys->sine, *cosine = sys->cosine, *alpha = sys->alpha;
|
||||
float *sine = sys->sine;
|
||||
float *cosine = sys->cosine;
|
||||
const float *alpha = sys->alpha;
|
||||
|
||||
for (i = 0; i < sys->nangles; i++, sine++, cosine++, alpha++) {
|
||||
*sine = sinf(*alpha);
|
||||
*cosine = cosf(*alpha);
|
||||
for (int i = 0; i < sys->nangles; i++) {
|
||||
const double angle = alpha[i];
|
||||
sine[i] = sin(angle);
|
||||
cosine[i] = cos(angle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2691,7 +2693,7 @@ static bool p_chart_abf_solve(PChart *chart)
|
|||
|
||||
/* compute initial angles */
|
||||
for (f = chart->faces; f; f = f->nextlink) {
|
||||
float a1, a2, a3;
|
||||
double a1, a2, a3;
|
||||
|
||||
e1 = f->edge;
|
||||
e2 = e1->next;
|
||||
|
@ -3104,7 +3106,7 @@ static bool p_chart_lscm_solve(ParamHandle *handle, PChart *chart)
|
|||
for (PFace *f = chart->faces; f; f = f->nextlink) {
|
||||
PEdge *e1 = f->edge, *e2 = e1->next, *e3 = e2->next;
|
||||
PVert *v1 = e1->vert, *v2 = e2->vert, *v3 = e3->vert;
|
||||
float a1, a2, a3;
|
||||
double a1, a2, a3;
|
||||
|
||||
if (alpha) {
|
||||
/* Use abf angles if present. */
|
||||
|
@ -3122,29 +3124,29 @@ static bool p_chart_lscm_solve(ParamHandle *handle, PChart *chart)
|
|||
std::swap(v2, v3);
|
||||
}
|
||||
|
||||
float sina1 = sinf(a1);
|
||||
float sina2 = sinf(a2);
|
||||
float sina3 = sinf(a3);
|
||||
double sina1 = sin(a1);
|
||||
double sina2 = sin(a2);
|
||||
double sina3 = sin(a3);
|
||||
|
||||
const float sinmax = max_fff(sina1, sina2, sina3);
|
||||
const double sinmax = max_ddd(sina1, sina2, sina3);
|
||||
|
||||
/* Shift vertices to find most stable order. */
|
||||
if (sina3 != sinmax) {
|
||||
SHIFT3(PVert *, v1, v2, v3);
|
||||
SHIFT3(float, a1, a2, a3);
|
||||
SHIFT3(float, sina1, sina2, sina3);
|
||||
SHIFT3(double, a1, a2, a3);
|
||||
SHIFT3(double, sina1, sina2, sina3);
|
||||
|
||||
if (sina2 == sinmax) {
|
||||
SHIFT3(PVert *, v1, v2, v3);
|
||||
SHIFT3(float, a1, a2, a3);
|
||||
SHIFT3(float, sina1, sina2, sina3);
|
||||
SHIFT3(double, a1, a2, a3);
|
||||
SHIFT3(double, sina1, sina2, sina3);
|
||||
}
|
||||
}
|
||||
|
||||
/* Angle based lscm formulation. */
|
||||
const float ratio = (sina3 == 0.0f) ? 1.0f : sina2 / sina3;
|
||||
const float cosine = cosf(a1) * ratio;
|
||||
const float sine = sina1 * ratio;
|
||||
const double ratio = (sina3 == 0.0f) ? 1.0f : sina2 / sina3;
|
||||
const double cosine = cos(a1) * ratio;
|
||||
const double sine = sina1 * ratio;
|
||||
|
||||
EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id, cosine - 1.0f);
|
||||
EIG_linear_solver_matrix_add(context, row, 2 * v1->u.id + 1, -sine);
|
||||
|
|
Loading…
Reference in New Issue