Mesh remap: Fix two potential numeric issues in corner cases, and enhance poly projection.

Null-area face could generate an int overflow, and potential numerical imprecision in face area computation
could lead to negative number of rays-to-cast (though highly unlikely).

Also, use domnant axis of poly normal as 'flattening' one, instead of always using Z axis.

Points raised by Campbell, thanks!
This commit is contained in:
Bastien Montagne 2015-08-07 16:14:54 +02:00
parent c30c3fde51
commit 930fc7d157
1 changed files with 5 additions and 4 deletions

View File

@ -2106,7 +2106,6 @@ void BKE_mesh_remap_calc_polys_from_dm(
int tot_rays, done_rays = 0;
float poly_area_2d_inv, done_area = 0.0f;
const float zvec[3] = {0.0f, 0.0f, 1.0f};
float pcent_dst[3];
float to_pnor_2d_mat[3][3], from_pnor_2d_mat[3][3];
float poly_dst_2d_min[2], poly_dst_2d_max[2], poly_dst_2d_z;
@ -2135,7 +2134,7 @@ void BKE_mesh_remap_calc_polys_from_dm(
tri_vidx_2d = MEM_reallocN(tri_vidx_2d, sizeof(*tri_vidx_2d) * (tmp_poly_size - 2));
}
rotation_between_vecs_to_mat3(to_pnor_2d_mat, tmp_no, zvec);
axis_dominant_v3_to_m3(to_pnor_2d_mat, tmp_no);
invert_m3_m3(from_pnor_2d_mat, to_pnor_2d_mat);
mul_m3_v3(to_pnor_2d_mat, pcent_dst);
@ -2168,7 +2167,9 @@ void BKE_mesh_remap_calc_polys_from_dm(
}
tot_rays *= tot_rays;
poly_area_2d_inv = 1.0f / area_poly_v2((const float(*)[2])poly_vcos_2d, (unsigned int)mp->totloop);
poly_area_2d_inv = area_poly_v2((const float(*)[2])poly_vcos_2d, (unsigned int)mp->totloop);
/* In case we have a null-area degenerated poly... */
poly_area_2d_inv = 1.0f / max_ff(poly_area_2d_inv, 1e-9f);
/* Tessellate our poly. */
if (mp->totloop == 3) {
@ -2198,7 +2199,7 @@ void BKE_mesh_remap_calc_polys_from_dm(
/* All this allows us to get 'absolute' number of rays for each tri, avoiding accumulating
* errors over iterations, and helping better even distribution. */
done_area += area_tri_v2(v1, v2, v3);
rays_num = (int)((float)tot_rays * done_area * poly_area_2d_inv + 0.5f) - done_rays;
rays_num = max_ii((int)((float)tot_rays * done_area * poly_area_2d_inv + 0.5f) - done_rays, 0);
done_rays += rays_num;
while (rays_num--) {