[Bf-blender-cvs] [1d159e1882b] temp-T97352-3d-texturing-seam-bleeding-b2: Use a minimum extension length to reduce artifacts in dense geometry.
Jeroen Bakker
noreply at git.blender.org
Fri Jul 15 16:34:02 CEST 2022
Commit: 1d159e1882b7ec66ad6cedc9b69d0a687c23b2ba
Author: Jeroen Bakker
Date: Fri Jul 15 16:33:48 2022 +0200
Branches: temp-T97352-3d-texturing-seam-bleeding-b2
https://developer.blender.org/rB1d159e1882b7ec66ad6cedc9b69d0a687c23b2ba
Use a minimum extension length to reduce artifacts in dense geometry.
===================================================================
M source/blender/blenkernel/BKE_uv_islands.hh
M source/blender/blenkernel/intern/pbvh_pixels.cc
M source/blender/blenkernel/intern/uv_islands.cc
===================================================================
diff --git a/source/blender/blenkernel/BKE_uv_islands.hh b/source/blender/blenkernel/BKE_uv_islands.hh
index 770dd6b6b96..b84fe9ef7a8 100644
--- a/source/blender/blenkernel/BKE_uv_islands.hh
+++ b/source/blender/blenkernel/BKE_uv_islands.hh
@@ -547,19 +547,13 @@ struct UVBorderCorner {
{
}
- float2 uv(float factor)
- {
- float2 origin = first->get_uv_vertex(1)->uv;
- float angle_between = angle * factor;
- float desired_len = second->length() * factor + first->length() * (1.0 - factor);
- float2 v = first->get_uv_vertex(0)->uv - origin;
- normalize_v2(v);
-
- float3x3 rot_mat = float3x3::from_rotation(angle_between);
- float2 rotated = rot_mat * v;
- float2 result = rotated * desired_len + first->get_uv_vertex(1)->uv;
- return result;
- }
+ /**
+ * Calculate a uv coordinate between the edges of the corner.
+ *
+ * 'min_uv_distance' is the minimum distance between the corner and the
+ * resulting uv coordinate. The distance is in uv space.
+ */
+ float2 uv(float factor, float min_uv_distance);
};
struct UVBorder {
@@ -823,18 +817,26 @@ struct UVIslandsMask {
/** Mask for each udim tile. */
struct Tile {
float2 udim_offset;
- ushort2 resolution;
+ ushort2 tile_resolution;
+ ushort2 mask_resolution;
Array<uint16_t> mask;
- Tile(float2 udim_offset, ushort2 resolution);
+ Tile(float2 udim_offset, ushort2 tile_resolution);
bool is_masked(const uint16_t island_index, const float2 uv) const;
+ bool contains(const float2 uv) const;
+ float get_pixel_size_in_uv_space() const;
};
Vector<Tile> tiles;
void add_tile(float2 udim_offset, ushort2 resolution);
+ /**
+ * Find a tile containing the given uv coordinate.
+ */
+ const Tile *find_tile(const float2 uv) const;
+
/**
* Is the given uv coordinate part of the given island_index mask.
*
diff --git a/source/blender/blenkernel/intern/pbvh_pixels.cc b/source/blender/blenkernel/intern/pbvh_pixels.cc
index 5969cd65208..faf56fb7b8d 100644
--- a/source/blender/blenkernel/intern/pbvh_pixels.cc
+++ b/source/blender/blenkernel/intern/pbvh_pixels.cc
@@ -367,10 +367,17 @@ static void update_pixels(PBVH *pbvh, Mesh *mesh, Image *image, ImageUser *image
// TODO: mask resolution should be based on the actual resolution of the image buffer (or a
// factor of it).
uv_islands::UVIslandsMask uv_masks;
+ ImageUser tile_user = *image_user;
LISTBASE_FOREACH (ImageTile *, tile_data, &image->tiles) {
image::ImageTileWrapper image_tile(tile_data);
+ tile_user.tile = image_tile.get_tile_number();
+ ImBuf *tile_buffer = BKE_image_acquire_ibuf(image, &tile_user, nullptr);
+ if (tile_buffer == nullptr) {
+ continue;
+ }
uv_masks.add_tile(float2(image_tile.get_tile_x_offset(), image_tile.get_tile_y_offset()),
- ushort2(1024, 1024));
+ ushort2(tile_buffer->x, tile_buffer->y));
+ BKE_image_release_ibuf(image, tile_buffer, nullptr);
}
uv_masks.add(islands);
uv_masks.dilate(image->seamfix_iter);
diff --git a/source/blender/blenkernel/intern/uv_islands.cc b/source/blender/blenkernel/intern/uv_islands.cc
index 37732d773e1..e32813c6712 100644
--- a/source/blender/blenkernel/intern/uv_islands.cc
+++ b/source/blender/blenkernel/intern/uv_islands.cc
@@ -406,7 +406,7 @@ static void add_uv_primitive_fill(UVIsland &island,
island.uv_primitives.append(uv_primitive);
}
-static void extend_at_vert(UVIsland &island, UVBorderCorner &corner)
+static void extend_at_vert(UVIsland &island, UVBorderCorner &corner, float min_uv_distance)
{
int border_index = corner.first->border_index;
UVBorder &border = island.borders[border_index];
@@ -441,7 +441,7 @@ static void extend_at_vert(UVIsland &island, UVBorderCorner &corner)
fill_primitive_2 = fill_primitive;
}
- float2 center_uv = corner.uv(0.5f);
+ float2 center_uv = corner.uv(0.5f, min_uv_distance);
add_uv_primitive_shared_uv_edge(island,
corner.first->get_uv_vertex(1),
corner.first->get_uv_vertex(0),
@@ -482,7 +482,7 @@ static void extend_at_vert(UVIsland &island, UVBorderCorner &corner)
current_edge->get_other_uv_vertex(uv_vertex->vertex)->vertex;
float factor = (i + 1.0f) / (num_to_add + 1.0f);
- float2 new_uv = corner.uv(factor);
+ float2 new_uv = corner.uv(factor, min_uv_distance);
// Find an segment that contains the 'current edge'.
for (InnerEdge &segment : fan.inner_edges) {
@@ -623,8 +623,9 @@ void UVIsland::extend_border(const UVIslandsMask &mask, const short island_index
UVVertex *uv_vertex = extension_corner->second->get_uv_vertex(0);
/* When outside the mask, the uv should not be considered for extension. */
- if (mask.is_masked(island_index, uv_vertex->uv)) {
- extend_at_vert(*this, *extension_corner);
+ const UVIslandsMask::Tile *tile = mask.find_tile(uv_vertex->uv);
+ if (tile && tile->is_masked(island_index, uv_vertex->uv)) {
+ extend_at_vert(*this, *extension_corner, tile->get_pixel_size_in_uv_space() * 2.0f);
}
/* Mark that the vert is extended. Unable to extend twice. */
uv_vertex->flags.is_extended = true;
@@ -756,6 +757,26 @@ void UVBorder::validate() const
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name UVBorderCorner
+ * \{ */
+float2 UVBorderCorner::uv(float factor, float min_uv_distance)
+{
+ float2 origin = first->get_uv_vertex(1)->uv;
+ float angle_between = angle * factor;
+ float desired_len = max_ff(second->length() * factor + first->length() * (1.0 - factor),
+ min_uv_distance);
+ float2 v = first->get_uv_vertex(0)->uv - origin;
+ normalize_v2(v);
+
+ float3x3 rot_mat = float3x3::from_rotation(angle_between);
+ float2 rotated = rot_mat * v;
+ float2 result = rotated * desired_len + first->get_uv_vertex(1)->uv;
+ return result;
+}
+
+/** \} */
+
/* -------------------------------------------------------------------- */
/** \name UVPrimitive
* \{ */
@@ -858,13 +879,31 @@ void UVIslands::extend_borders(const UVIslandsMask &islands_mask)
/* -------------------------------------------------------------------- */
/** \name UVIslandsMask
* \{ */
+constexpr ushort2 mask_resolution_from_tile_resolution(ushort2 tile_resolution)
+{
+ return tile_resolution;
+}
-UVIslandsMask::Tile::Tile(float2 udim_offset, ushort2 resolution)
- : udim_offset(udim_offset), resolution(resolution), mask(resolution.x * resolution.y)
+UVIslandsMask::Tile::Tile(float2 udim_offset, ushort2 tile_resolution)
+ : udim_offset(udim_offset),
+ tile_resolution(tile_resolution),
+ mask_resolution(mask_resolution_from_tile_resolution(tile_resolution)),
+ mask(mask_resolution.x * mask_resolution.y)
{
mask.fill(0xffff);
}
+bool UVIslandsMask::Tile::contains(const float2 uv) const
+{
+ const float2 tile_uv = uv - udim_offset;
+ return IN_RANGE(tile_uv.x, 0.0, 1.0f) && IN_RANGE(tile_uv.y, 0.0f, 1.0f);
+}
+
+float UVIslandsMask::Tile::get_pixel_size_in_uv_space() const
+{
+ return min_ff(1.0f / tile_resolution.x, 1.0f / tile_resolution.y);
+}
+
static void add_uv_island(UVIslandsMask::Tile &tile,
const UVIsland &uv_island,
int16_t island_index)
@@ -875,18 +914,20 @@ static void add_uv_island(UVIslandsMask::Tile &tile,
rctf uv_bounds = mesh_primitive->uv_bounds();
rcti buffer_bounds;
- buffer_bounds.xmin = max_ii(floor((uv_bounds.xmin - tile.udim_offset.x) * tile.resolution.x),
- 0);
- buffer_bounds.xmax = min_ii(ceil((uv_bounds.xmax - tile.udim_offset.x) * tile.resolution.x),
- tile.resolution.x - 1);
- buffer_bounds.ymin = max_ii(floor((uv_bounds.ymin - tile.udim_offset.y) * tile.resolution.y),
- 0);
- buffer_bounds.ymax = min_ii(ceil((uv_bounds.ymax - tile.udim_offset.y) * tile.resolution.y),
- tile.resolution.y - 1);
+ buffer_bounds.xmin = max_ii(
+ floor((uv_bounds.xmin - tile.udim_offset.x) * tile.mask_resolution.x), 0);
+ buffer_bounds.xmax = min_ii(
+ ceil((uv_bounds.xmax - tile.udim_offset.x) * tile.mask_resolution.x),
+ tile.mask_resolution.x - 1);
+ buffer_bounds.ymin = max_ii(
+ floor((uv_bounds.ymin - tile.udim_offset.y) * tile.mask_resolution.y), 0);
+ buffer_bounds.ymax = min_ii(
+ ceil((uv_bounds.ymax - tile.udim_offset.y) * tile.mask_resolution.y),
+ tile.mask_resolution.y - 1);
for (int y = buffer_bounds.ymin; y < buffer_bounds.ymax + 1; y++) {
for (int x = buffer_bounds.xmin; x < buffer_bounds.xmax + 1; x++) {
- float2 uv(float(x) / tile.resolution.x, float(y) / tile.resolution.y);
+ float2 uv(float(x) / tile.mask_resolution.x, float(y) / tile.mask_resolution.y);
float3 weights;
barycentric_weights_v2(mesh_primitive->vertices[0].uv,
mesh_primitive->vertices[1].uv,
@@ -897,7 +938,7 @@ static void add_uv_island(UVIslandsMask::Tile &tile,
continue;
}
- uint64_t offset = tile.resolution.x * y + x;
+ uint64_t offset = tile.mask_resolution.x * y + x;
tile.mask[offset] = island_index;
}
}
@@ -922,9 +963,9 @@ static bool dilate_x(UVIslandsMask::Tile &islands_mask)
{
bool changed = false;
const Array<uint16_t> prev_mask = islands_mask.mask;
- for (int y = 0; y < islands_mask.resolution.y; y++) {
- for (int x = 0; x < islands_mask.resolution.x; x++) {
- uint64_t offset = y * islands_mask.resolution.x + x;
+ for (int y = 0; y < islands_mask.mask_resolution.y; y++) {
+ for (int x = 0; x < islands_mask.mask_resolution.x; x++) {
+ uint64_t offset = y * islands_mask.mask_resolution.x + x;
if (prev_mask[offset] != 0xffff) {
continue;
}
@@ -932,7 +973,7 @@ static bool dilate_x(UVIslandsMask::Tile &islands_mask)
islands_mask.mask[offset] = prev_mask[offset - 1];
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list