UV: Add alpaca_rotate variant for improved packing efficiency #105977
|
@ -1407,6 +1407,8 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
||||||
blender::geometry::PackIsland *pack_island = new blender::geometry::PackIsland();
|
blender::geometry::PackIsland *pack_island = new blender::geometry::PackIsland();
|
||||||
pack_island->bounds_rect = face_island->bounds_rect;
|
pack_island->bounds_rect = face_island->bounds_rect;
|
||||||
pack_island->caller_index = i;
|
pack_island->caller_index = i;
|
||||||
|
pack_island->aspect_y = face_island->aspect_y;
|
||||||
|
pack_island->angle = 0.0f;
|
||||||
pack_island_vector.append(pack_island);
|
pack_island_vector.append(pack_island);
|
||||||
|
|
||||||
for (int i = 0; i < face_island->faces_len; i++) {
|
for (int i = 0; i < face_island->faces_len; i++) {
|
||||||
|
@ -1473,10 +1475,12 @@ static void uvedit_pack_islands_multi(const Scene *scene,
|
||||||
for (int64_t i : pack_island_vector.index_range()) {
|
for (int64_t i : pack_island_vector.index_range()) {
|
||||||
blender::geometry::PackIsland *pack_island = pack_island_vector[i];
|
blender::geometry::PackIsland *pack_island = pack_island_vector[i];
|
||||||
FaceIsland *island = island_vector[pack_island->caller_index];
|
FaceIsland *island = island_vector[pack_island->caller_index];
|
||||||
matrix[0][0] = scale[0];
|
const float cos_angle = cosf(pack_island->angle);
|
||||||
matrix[0][1] = 0.0f;
|
const float sin_angle = sinf(pack_island->angle);
|
||||||
matrix[1][0] = 0.0f;
|
matrix[0][0] = cos_angle * scale[0];
|
||||||
matrix[1][1] = scale[1];
|
matrix[0][1] = -sin_angle * scale[0] * pack_island->aspect_y;
|
||||||
|
matrix[1][0] = sin_angle * scale[1] / pack_island->aspect_y;
|
||||||
|
matrix[1][1] = cos_angle * scale[1];
|
||||||
invert_m2_m2(matrix_inverse, matrix);
|
invert_m2_m2(matrix_inverse, matrix);
|
||||||
|
|
||||||
/* Add base_offset, post transform. */
|
/* Add base_offset, post transform. */
|
||||||
|
|
|
@ -73,8 +73,11 @@ class UVPackIsland_Params {
|
||||||
class PackIsland {
|
class PackIsland {
|
||||||
public:
|
public:
|
||||||
rctf bounds_rect;
|
rctf bounds_rect;
|
||||||
|
/** Aspect ratio, required for rotation. */
|
||||||
|
float aspect_y;
|
||||||
/** Output. */
|
/** Output. */
|
||||||
float2 pre_translate;
|
float2 pre_translate;
|
||||||
|
float angle;
|
||||||
/** Unchanged by #pack_islands, used by caller. */
|
/** Unchanged by #pack_islands, used by caller. */
|
||||||
int caller_index;
|
int caller_index;
|
||||||
|
|
||||||
|
|
|
@ -180,6 +180,7 @@ class UVAABBIsland {
|
||||||
float2 uv_diagonal;
|
float2 uv_diagonal;
|
||||||
float2 uv_placement;
|
float2 uv_placement;
|
||||||
int64_t index;
|
int64_t index;
|
||||||
|
float angle;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -508,7 +509,7 @@ static void pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
|
||||||
else {
|
else {
|
||||||
/* Increasing by 2 here has the effect of changing the sampling pattern.
|
/* Increasing by 2 here has the effect of changing the sampling pattern.
|
||||||
* The parameter '2' is not "free" in the sense that changing it requires
|
* The parameter '2' is not "free" in the sense that changing it requires
|
||||||
* a change to `bitmap_radix` and then returning `alpaca_cutoff`.
|
* a change to `bitmap_radix` and then re-tuning `alpaca_cutoff`.
|
||||||
* Possible values here *could* be 1, 2 or 3, however the only *reasonable*
|
* Possible values here *could* be 1, 2 or 3, however the only *reasonable*
|
||||||
* choice is 2. */
|
* choice is 2. */
|
||||||
scan_line += 2;
|
scan_line += 2;
|
||||||
|
@ -551,6 +552,132 @@ static void pack_island_xatlas(const Span<UVAABBIsland *> island_indices,
|
||||||
*r_max_v = max_v;
|
*r_max_v = max_v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void update_hole_rotate(float2 &hole,
|
||||||
Chris_Blackbourn marked this conversation as resolved
Outdated
|
|||||||
|
float2 &hole_diagonal,
|
||||||
|
bool &hole_rotate,
|
||||||
|
const float u0,
|
||||||
|
const float v0,
|
||||||
|
const float u1,
|
||||||
|
const float v1)
|
||||||
|
{
|
||||||
|
const float p = hole_diagonal.x * hole_diagonal.y;
|
||||||
|
const float quad_area = (u1 - u0) * (v1 - v0);
|
||||||
|
if (p >= quad_area) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
hole.x = u0;
|
||||||
|
hole.y = v0;
|
||||||
|
hole_diagonal.x = u1 - u0;
|
||||||
|
hole_diagonal.y = v1 - v0;
|
||||||
|
if (hole_diagonal.y < hole_diagonal.x) {
|
||||||
|
std::swap(hole_diagonal.x, hole_diagonal.y);
|
||||||
|
hole_rotate = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hole_rotate = false;
|
||||||
|
}
|
||||||
|
const float q = hole_diagonal.x * hole_diagonal.y;
|
||||||
|
BLI_assert(q > p);
|
||||||
|
UNUSED_VARS(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pack AABB islands using the "Alpaca" strategy, with rotation.
|
||||||
|
*
|
||||||
|
* Same as #pack_islands_alpaca_turbo with support for rotation in 90 degree increments.
|
||||||
|
*/
|
||||||
|
static void pack_islands_alpaca_rotate(const Span<UVAABBIsland *> islands,
|
||||||
|
float *r_max_u,
|
||||||
|
float *r_max_v)
|
||||||
|
{
|
||||||
|
/* Exclude an initial AABB near the origin. */
|
||||||
|
float next_u1 = *r_max_u;
|
||||||
|
float next_v1 = *r_max_v;
|
||||||
|
bool zigzag = next_u1 < next_v1; /* Horizontal or Vertical strip? */
|
||||||
|
|
||||||
|
/* Track an AABB "hole" which may be filled at any time. */
|
||||||
|
float2 hole(0.0f);
|
||||||
|
float2 hole_diagonal(0.0f);
|
||||||
|
bool hole_rotate = false;
|
||||||
|
|
||||||
|
float u0 = zigzag ? next_u1 : 0.0f;
|
||||||
|
float v0 = zigzag ? 0.0f : next_v1;
|
||||||
|
|
||||||
|
/* Visit every island in order. */
|
||||||
|
for (UVAABBIsland *island : islands) {
|
||||||
|
float min_dsm = std::min(island->uv_diagonal.x, island->uv_diagonal.y);
|
||||||
|
float max_dsm = std::max(island->uv_diagonal.x, island->uv_diagonal.y);
|
||||||
|
|
||||||
|
if (min_dsm < hole_diagonal.x && max_dsm < hole_diagonal.y) {
|
||||||
|
/* Place island in the hole. */
|
||||||
|
island->uv_placement.x = hole[0];
|
||||||
|
island->uv_placement.y = hole[1];
|
||||||
|
if (hole_rotate == (min_dsm == island->uv_diagonal.x)) {
|
||||||
|
island->angle = DEG2RADF(90.0f);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
island->angle = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update space left in the hole. */
|
||||||
|
float p[6];
|
||||||
|
p[0] = hole[0];
|
||||||
|
p[1] = hole[1];
|
||||||
|
p[2] = hole[0] + (hole_rotate ? max_dsm : min_dsm);
|
||||||
|
p[3] = hole[1] + (hole_rotate ? min_dsm : max_dsm);
|
||||||
|
p[4] = hole[0] + (hole_rotate ? hole_diagonal.y : hole_diagonal.x);
|
||||||
|
p[5] = hole[1] + (hole_rotate ? hole_diagonal.x : hole_diagonal.y);
|
||||||
|
hole_diagonal.x = 0; /* Invalidate old hole. */
|
||||||
|
update_hole_rotate(hole, hole_diagonal, hole_rotate, p[0], p[3], p[4], p[5]);
|
||||||
|
update_hole_rotate(hole, hole_diagonal, hole_rotate, p[2], p[1], p[4], p[5]);
|
||||||
|
|
||||||
|
/* Island is placed, no need to check for restart. */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool restart = false;
|
||||||
|
if (zigzag) {
|
||||||
|
restart = (next_v1 < v0 + min_dsm);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
restart = (next_u1 < u0 + min_dsm);
|
||||||
|
}
|
||||||
|
if (restart) {
|
||||||
|
update_hole_rotate(hole, hole_diagonal, hole_rotate, u0, v0, next_u1, next_v1);
|
||||||
|
/* We're at the end of a strip. Restart from U axis or V axis. */
|
||||||
|
zigzag = next_u1 < next_v1;
|
||||||
|
u0 = zigzag ? next_u1 : 0.0f;
|
||||||
|
v0 = zigzag ? 0.0f : next_v1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Place the island. */
|
||||||
|
if (zigzag == (min_dsm == island->uv_diagonal.x)) {
|
||||||
|
island->angle = DEG2RADF(90.0f);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
island->angle = 0.0f;
|
||||||
|
}
|
||||||
|
island->uv_placement.x = u0;
|
||||||
|
island->uv_placement.y = v0;
|
||||||
|
if (zigzag) {
|
||||||
|
/* Move upwards. */
|
||||||
|
v0 += min_dsm;
|
||||||
|
next_u1 = max_ff(next_u1, u0 + max_dsm);
|
||||||
|
next_v1 = max_ff(next_v1, v0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Move sideways. */
|
||||||
|
u0 += min_dsm;
|
||||||
|
next_v1 = max_ff(next_v1, v0 + max_dsm);
|
||||||
|
next_u1 = max_ff(next_u1, u0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write back total pack AABB. */
|
||||||
|
*r_max_u = next_u1;
|
||||||
|
*r_max_v = next_v1;
|
||||||
|
}
|
||||||
|
|
||||||
static float pack_islands_scale_margin(const Span<PackIsland *> islands,
|
static float pack_islands_scale_margin(const Span<PackIsland *> islands,
|
||||||
BoxPack *box_array,
|
BoxPack *box_array,
|
||||||
const float scale,
|
const float scale,
|
||||||
|
@ -569,7 +696,7 @@ static float pack_islands_scale_margin(const Span<PackIsland *> islands,
|
||||||
* The current strategy is:
|
* The current strategy is:
|
||||||
* - Sort islands in size order.
|
* - Sort islands in size order.
|
||||||
* - Call #BLI_box_pack_2d on the first `alpaca_cutoff` islands.
|
* - Call #BLI_box_pack_2d on the first `alpaca_cutoff` islands.
|
||||||
* - Call #pack_islands_alpaca_turbo on the remaining islands.
|
* - Call #pack_islands_alpaca_* on the remaining islands.
|
||||||
* - Combine results.
|
* - Combine results.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -585,10 +712,36 @@ static float pack_islands_scale_margin(const Span<PackIsland *> islands,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sort from "biggest" to "smallest". */
|
/* Sort from "biggest" to "smallest". */
|
||||||
std::stable_sort(aabbs.begin(), aabbs.end(), [](const UVAABBIsland *a, const UVAABBIsland *b) {
|
|
||||||
/* Just choose the AABB with larger rectangular area. */
|
if (params.rotate) {
|
||||||
return b->uv_diagonal.x * b->uv_diagonal.y < a->uv_diagonal.x * a->uv_diagonal.y;
|
std::stable_sort(aabbs.begin(), aabbs.end(), [](const UVAABBIsland *a, const UVAABBIsland *b) {
|
||||||
});
|
/* Choose the AABB with the longest large edge. */
|
||||||
|
float a_u = a->uv_diagonal.x;
|
||||||
|
float a_v = a->uv_diagonal.y;
|
||||||
|
float b_u = b->uv_diagonal.x;
|
||||||
|
float b_v = b->uv_diagonal.y;
|
||||||
|
if (a_u > a_v) {
|
||||||
|
std::swap(a_u, a_v);
|
||||||
|
}
|
||||||
|
if (b_u > b_v) {
|
||||||
|
std::swap(b_u, b_v);
|
||||||
|
}
|
||||||
|
float diff_u = a_u - b_u;
|
||||||
|
float diff_v = a_v - b_v;
|
||||||
|
diff_v += diff_u * 0.05f; /* Robust sort, smooth over round-off errors. */
|
||||||
|
if (diff_v == 0.0f) { /* Tie break. */
|
||||||
|
return diff_u > 0.0f;
|
||||||
|
}
|
||||||
|
return diff_v > 0.0f;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
std::stable_sort(aabbs.begin(), aabbs.end(), [](const UVAABBIsland *a, const UVAABBIsland *b) {
|
||||||
|
/* Choose the AABB with larger rectangular area. */
|
||||||
|
return b->uv_diagonal.x * b->uv_diagonal.y < a->uv_diagonal.x * a->uv_diagonal.y;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/* Partition `islands`, largest will go to a slow packer, the rest alpaca_turbo.
|
/* Partition `islands`, largest will go to a slow packer, the rest alpaca_turbo.
|
||||||
* See discussion above for details. */
|
* See discussion above for details. */
|
||||||
|
@ -632,14 +785,22 @@ static float pack_islands_scale_margin(const Span<PackIsland *> islands,
|
||||||
/* At this stage, `max_u` and `max_v` contain the box_pack UVs. */
|
/* At this stage, `max_u` and `max_v` contain the box_pack UVs. */
|
||||||
|
|
||||||
/* Call Alpaca. */
|
/* Call Alpaca. */
|
||||||
pack_islands_alpaca_turbo(aabbs.as_span().drop_front(max_box_pack), &max_u, &max_v);
|
if (params.rotate) {
|
||||||
|
pack_islands_alpaca_rotate(aabbs.as_mutable_span().drop_front(max_box_pack), &max_u, &max_v);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pack_islands_alpaca_turbo(aabbs.as_mutable_span().drop_front(max_box_pack), &max_u, &max_v);
|
||||||
|
}
|
||||||
|
|
||||||
/* Write back Alpaca UVs. */
|
/* Write back Alpaca UVs. */
|
||||||
for (int64_t index = max_box_pack; index < aabbs.size(); index++) {
|
for (int64_t i = max_box_pack; i < aabbs.size(); i++) {
|
||||||
UVAABBIsland *aabb = aabbs[index];
|
UVAABBIsland *aabb = aabbs[i];
|
||||||
BoxPack *box = &box_array[index];
|
BoxPack *box = &box_array[i];
|
||||||
box->x = aabb->uv_placement.x;
|
box->x = aabb->uv_placement.x;
|
||||||
box->y = aabb->uv_placement.y;
|
box->y = aabb->uv_placement.y;
|
||||||
|
|
||||||
|
PackIsland *pack_island = islands[aabb->index];
|
||||||
|
pack_island->angle = aabb->angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Memory management. */
|
/* Memory management. */
|
||||||
|
@ -748,6 +909,7 @@ static float pack_islands_margin_fraction(const Span<PackIsland *> &island_vecto
|
||||||
scale_last = scale_low;
|
scale_last = scale_low;
|
||||||
const float max_uv = pack_islands_scale_margin(
|
const float max_uv = pack_islands_scale_margin(
|
||||||
island_vector, box_array, scale_last, margin_fraction, params);
|
island_vector, box_array, scale_last, margin_fraction, params);
|
||||||
|
BLI_assert(max_uv == value_low);
|
||||||
UNUSED_VARS(max_uv);
|
UNUSED_VARS(max_uv);
|
||||||
/* TODO (?): `if (max_uv < 1.0f) { scale_last /= max_uv; }` */
|
/* TODO (?): `if (max_uv < 1.0f) { scale_last /= max_uv; }` */
|
||||||
}
|
}
|
||||||
|
@ -780,16 +942,16 @@ static float calc_margin_from_aabb_length_sum(const Span<PackIsland *> &island_v
|
||||||
return params.margin * aabb_length_sum * 0.1f;
|
return params.margin * aabb_length_sum * 0.1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BoxPack *pack_islands_box_array(const Span<PackIsland *> &island_vector,
|
static BoxPack *pack_islands_box_array(const Span<PackIsland *> &islands,
|
||||||
const UVPackIsland_Params ¶ms,
|
const UVPackIsland_Params ¶ms,
|
||||||
float r_scale[2])
|
float r_scale[2])
|
||||||
{
|
{
|
||||||
BoxPack *box_array = static_cast<BoxPack *>(
|
BoxPack *box_array = static_cast<BoxPack *>(
|
||||||
MEM_mallocN(sizeof(*box_array) * island_vector.size(), __func__));
|
MEM_mallocN(sizeof(*box_array) * islands.size(), __func__));
|
||||||
|
|
||||||
if (params.margin == 0.0f) {
|
if (params.margin == 0.0f) {
|
||||||
/* Special case for zero margin. Margin_method is ignored as all formulas give same result. */
|
/* Special case for zero margin. Margin_method is ignored as all formulas give same result. */
|
||||||
const float max_uv = pack_islands_scale_margin(island_vector, box_array, 1.0f, 0.0f, params);
|
const float max_uv = pack_islands_scale_margin(islands, box_array, 1.0f, 0.0f, params);
|
||||||
r_scale[0] = 1.0f / max_uv;
|
r_scale[0] = 1.0f / max_uv;
|
||||||
r_scale[1] = r_scale[0];
|
r_scale[1] = r_scale[0];
|
||||||
return box_array;
|
return box_array;
|
||||||
|
@ -797,8 +959,7 @@ static BoxPack *pack_islands_box_array(const Span<PackIsland *> &island_vector,
|
||||||
|
|
||||||
if (params.margin_method == ED_UVPACK_MARGIN_FRACTION) {
|
if (params.margin_method == ED_UVPACK_MARGIN_FRACTION) {
|
||||||
/* Uses a line search on scale. ~10x slower than other method. */
|
/* Uses a line search on scale. ~10x slower than other method. */
|
||||||
const float scale = pack_islands_margin_fraction(
|
const float scale = pack_islands_margin_fraction(islands, box_array, params.margin, params);
|
||||||
island_vector, box_array, params.margin, params);
|
|
||||||
r_scale[0] = scale;
|
r_scale[0] = scale;
|
||||||
r_scale[1] = scale;
|
r_scale[1] = scale;
|
||||||
/* pack_islands_margin_fraction will pad FaceIslands, return early. */
|
/* pack_islands_margin_fraction will pad FaceIslands, return early. */
|
||||||
|
@ -810,7 +971,7 @@ static BoxPack *pack_islands_box_array(const Span<PackIsland *> &island_vector,
|
||||||
case ED_UVPACK_MARGIN_ADD: /* Default for Blender 2.8 and earlier. */
|
case ED_UVPACK_MARGIN_ADD: /* Default for Blender 2.8 and earlier. */
|
||||||
break; /* Nothing to do. */
|
break; /* Nothing to do. */
|
||||||
case ED_UVPACK_MARGIN_SCALED: /* Default for Blender 3.3 and later. */
|
case ED_UVPACK_MARGIN_SCALED: /* Default for Blender 3.3 and later. */
|
||||||
margin = calc_margin_from_aabb_length_sum(island_vector, params);
|
margin = calc_margin_from_aabb_length_sum(islands, params);
|
||||||
break;
|
break;
|
||||||
case ED_UVPACK_MARGIN_FRACTION: /* Added as an option in Blender 3.4. */
|
case ED_UVPACK_MARGIN_FRACTION: /* Added as an option in Blender 3.4. */
|
||||||
BLI_assert_unreachable(); /* Handled above. */
|
BLI_assert_unreachable(); /* Handled above. */
|
||||||
|
@ -819,12 +980,12 @@ static BoxPack *pack_islands_box_array(const Span<PackIsland *> &island_vector,
|
||||||
BLI_assert_unreachable();
|
BLI_assert_unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
const float max_uv = pack_islands_scale_margin(island_vector, box_array, 1.0f, margin, params);
|
const float max_uv = pack_islands_scale_margin(islands, box_array, 1.0f, margin, params);
|
||||||
r_scale[0] = 1.0f / max_uv;
|
r_scale[0] = 1.0f / max_uv;
|
||||||
r_scale[1] = r_scale[0];
|
r_scale[1] = r_scale[0];
|
||||||
|
|
||||||
for (int index = 0; index < island_vector.size(); index++) {
|
for (int index = 0; index < islands.size(); index++) {
|
||||||
PackIsland *island = island_vector[index];
|
PackIsland *island = islands[index];
|
||||||
BLI_rctf_pad(&island->bounds_rect, margin, margin);
|
BLI_rctf_pad(&island->bounds_rect, margin, margin);
|
||||||
}
|
}
|
||||||
return box_array;
|
return box_array;
|
||||||
|
@ -839,8 +1000,15 @@ void pack_islands(const Span<PackIsland *> &islands,
|
||||||
for (int64_t i : islands.index_range()) {
|
for (int64_t i : islands.index_range()) {
|
||||||
BoxPack *box = box_array + i;
|
BoxPack *box = box_array + i;
|
||||||
PackIsland *island = islands[box->index];
|
PackIsland *island = islands[box->index];
|
||||||
island->pre_translate.x = box->x - island->bounds_rect.xmin;
|
if (island->angle) {
|
||||||
island->pre_translate.y = box->y - island->bounds_rect.ymin;
|
/* TODO: Apply proper rotation. */
|
||||||
|
island->pre_translate.x = (-box->y / island->aspect_y) - island->bounds_rect.xmax;
|
||||||
|
island->pre_translate.y = (box->x * island->aspect_y) - island->bounds_rect.ymin;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
island->pre_translate.x = box->x - island->bounds_rect.xmin;
|
||||||
|
island->pre_translate.y = box->y - island->bounds_rect.ymin;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_freeN(box_array);
|
MEM_freeN(box_array);
|
||||||
|
|
|
@ -4168,6 +4168,8 @@ void uv_parametrizer_pack(ParamHandle *handle, float margin, bool do_rotate, boo
|
||||||
|
|
||||||
geometry::PackIsland *pack_island = new geometry::PackIsland();
|
geometry::PackIsland *pack_island = new geometry::PackIsland();
|
||||||
pack_island->caller_index = i;
|
pack_island->caller_index = i;
|
||||||
|
pack_island->aspect_y = handle->aspx / handle->aspy;
|
||||||
|
pack_island->angle = 0.0f;
|
||||||
pack_island_vector.append(pack_island);
|
pack_island_vector.append(pack_island);
|
||||||
|
|
||||||
float minv[2];
|
float minv[2];
|
||||||
|
@ -4191,16 +4193,18 @@ void uv_parametrizer_pack(ParamHandle *handle, float margin, bool do_rotate, boo
|
||||||
PackIsland *pack_island = pack_island_vector[i];
|
PackIsland *pack_island = pack_island_vector[i];
|
||||||
PChart *chart = handle->charts[pack_island->caller_index];
|
PChart *chart = handle->charts[pack_island->caller_index];
|
||||||
|
|
||||||
float m[2][2];
|
float matrix[2][2];
|
||||||
float b[2];
|
float b[2];
|
||||||
m[0][0] = scale[0];
|
const float cos_angle = cosf(pack_island->angle);
|
||||||
m[0][1] = 0.0f;
|
const float sin_angle = sinf(pack_island->angle);
|
||||||
m[1][0] = 0.0f;
|
matrix[0][0] = cos_angle * scale[0];
|
||||||
m[1][1] = scale[1];
|
matrix[0][1] = -sin_angle * scale[0] * pack_island->aspect_y;
|
||||||
|
matrix[1][0] = sin_angle * scale[1] / pack_island->aspect_y;
|
||||||
|
matrix[1][1] = cos_angle * scale[1];
|
||||||
b[0] = pack_island->pre_translate.x;
|
b[0] = pack_island->pre_translate.x;
|
||||||
b[1] = pack_island->pre_translate.y;
|
b[1] = pack_island->pre_translate.y;
|
||||||
for (PVert *v = chart->verts; v; v = v->nextlink) {
|
for (PVert *v = chart->verts; v; v = v->nextlink) {
|
||||||
blender::geometry::mul_v2_m2_add_v2v2(v->uv, m, v->uv, b);
|
blender::geometry::mul_v2_m2_add_v2v2(v->uv, matrix, v->uv, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
pack_island_vector[i] = nullptr;
|
pack_island_vector[i] = nullptr;
|
||||||
|
|
Loading…
Reference in New Issue
update_hole_rotate
doesn't have a doc-string, a short explanation explaining what it's doing would be good. It's not totally obvious thatq
andquad_area
will never be negative, that could be asserted, it could also be noted that the arguments are ordered. (to ensure unexpected negative values never occur).