Fix #108037: UV packing problems with pinned islands #108063
|
@ -1150,12 +1150,12 @@ static bool rotate_inside_square(const Span<UVAABBIsland *> island_indices,
|
|||
return false; /* Nothing to do. */
|
||||
}
|
||||
|
||||
/* Transform phis. */
|
||||
/* Transform phis, rotate by best_angle, then translate back to the origin. No scale. */
|
||||
for (const int64_t j : island_indices.index_range()) {
|
||||
const int64_t i = island_indices[j]->index;
|
||||
const PackIsland *island = islands[i];
|
||||
const float island_scale = island->can_scale_(params) ? scale : 1.0f;
|
||||
island->build_transformation(island_scale, square_finder.best_angle, matrix);
|
||||
const float identity_scale = 1.0f; /* Don't rescale the placement, just rotate. */
|
||||
island->build_transformation(identity_scale, square_finder.best_angle, matrix);
|
||||
r_phis[i].rotation += square_finder.best_angle;
|
||||
mul_m2_v2(matrix, r_phis[i].translation);
|
||||
r_phis[i].translation.x -= square_finder.best_bounds.xmin;
|
||||
|
@ -1777,17 +1777,25 @@ class OverlapMerger {
|
|||
sub_params.merge_overlap = false;
|
||||
const float result = pack_islands(sub_islands, sub_params);
|
||||
|
||||
/* Must loop backwards! */
|
||||
/* Must loop backwards, or we will miss sub-sub-islands. */
|
||||
for (int64_t i = merge_trace.size() - 3; i >= 0; i -= 3) {
|
||||
PackIsland *sub_a = merge_trace[i];
|
||||
PackIsland *sub_b = merge_trace[i + 1];
|
||||
PackIsland *merge = merge_trace[i + 2];
|
||||
|
||||
/* Copy `angle`, `pre_translate` and `pre_rotate` from merged island to sub islands. */
|
||||
sub_a->angle = merge->angle;
|
||||
sub_b->angle = merge->angle;
|
||||
sub_a->pre_translate = merge->pre_translate;
|
||||
sub_b->pre_translate = merge->pre_translate;
|
||||
sub_a->pre_rotate_ = merge->pre_rotate_;
|
||||
sub_b->pre_rotate_ = merge->pre_rotate_;
|
||||
|
||||
/* If the merged island is pinned, the sub-islands are also pinned to correct scaling. */
|
||||
if (merge->pinned) {
|
||||
sub_a->pinned = true;
|
||||
sub_b->pinned = true;
|
||||
}
|
||||
delete merge;
|
||||
}
|
||||
|
||||
|
@ -1823,8 +1831,24 @@ float pack_islands(const Span<PackIsland *> &islands, const UVPackIsland_Params
|
|||
|
||||
finalize_geometry(islands, params);
|
||||
|
||||
/* Count the number of islands which can scale and which can translate. */
|
||||
int64_t can_scale_count = 0;
|
||||
int64_t can_translate_count = 0;
|
||||
for (const int64_t i : islands.index_range()) {
|
||||
if (islands[i]->can_scale_(params)) {
|
||||
can_scale_count++;
|
||||
}
|
||||
if (islands[i]->can_translate_(params)) {
|
||||
can_translate_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (can_translate_count == 0) {
|
||||
return 1.0f; /* Nothing to do, all islands are locked. */
|
||||
}
|
||||
|
||||
if (params.margin_method == ED_UVPACK_MARGIN_FRACTION && params.margin > 0.0f &&
|
||||
params.scale_to_fit)
|
||||
can_scale_count > 0)
|
||||
{
|
||||
/* Uses a line search on scale. ~10x slower than other method. */
|
||||
return pack_islands_margin_fraction(islands, params.margin, false, params);
|
||||
|
@ -1837,28 +1861,24 @@ float pack_islands(const Span<PackIsland *> &islands, const UVPackIsland_Params
|
|||
case ED_UVPACK_MARGIN_SCALED: /* Default for Blender 3.3 and later. */
|
||||
margin = calc_margin_from_aabb_length_sum(islands, params);
|
||||
break;
|
||||
case ED_UVPACK_MARGIN_FRACTION: /* Added as an option in Blender 3.4. */
|
||||
BLI_assert(params.margin == 0.0f); /* Other (slower) cases are handled above. */
|
||||
case ED_UVPACK_MARGIN_FRACTION: /* Added as an option in Blender 3.4. */
|
||||
/* Most other cases are handled above, unless pinning is involved. */
|
||||
break;
|
||||
default:
|
||||
BLI_assert_unreachable();
|
||||
}
|
||||
|
||||
/* TODO: Only line-search if *some* islands can scale and *some* are locked. */
|
||||
switch (params.pin_method) {
|
||||
case ED_UVPACK_PIN_LOCK_ALL:
|
||||
case ED_UVPACK_PIN_LOCK_SCALE:
|
||||
case ED_UVPACK_PIN_LOCK_ROTATION_SCALE:
|
||||
return pack_islands_margin_fraction(islands, margin, true, params);
|
||||
default:
|
||||
break;
|
||||
if (can_scale_count > 0 && can_scale_count != islands.size()) {
|
||||
/* Search for the best scale parameter. (slow) */
|
||||
return pack_islands_margin_fraction(islands, margin, true, params);
|
||||
}
|
||||
|
||||
/* Either all of the islands can scale, or none of them can.
|
||||
* In either case, we pack them all tight to the origin. */
|
||||
blender::Array<uv_phi> phis(islands.size());
|
||||
|
||||
const float scale = 1.0f;
|
||||
const float max_uv = pack_islands_scale_margin(islands, scale, margin, params, phis);
|
||||
const float result = params.scale_to_fit ? 1.0f / max_uv : 1.0f;
|
||||
const float result = can_scale_count > 0 ? 1.0f / max_uv : 1.0f;
|
||||
for (const int64_t i : islands.index_range()) {
|
||||
BLI_assert(result == 1.0f || islands[i]->can_scale_(params));
|
||||
islands[i]->place_(scale, phis[i]);
|
||||
|
|
Loading…
Reference in New Issue