UV: when finding the best packing method, use area as tie breaker

When multiple packing methods results in effectively the same bounds,
prefer the packer that uses the smallest area. When all islands can
easily fit this is usually the box packer instead of alpaca. The zigzag
method of the latter has a tendendcy to take up more area and rotate
islands.

Fix #110724: smart UV project unnecessarily rotates islands

Pull Request: https://projects.blender.org/blender/blender/pulls/112295
This commit is contained in:
Brecht Van Lommel 2023-09-12 17:05:18 +02:00
parent d4cc0d02cb
commit 89b3249c14
1 changed files with 21 additions and 1 deletions

View File

@ -106,12 +106,32 @@ static float get_aspect_scaled_extent(const rctf &extent, const UVPackIsland_Par
return std::max(width / params.target_aspect_y, height);
}
/**
* \return the area of `extent`, factoring in the target aspect ratio.
*/
static float get_aspect_scaled_area(const rctf &extent, const UVPackIsland_Params &params)
{
const float width = BLI_rctf_size_x(&extent);
const float height = BLI_rctf_size_y(&extent);
return (width / params.target_aspect_y) * height;
}
/**
* \return true if `b` is a preferred layout over `a`, given the packing parameters supplied.
*/
static bool is_larger(const rctf &a, const rctf &b, const UVPackIsland_Params &params)
{
return get_aspect_scaled_extent(b, params) < get_aspect_scaled_extent(a, params);
const float extent_a = get_aspect_scaled_extent(a, params);
const float extent_b = get_aspect_scaled_extent(b, params);
/* Equal extent, use smaller area. */
if (compare_ff_relative(extent_a, extent_b, FLT_EPSILON, 64)) {
const float area_a = get_aspect_scaled_area(a, params);
const float area_b = get_aspect_scaled_area(b, params);
return area_b < area_a;
}
return extent_b < extent_a;
}
PackIsland::PackIsland()