From 5c780f315df620e049f43aecda45b2f19007ef22 Mon Sep 17 00:00:00 2001 From: Chris Blackbourn Date: Tue, 21 Feb 2023 17:01:08 +1300 Subject: [PATCH 1/4] UV: Migrate UV packing from Editor to bf_geometry. --- source/blender/editors/include/ED_uvedit.h | 20 -- .../blender/editors/uvedit/uvedit_islands.cc | 210 ++--------------- .../editors/uvedit/uvedit_unwrap_ops.cc | 1 + source/blender/geometry/CMakeLists.txt | 2 + source/blender/geometry/GEO_uv_pack.hh | 50 +++++ source/blender/geometry/intern/uv_pack.cc | 212 ++++++++++++++++++ 6 files changed, 281 insertions(+), 214 deletions(-) create mode 100644 source/blender/geometry/GEO_uv_pack.hh create mode 100644 source/blender/geometry/intern/uv_pack.cc diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index 349975e1181..a494fb028db 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -348,26 +348,6 @@ struct UVMapUDIM_Params { int grid_shape[2]; }; -typedef enum { - ED_UVPACK_MARGIN_SCALED = 0, /* Use scale of existing UVs to multiply margin. */ - ED_UVPACK_MARGIN_ADD, /* Just add the margin, ignoring any UV scale. */ - ED_UVPACK_MARGIN_FRACTION, /* Specify a precise fraction of final UV output. */ -} eUVPackIsland_MarginMethod; - -/** See also #UnwrapOptions. */ -struct UVPackIsland_Params { - uint rotate : 1; - uint only_selected_uvs : 1; - uint only_selected_faces : 1; - uint use_seams : 1; - uint correct_aspect : 1; - bool ignore_pinned; /* Ignore islands which have any pinned UVs. */ - bool pin_unselected; /* Treat unselected UVs as if they were pinned. */ - eUVPackIsland_MarginMethod margin_method; /* Which formula to use when scaling island margin. */ - float margin; /* Additional space to add around each island. */ - float udim_base_offset[2]; /* Additional translation for bottom left corner. */ -}; - /** * Returns true if UV coordinates lie on a valid tile in UDIM grid or tiled image. */ diff --git a/source/blender/editors/uvedit/uvedit_islands.cc b/source/blender/editors/uvedit/uvedit_islands.cc index 612d173772e..028ba0fb9b2 100644 --- a/source/blender/editors/uvedit/uvedit_islands.cc +++ b/source/blender/editors/uvedit/uvedit_islands.cc @@ -31,6 +31,8 @@ #include "ED_uvedit.h" /* Own include. */ +#include "GEO_uv_pack.hh" + #include "WM_api.h" #include "WM_types.h" @@ -435,199 +437,6 @@ int bm_mesh_calc_uv_islands(const Scene *scene, /** \} */ -static float pack_islands_scale_margin(const blender::Vector &island_vector, - BoxPack *box_array, - const float scale, - const float margin) -{ - for (const int index : island_vector.index_range()) { - FaceIsland *island = island_vector[index]; - BoxPack *box = &box_array[index]; - box->index = index; - box->w = BLI_rctf_size_x(&island->bounds_rect) * scale + 2 * margin; - box->h = BLI_rctf_size_y(&island->bounds_rect) * scale + 2 * margin; - } - float max_u, max_v; - BLI_box_pack_2d(box_array, island_vector.size(), &max_u, &max_v); - return max_ff(max_u, max_v); -} - -static float pack_islands_margin_fraction(const blender::Vector &island_vector, - BoxPack *box_array, - const float margin_fraction) -{ - /* - * Root finding using a combined search / modified-secant method. - * First, use a robust search procedure to bracket the root within a factor of 10. - * Then, use a modified-secant method to converge. - * - * This is a specialized solver using domain knowledge to accelerate convergence. */ - - float scale_low = 0.0f; - float value_low = 0.0f; - float scale_high = 0.0f; - float value_high = 0.0f; - float scale_last = 0.0f; - - /* Scaling smaller than `min_scale_roundoff` is unlikely to fit and - * will destroy information in existing UVs. */ - float min_scale_roundoff = 1e-5f; - - /* Certain inputs might have poor convergence properties. - * Use `max_iteration` to prevent an infinite loop. */ - int max_iteration = 25; - for (int iteration = 0; iteration < max_iteration; iteration++) { - float scale = 1.0f; - - if (iteration == 0) { - BLI_assert(iteration == 0); - BLI_assert(scale == 1.0f); - BLI_assert(scale_low == 0.0f); - BLI_assert(scale_high == 0.0f); - } - else if (scale_low == 0.0f) { - BLI_assert(scale_high > 0.0f); - /* Search mode, shrink layout until we can find a scale that fits. */ - scale = scale_high * 0.1f; - } - else if (scale_high == 0.0f) { - BLI_assert(scale_low > 0.0f); - /* Search mode, grow layout until we can find a scale that doesn't fit. */ - scale = scale_low * 10.0f; - } - else { - /* Bracket mode, use modified secant method to find root. */ - BLI_assert(scale_low > 0.0f); - BLI_assert(scale_high > 0.0f); - BLI_assert(value_low <= 0.0f); - BLI_assert(value_high >= 0.0f); - if (scale_high < scale_low * 1.0001f) { - /* Convergence. */ - break; - } - - /* Secant method for area. */ - scale = (sqrtf(scale_low) * value_high - sqrtf(scale_high) * value_low) / - (value_high - value_low); - scale = scale * scale; - - if (iteration & 1) { - /* Modified binary-search to improve robustness. */ - scale = sqrtf(scale * sqrtf(scale_low * scale_high)); - } - } - - scale = max_ff(scale, min_scale_roundoff); - - /* Evaluate our `f`. */ - scale_last = scale; - float max_uv = pack_islands_scale_margin( - island_vector, box_array, scale_last, margin_fraction); - float value = sqrtf(max_uv) - 1.0f; - - if (value <= 0.0f) { - scale_low = scale; - value_low = value; - } - else { - scale_high = scale; - value_high = value; - if (scale == min_scale_roundoff) { - /* Unable to pack without damaging UVs. */ - scale_low = scale; - break; - } - } - } - - const bool flush = true; - if (flush) { - /* Write back best pack as a side-effect. First get best pack. */ - if (scale_last != scale_low) { - scale_last = scale_low; - float max_uv = pack_islands_scale_margin( - island_vector, box_array, scale_last, margin_fraction); - UNUSED_VARS(max_uv); - /* TODO (?): `if (max_uv < 1.0f) { scale_last /= max_uv; }` */ - } - - /* Then expand FaceIslands by the correct amount. */ - for (const int index : island_vector.index_range()) { - BoxPack *box = &box_array[index]; - box->x /= scale_last; - box->y /= scale_last; - FaceIsland *island = island_vector[index]; - BLI_rctf_pad( - &island->bounds_rect, margin_fraction / scale_last, margin_fraction / scale_last); - } - } - return scale_last; -} - -static float calc_margin_from_aabb_length_sum(const blender::Vector &island_vector, - const struct UVPackIsland_Params ¶ms) -{ - /* Logic matches behavior from #GEO_uv_parametrizer_pack. - * Attempt to give predictable results not dependent on current UV scale by using - * `aabb_length_sum` (was "`area`") to multiply the margin by the length (was "area"). */ - double aabb_length_sum = 0.0f; - for (FaceIsland *island : island_vector) { - float w = BLI_rctf_size_x(&island->bounds_rect); - float h = BLI_rctf_size_y(&island->bounds_rect); - aabb_length_sum += sqrtf(w * h); - } - return params.margin * aabb_length_sum * 0.1f; -} - -static BoxPack *pack_islands_params(const blender::Vector &island_vector, - const struct UVPackIsland_Params ¶ms, - float r_scale[2]) -{ - BoxPack *box_array = static_cast( - MEM_mallocN(sizeof(*box_array) * island_vector.size(), __func__)); - - if (params.margin == 0.0f) { - /* 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); - r_scale[0] = 1.0f / max_uv; - r_scale[1] = r_scale[0]; - return box_array; - } - - if (params.margin_method == ED_UVPACK_MARGIN_FRACTION) { - /* Uses a line search on scale. ~10x slower than other method. */ - const float scale = pack_islands_margin_fraction(island_vector, box_array, params.margin); - r_scale[0] = scale; - r_scale[1] = scale; - /* pack_islands_margin_fraction will pad FaceIslands, return early. */ - return box_array; - } - - float margin = params.margin; - switch (params.margin_method) { - case ED_UVPACK_MARGIN_ADD: /* Default for Blender 2.8 and earlier. */ - break; /* Nothing to do. */ - case ED_UVPACK_MARGIN_SCALED: /* Default for Blender 3.3 and later. */ - margin = calc_margin_from_aabb_length_sum(island_vector, params); - break; - case ED_UVPACK_MARGIN_FRACTION: /* Added as an option in Blender 3.4. */ - BLI_assert_unreachable(); /* Handled above. */ - break; - default: - BLI_assert_unreachable(); - } - - const float max_uv = pack_islands_scale_margin(island_vector, box_array, 1.0f, margin); - r_scale[0] = 1.0f / max_uv; - r_scale[1] = r_scale[0]; - - for (int index = 0; index < island_vector.size(); index++) { - FaceIsland *island = island_vector[index]; - BLI_rctf_pad(&island->bounds_rect, margin, margin); - } - return box_array; -} - static bool island_has_pins(const Scene *scene, FaceIsland *island, const UVPackIsland_Params *params) @@ -751,7 +560,14 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, } float scale[2] = {1.0f, 1.0f}; - BoxPack *box_array = pack_islands_params(island_vector, *params, scale); + blender::Vector pack_island_vector; + for (int i = 0; i < island_vector.size(); i++) { + FaceIsland *face_island = island_vector[i]; + PackIsland *pack_island = new PackIsland(); + pack_island->bounds_rect = face_island->bounds_rect; + pack_island_vector.append(pack_island); + } + BoxPack *box_array = pack_islands(pack_island_vector, *params, scale); float base_offset[2] = {0.0f, 0.0f}; copy_v2_v2(base_offset, params->udim_base_offset); @@ -818,6 +634,12 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, MEM_freeN(island); } + for (int i = 0; i < pack_island_vector.size(); i++) { + PackIsland *pack_island = pack_island_vector[i]; + pack_island_vector[i] = nullptr; + delete pack_island; + } + MEM_freeN(box_array); } diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.cc b/source/blender/editors/uvedit/uvedit_unwrap_ops.cc index 4cfaf6b5428..d2fca0e9604 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.cc +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.cc @@ -47,6 +47,7 @@ #include "DEG_depsgraph.h" +#include "GEO_uv_pack.hh" #include "GEO_uv_parametrizer.h" #include "PIL_time.h" diff --git a/source/blender/geometry/CMakeLists.txt b/source/blender/geometry/CMakeLists.txt index 6e0dec8f4f6..c0bb0f04f10 100644 --- a/source/blender/geometry/CMakeLists.txt +++ b/source/blender/geometry/CMakeLists.txt @@ -30,6 +30,7 @@ set(SRC intern/set_curve_type.cc intern/subdivide_curves.cc intern/trim_curves.cc + intern/uv_pack.cc intern/uv_parametrizer.cc GEO_add_curves_on_mesh.hh @@ -47,6 +48,7 @@ set(SRC GEO_set_curve_type.hh GEO_subdivide_curves.hh GEO_trim_curves.hh + GEO_uv_pack.hh GEO_uv_parametrizer.h ) diff --git a/source/blender/geometry/GEO_uv_pack.hh b/source/blender/geometry/GEO_uv_pack.hh new file mode 100644 index 00000000000..8e1580e8b9f --- /dev/null +++ b/source/blender/geometry/GEO_uv_pack.hh @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#pragma once + +/** \file + * \ingroup geo + */ + +#include "BLI_boxpack_2d.h" +#include "BLI_vector.hh" +#include "DNA_vec_types.h" + +typedef enum { + ED_UVPACK_MARGIN_SCALED = 0, /* Use scale of existing UVs to multiply margin. */ + ED_UVPACK_MARGIN_ADD, /* Just add the margin, ignoring any UV scale. */ + ED_UVPACK_MARGIN_FRACTION, /* Specify a precise fraction of final UV output. */ +} eUVPackIsland_MarginMethod; + +/** See also #UnwrapOptions. */ +struct UVPackIsland_Params { + /** Islands can be rotated to improve packing. */ + bool rotate; + /** (In UV Editor) only pack islands which have one or more selected UVs.*/ + bool only_selected_uvs; + /** (In 3D Viewport or UV Editor) only pack islands which have selected faces. */ + bool only_selected_faces; + /** When determining islands, use Seams as boundary edges. */ + bool use_seams; + /** (In 3D Viewport or UV Editor) use aspect ratio from face. */ + bool correct_aspect; + /** Ignore islands which have any pinned UVs. */ + bool ignore_pinned; + /** Treat unselected UVs as if they were pinned. */ + bool pin_unselected; + /** Additional space to add around each island. */ + float margin; + /** Which formula to use when scaling island margin. */ + eUVPackIsland_MarginMethod margin_method; + /** Additional translation for bottom left corner. */ + float udim_base_offset[2]; +}; + +class PackIsland { + public: + rctf bounds_rect; +}; + +extern BoxPack *pack_islands(const blender::Vector &island_vector, + const struct UVPackIsland_Params ¶ms, + float r_scale[2]); diff --git a/source/blender/geometry/intern/uv_pack.cc b/source/blender/geometry/intern/uv_pack.cc new file mode 100644 index 00000000000..afbc33b6cd2 --- /dev/null +++ b/source/blender/geometry/intern/uv_pack.cc @@ -0,0 +1,212 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup eduv + */ + +#include "GEO_uv_pack.hh" + +#include "BLI_boxpack_2d.h" +#include "BLI_convexhull_2d.h" +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_rect.h" + +#include "DNA_meshdata_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" + +#include "MEM_guardedalloc.h" + +static float pack_islands_scale_margin(const blender::Vector &island_vector, + BoxPack *box_array, + const float scale, + const float margin) +{ + for (const int64_t index : island_vector.index_range()) { + PackIsland *island = island_vector[index]; + BoxPack *box = &box_array[index]; + box->index = index; + box->w = BLI_rctf_size_x(&island->bounds_rect) * scale + 2 * margin; + box->h = BLI_rctf_size_y(&island->bounds_rect) * scale + 2 * margin; + } + float max_u, max_v; + BLI_box_pack_2d(box_array, island_vector.size(), &max_u, &max_v); + return max_ff(max_u, max_v); +} + +static float pack_islands_margin_fraction(const blender::Vector &island_vector, + BoxPack *box_array, + const float margin_fraction) +{ + /* + * Root finding using a combined search / modified-secant method. + * First, use a robust search procedure to bracket the root within a factor of 10. + * Then, use a modified-secant method to converge. + * + * This is a specialized solver using domain knowledge to accelerate convergence. */ + + float scale_low = 0.0f; + float value_low = 0.0f; + float scale_high = 0.0f; + float value_high = 0.0f; + float scale_last = 0.0f; + + /* Scaling smaller than `min_scale_roundoff` is unlikely to fit and + * will destroy information in existing UVs. */ + float min_scale_roundoff = 1e-5f; + + /* Certain inputs might have poor convergence properties. + * Use `max_iteration` to prevent an infinite loop. */ + int max_iteration = 25; + for (int iteration = 0; iteration < max_iteration; iteration++) { + float scale = 1.0f; + + if (iteration == 0) { + BLI_assert(iteration == 0); + BLI_assert(scale == 1.0f); + BLI_assert(scale_low == 0.0f); + BLI_assert(scale_high == 0.0f); + } + else if (scale_low == 0.0f) { + BLI_assert(scale_high > 0.0f); + /* Search mode, shrink layout until we can find a scale that fits. */ + scale = scale_high * 0.1f; + } + else if (scale_high == 0.0f) { + BLI_assert(scale_low > 0.0f); + /* Search mode, grow layout until we can find a scale that doesn't fit. */ + scale = scale_low * 10.0f; + } + else { + /* Bracket mode, use modified secant method to find root. */ + BLI_assert(scale_low > 0.0f); + BLI_assert(scale_high > 0.0f); + BLI_assert(value_low <= 0.0f); + BLI_assert(value_high >= 0.0f); + if (scale_high < scale_low * 1.0001f) { + /* Convergence. */ + break; + } + + /* Secant method for area. */ + scale = (sqrtf(scale_low) * value_high - sqrtf(scale_high) * value_low) / + (value_high - value_low); + scale = scale * scale; + + if (iteration & 1) { + /* Modified binary-search to improve robustness. */ + scale = sqrtf(scale * sqrtf(scale_low * scale_high)); + } + } + + scale = max_ff(scale, min_scale_roundoff); + + /* Evaluate our `f`. */ + scale_last = scale; + float max_uv = pack_islands_scale_margin( + island_vector, box_array, scale_last, margin_fraction); + float value = sqrtf(max_uv) - 1.0f; + + if (value <= 0.0f) { + scale_low = scale; + value_low = value; + } + else { + scale_high = scale; + value_high = value; + if (scale == min_scale_roundoff) { + /* Unable to pack without damaging UVs. */ + scale_low = scale; + break; + } + } + } + + const bool flush = true; + if (flush) { + /* Write back best pack as a side-effect. First get best pack. */ + if (scale_last != scale_low) { + scale_last = scale_low; + float max_uv = pack_islands_scale_margin( + island_vector, box_array, scale_last, margin_fraction); + UNUSED_VARS(max_uv); + /* TODO (?): `if (max_uv < 1.0f) { scale_last /= max_uv; }` */ + } + + /* Then expand FaceIslands by the correct amount. */ + for (const int64_t index : island_vector.index_range()) { + BoxPack *box = &box_array[index]; + box->x /= scale_last; + box->y /= scale_last; + PackIsland *island = island_vector[index]; + BLI_rctf_pad( + &island->bounds_rect, margin_fraction / scale_last, margin_fraction / scale_last); + } + } + return scale_last; +} + +static float calc_margin_from_aabb_length_sum(const blender::Vector &island_vector, + const struct UVPackIsland_Params ¶ms) +{ + /* Logic matches behavior from #GEO_uv_parametrizer_pack. + * Attempt to give predictable results not dependent on current UV scale by using + * `aabb_length_sum` (was "`area`") to multiply the margin by the length (was "area"). */ + double aabb_length_sum = 0.0f; + for (PackIsland *island : island_vector) { + float w = BLI_rctf_size_x(&island->bounds_rect); + float h = BLI_rctf_size_y(&island->bounds_rect); + aabb_length_sum += sqrtf(w * h); + } + return params.margin * aabb_length_sum * 0.1f; +} + +BoxPack *pack_islands(const blender::Vector &island_vector, + const struct UVPackIsland_Params ¶ms, + float r_scale[2]) +{ + BoxPack *box_array = static_cast( + MEM_mallocN(sizeof(*box_array) * island_vector.size(), __func__)); + + if (params.margin == 0.0f) { + /* 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); + r_scale[0] = 1.0f / max_uv; + r_scale[1] = r_scale[0]; + return box_array; + } + + if (params.margin_method == ED_UVPACK_MARGIN_FRACTION) { + /* Uses a line search on scale. ~10x slower than other method. */ + const float scale = pack_islands_margin_fraction(island_vector, box_array, params.margin); + r_scale[0] = scale; + r_scale[1] = scale; + /* pack_islands_margin_fraction will pad FaceIslands, return early. */ + return box_array; + } + + float margin = params.margin; + switch (params.margin_method) { + case ED_UVPACK_MARGIN_ADD: /* Default for Blender 2.8 and earlier. */ + break; /* Nothing to do. */ + case ED_UVPACK_MARGIN_SCALED: /* Default for Blender 3.3 and later. */ + margin = calc_margin_from_aabb_length_sum(island_vector, params); + break; + case ED_UVPACK_MARGIN_FRACTION: /* Added as an option in Blender 3.4. */ + BLI_assert_unreachable(); /* Handled above. */ + break; + default: + BLI_assert_unreachable(); + } + + const float max_uv = pack_islands_scale_margin(island_vector, box_array, 1.0f, margin); + r_scale[0] = 1.0f / max_uv; + r_scale[1] = r_scale[0]; + + for (int index = 0; index < island_vector.size(); index++) { + PackIsland *island = island_vector[index]; + BLI_rctf_pad(&island->bounds_rect, margin, margin); + } + return box_array; +} -- 2.30.2 From 496567acce8ccfa773164d6f3f961054ac8a3fc1 Mon Sep 17 00:00:00 2001 From: Chris Blackbourn Date: Mon, 27 Feb 2023 13:15:18 +1300 Subject: [PATCH 2/4] UV: Migrate UV packing from Editor to bf_geometry. Improved C++ styling. --- source/blender/editors/uvedit/uvedit_islands.cc | 4 ++-- source/blender/geometry/GEO_uv_pack.hh | 12 ++++++------ source/blender/geometry/intern/uv_pack.cc | 12 ++++++------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/source/blender/editors/uvedit/uvedit_islands.cc b/source/blender/editors/uvedit/uvedit_islands.cc index 028ba0fb9b2..b93d10fa34c 100644 --- a/source/blender/editors/uvedit/uvedit_islands.cc +++ b/source/blender/editors/uvedit/uvedit_islands.cc @@ -473,8 +473,8 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, Object **objects, const uint objects_len, BMesh **bmesh_override, - const struct UVMapUDIM_Params *closest_udim, - const struct UVPackIsland_Params *params) + const UVMapUDIM_Params *closest_udim, + const UVPackIsland_Params *params) { blender::Vector island_vector; diff --git a/source/blender/geometry/GEO_uv_pack.hh b/source/blender/geometry/GEO_uv_pack.hh index 8e1580e8b9f..d45dc72008a 100644 --- a/source/blender/geometry/GEO_uv_pack.hh +++ b/source/blender/geometry/GEO_uv_pack.hh @@ -7,14 +7,14 @@ */ #include "BLI_boxpack_2d.h" -#include "BLI_vector.hh" +#include "BLI_span.hh" #include "DNA_vec_types.h" -typedef enum { +enum eUVPackIsland_MarginMethod { ED_UVPACK_MARGIN_SCALED = 0, /* Use scale of existing UVs to multiply margin. */ ED_UVPACK_MARGIN_ADD, /* Just add the margin, ignoring any UV scale. */ ED_UVPACK_MARGIN_FRACTION, /* Specify a precise fraction of final UV output. */ -} eUVPackIsland_MarginMethod; +}; /** See also #UnwrapOptions. */ struct UVPackIsland_Params { @@ -45,6 +45,6 @@ class PackIsland { rctf bounds_rect; }; -extern BoxPack *pack_islands(const blender::Vector &island_vector, - const struct UVPackIsland_Params ¶ms, - float r_scale[2]); +BoxPack *pack_islands(const blender::Span &island_vector, + const UVPackIsland_Params ¶ms, + float r_scale[2]); diff --git a/source/blender/geometry/intern/uv_pack.cc b/source/blender/geometry/intern/uv_pack.cc index afbc33b6cd2..a28b16da5a9 100644 --- a/source/blender/geometry/intern/uv_pack.cc +++ b/source/blender/geometry/intern/uv_pack.cc @@ -18,7 +18,7 @@ #include "MEM_guardedalloc.h" -static float pack_islands_scale_margin(const blender::Vector &island_vector, +static float pack_islands_scale_margin(const blender::Span &island_vector, BoxPack *box_array, const float scale, const float margin) @@ -35,7 +35,7 @@ static float pack_islands_scale_margin(const blender::Vector &isla return max_ff(max_u, max_v); } -static float pack_islands_margin_fraction(const blender::Vector &island_vector, +static float pack_islands_margin_fraction(const blender::Span &island_vector, BoxPack *box_array, const float margin_fraction) { @@ -147,8 +147,8 @@ static float pack_islands_margin_fraction(const blender::Vector &i return scale_last; } -static float calc_margin_from_aabb_length_sum(const blender::Vector &island_vector, - const struct UVPackIsland_Params ¶ms) +static float calc_margin_from_aabb_length_sum(const blender::Span &island_vector, + const UVPackIsland_Params ¶ms) { /* Logic matches behavior from #GEO_uv_parametrizer_pack. * Attempt to give predictable results not dependent on current UV scale by using @@ -162,8 +162,8 @@ static float calc_margin_from_aabb_length_sum(const blender::Vector &island_vector, - const struct UVPackIsland_Params ¶ms, +BoxPack *pack_islands(const blender::Span &island_vector, + const UVPackIsland_Params ¶ms, float r_scale[2]) { BoxPack *box_array = static_cast( -- 2.30.2 From 6f011576f00aebadfb1d16cec937afdc796b02cd Mon Sep 17 00:00:00 2001 From: Chris Blackbourn Date: Tue, 28 Feb 2023 10:03:05 +1300 Subject: [PATCH 3/4] UV: Migrate UV packing from Editor to bf_geometry. Move to blender::geometry namespace. --- source/blender/editors/uvedit/uvedit_islands.cc | 6 +++--- source/blender/geometry/GEO_uv_pack.hh | 15 ++++++++++----- source/blender/geometry/intern/uv_pack.cc | 12 ++++++++---- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/source/blender/editors/uvedit/uvedit_islands.cc b/source/blender/editors/uvedit/uvedit_islands.cc index b93d10fa34c..eaf812e3b2f 100644 --- a/source/blender/editors/uvedit/uvedit_islands.cc +++ b/source/blender/editors/uvedit/uvedit_islands.cc @@ -560,10 +560,10 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, } float scale[2] = {1.0f, 1.0f}; - blender::Vector pack_island_vector; + blender::Vector pack_island_vector; for (int i = 0; i < island_vector.size(); i++) { FaceIsland *face_island = island_vector[i]; - PackIsland *pack_island = new PackIsland(); + blender::geometry::PackIsland *pack_island = new blender::geometry::PackIsland(); pack_island->bounds_rect = face_island->bounds_rect; pack_island_vector.append(pack_island); } @@ -635,7 +635,7 @@ void ED_uvedit_pack_islands_multi(const Scene *scene, } for (int i = 0; i < pack_island_vector.size(); i++) { - PackIsland *pack_island = pack_island_vector[i]; + blender::geometry::PackIsland *pack_island = pack_island_vector[i]; pack_island_vector[i] = nullptr; delete pack_island; } diff --git a/source/blender/geometry/GEO_uv_pack.hh b/source/blender/geometry/GEO_uv_pack.hh index d45dc72008a..622efe1e608 100644 --- a/source/blender/geometry/GEO_uv_pack.hh +++ b/source/blender/geometry/GEO_uv_pack.hh @@ -1,15 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ +#include "BLI_boxpack_2d.h" +#include "BLI_span.hh" + +#include "DNA_vec_types.h" + #pragma once /** \file * \ingroup geo */ -#include "BLI_boxpack_2d.h" -#include "BLI_span.hh" -#include "DNA_vec_types.h" - enum eUVPackIsland_MarginMethod { ED_UVPACK_MARGIN_SCALED = 0, /* Use scale of existing UVs to multiply margin. */ ED_UVPACK_MARGIN_ADD, /* Just add the margin, ignoring any UV scale. */ @@ -40,11 +41,15 @@ struct UVPackIsland_Params { float udim_base_offset[2]; }; +namespace blender::geometry { + class PackIsland { public: rctf bounds_rect; }; -BoxPack *pack_islands(const blender::Span &island_vector, +BoxPack *pack_islands(const Span &island_vector, const UVPackIsland_Params ¶ms, float r_scale[2]); + +} // namespace blender::geometry diff --git a/source/blender/geometry/intern/uv_pack.cc b/source/blender/geometry/intern/uv_pack.cc index a28b16da5a9..9aadf23f922 100644 --- a/source/blender/geometry/intern/uv_pack.cc +++ b/source/blender/geometry/intern/uv_pack.cc @@ -18,7 +18,9 @@ #include "MEM_guardedalloc.h" -static float pack_islands_scale_margin(const blender::Span &island_vector, +namespace blender::geometry { + +static float pack_islands_scale_margin(const Span &island_vector, BoxPack *box_array, const float scale, const float margin) @@ -35,7 +37,7 @@ static float pack_islands_scale_margin(const blender::Span &island return max_ff(max_u, max_v); } -static float pack_islands_margin_fraction(const blender::Span &island_vector, +static float pack_islands_margin_fraction(const Span &island_vector, BoxPack *box_array, const float margin_fraction) { @@ -147,7 +149,7 @@ static float pack_islands_margin_fraction(const blender::Span &isl return scale_last; } -static float calc_margin_from_aabb_length_sum(const blender::Span &island_vector, +static float calc_margin_from_aabb_length_sum(const Span &island_vector, const UVPackIsland_Params ¶ms) { /* Logic matches behavior from #GEO_uv_parametrizer_pack. @@ -162,7 +164,7 @@ static float calc_margin_from_aabb_length_sum(const blender::Span return params.margin * aabb_length_sum * 0.1f; } -BoxPack *pack_islands(const blender::Span &island_vector, +BoxPack *pack_islands(const Span &island_vector, const UVPackIsland_Params ¶ms, float r_scale[2]) { @@ -210,3 +212,5 @@ BoxPack *pack_islands(const blender::Span &island_vector, } return box_array; } + +} // namespace blender::geometry -- 2.30.2 From 809d7a61a321665c9cb67797b40e8356abac1468 Mon Sep 17 00:00:00 2001 From: Chris Blackbourn Date: Tue, 28 Feb 2023 10:35:35 +1300 Subject: [PATCH 4/4] UV: Migrate UV packing from Editor to bf_geometry. Add comments and fix minor warnings. --- source/blender/geometry/GEO_uv_pack.hh | 4 ++++ source/blender/geometry/intern/uv_pack.cc | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/source/blender/geometry/GEO_uv_pack.hh b/source/blender/geometry/GEO_uv_pack.hh index 622efe1e608..a6adcb4cbaf 100644 --- a/source/blender/geometry/GEO_uv_pack.hh +++ b/source/blender/geometry/GEO_uv_pack.hh @@ -11,6 +11,9 @@ * \ingroup geo */ +/** Workaround to forward-declare C type in C++ header. */ +extern "C" { + enum eUVPackIsland_MarginMethod { ED_UVPACK_MARGIN_SCALED = 0, /* Use scale of existing UVs to multiply margin. */ ED_UVPACK_MARGIN_ADD, /* Just add the margin, ignoring any UV scale. */ @@ -40,6 +43,7 @@ struct UVPackIsland_Params { /** Additional translation for bottom left corner. */ float udim_base_offset[2]; }; +} namespace blender::geometry { diff --git a/source/blender/geometry/intern/uv_pack.cc b/source/blender/geometry/intern/uv_pack.cc index 9aadf23f922..b8434b7b224 100644 --- a/source/blender/geometry/intern/uv_pack.cc +++ b/source/blender/geometry/intern/uv_pack.cc @@ -28,12 +28,12 @@ static float pack_islands_scale_margin(const Span &island_vector, for (const int64_t index : island_vector.index_range()) { PackIsland *island = island_vector[index]; BoxPack *box = &box_array[index]; - box->index = index; + box->index = (int)index; box->w = BLI_rctf_size_x(&island->bounds_rect) * scale + 2 * margin; box->h = BLI_rctf_size_y(&island->bounds_rect) * scale + 2 * margin; } float max_u, max_v; - BLI_box_pack_2d(box_array, island_vector.size(), &max_u, &max_v); + BLI_box_pack_2d(box_array, (int)island_vector.size(), &max_u, &max_v); return max_ff(max_u, max_v); } -- 2.30.2