[Bf-blender-cvs] [94463e66fd3] temp-T101739-fix-seam-bleeding-non-manifold: Improve mix factor calculation.
Jeroen Bakker
noreply at git.blender.org
Fri Jan 13 11:36:44 CET 2023
Commit: 94463e66fd3aa3f3011540a30117c5a299ba663b
Author: Jeroen Bakker
Date: Fri Jan 13 10:52:06 2023 +0100
Branches: temp-T101739-fix-seam-bleeding-non-manifold
https://developer.blender.org/rB94463e66fd3aa3f3011540a30117c5a299ba663b
Improve mix factor calculation.
===================================================================
M source/blender/blenkernel/intern/pbvh_pixels_copy.cc
===================================================================
diff --git a/source/blender/blenkernel/intern/pbvh_pixels_copy.cc b/source/blender/blenkernel/intern/pbvh_pixels_copy.cc
index 297d6f0123e..1fc553097f2 100644
--- a/source/blender/blenkernel/intern/pbvh_pixels_copy.cc
+++ b/source/blender/blenkernel/intern/pbvh_pixels_copy.cc
@@ -233,6 +233,13 @@ struct Rows {
PixelType type = PixelType::Undecided;
float distance = std::numeric_limits<float>::max();
CopyPixelCommand copy_command;
+ /**
+ * Index of the edge in the list of non-manifold edges.
+ *
+ * The edge is kept to calculate athe mix factor between the two pixels that have chosen to
+ * be mixed.
+ */
+ int64_t edge_index = -1;
Pixel() = default;
@@ -260,7 +267,10 @@ struct Rows {
}
}
- void mask_brush_pixels(const PixelNodesTileData &nodes_tile_pixels)
+ /**
+ * Mark pixels that are painted on by the brush. Those pixels don't need to be updated.
+ */
+ void mark_pixels_effected_by_brush(const PixelNodesTileData &nodes_tile_pixels)
{
for (const UDIMTilePixels &tile_pixels : nodes_tile_pixels) {
for (const PackedPixelRow &encoded_pixels : tile_pixels.pixel_rows) {
@@ -277,9 +287,14 @@ struct Rows {
}
}
+ /**
+ * Mark pixels that needs to be evaluated. Pixels that are marked will have its `edge_index`
+ * filled.
+ */
void mark_for_evaluation(const Rows &rows, const NonManifoldTileEdges &tile_edges)
{
- for (const Edge<CoordSpace::Tile> &tile_edge : tile_edges) {
+ for (int tile_edge_index : tile_edges.index_range()) {
+ const Edge<CoordSpace::Tile> &tile_edge = tile_edges[tile_edge_index];
rcti edge_bounds = get_bounds(tile_edge);
add_margin(edge_bounds, rows.margin);
clamp(edge_bounds, rows.resolution);
@@ -293,9 +308,12 @@ struct Rows {
for (const int x : IndexRange(edge_bounds.xmin, BLI_rcti_size_x(&edge_bounds))) {
Pixel &pixel = pixels[x];
- if (pixel.type != PixelType::Undecided) {
+ if (pixel.type == PixelType::Brush) {
continue;
}
+ BLI_assert_msg(pixel.type != PixelType::CopyFromClosestEdge,
+ "PixelType::CopyFromClosestEdge isn't allowed to be set as it is set "
+ "when finding the pixels to copy.");
const float2 point(pixel.copy_command.destination);
float2 closest_edge_point;
@@ -304,13 +322,25 @@ struct Rows {
tile_edge.vertex_1.coordinate,
tile_edge.vertex_2.coordinate);
float distance_to_edge = blender::math::distance(closest_edge_point, point);
- if (distance_to_edge < rows.margin) {
+ if (distance_to_edge < rows.margin && distance_to_edge < pixel.distance) {
pixel.type = PixelType::Selected;
+ pixel.distance = distance_to_edge;
+ pixel.edge_index = tile_edge_index;
}
}
}
}
+ /**
+ * Look for a second source pixel that will be blended with the first source pixel to improve
+ * the quality of the fix.
+ *
+ * - The second source pixel must be a neighbour pixel of the first source, or the same as the
+ * first source when no second pixel could be found.
+ * - The second source pixel must be a pixel that is painted on by the brush.
+ * - The second source pixel must be the second closest pixel , or the first source
+ * when no second pixel could be found.
+ */
int2 find_second_source(Rows &rows, int2 destination, int2 first_source)
{
rcti search_bounds;
@@ -344,15 +374,32 @@ struct Rows {
return found_source;
}
- float determine_mix_factor(int2 destination, int2 source_1, int2 source_2)
+ float determine_mix_factor(const int2 destination,
+ const int2 source_1,
+ const int2 source_2,
+ const Edge<CoordSpace::Tile> &edge)
{
+ /* Use stable result when both sources are the same. */
if (source_1 == source_2) {
return 0.0f;
}
- return dist_to_line_segment_v2(float2(destination), float2(source_1), float2(source_2));
+
+ float2 clamped_to_edge;
+ float destination_lambda = closest_to_line_v2(clamped_to_edge,
+ float2(destination),
+ edge.vertex_1.coordinate,
+ edge.vertex_2.coordinate);
+ float source_1_lambda = closest_to_line_v2(
+ clamped_to_edge, float2(source_1), edge.vertex_1.coordinate, edge.vertex_2.coordinate);
+ float source_2_lambda = closest_to_line_v2(
+ clamped_to_edge, float2(source_2), edge.vertex_1.coordinate, edge.vertex_2.coordinate);
+
+ return clamp_f((destination_lambda - source_1_lambda) / (source_2_lambda - source_1_lambda),
+ 0.0f,
+ 1.0f);
}
- void find_copy_source(Rows &rows)
+ void find_copy_source(Rows &rows, const NonManifoldTileEdges &tile_edges)
{
for (int x : pixels.index_range()) {
Pixel &elem = pixels[x];
@@ -365,6 +412,8 @@ struct Rows {
BLI_rcti_init(&bounds, x, x, row_number, row_number);
add_margin(bounds, rows.margin);
clamp(bounds, rows.resolution);
+ // TODO: improvement is to clamp it with the bounds of the edge that is assigned to the
+ // pixel.
float found_distance = std::numeric_limits<float>().max();
int2 found_source(0);
@@ -392,8 +441,10 @@ struct Rows {
elem.copy_command.source_1 = found_source;
elem.copy_command.source_2 = find_second_source(
rows, elem.copy_command.destination, found_source);
- elem.copy_command.mix_factor = determine_mix_factor(
- elem.copy_command.destination, elem.copy_command.source_1, elem.copy_command.source_2);
+ elem.copy_command.mix_factor = determine_mix_factor(elem.copy_command.destination,
+ elem.copy_command.source_1,
+ elem.copy_command.source_2,
+ tile_edges[elem.edge_index]);
}
}
@@ -475,14 +526,14 @@ struct Rows {
rows.resize(resolution.y, row_template);
for (int row_number : rows.index_range()) {
rows[row_number].reinit(row_number);
- rows[row_number].mask_brush_pixels(node_tile_pixels);
+ rows[row_number].mark_pixels_effected_by_brush(node_tile_pixels);
}
}
- void find_copy_source()
+ void find_copy_source(const NonManifoldTileEdges &tile_edges)
{
for (Row &row : rows) {
- row.find_copy_source(*this);
+ row.find_copy_source(*this, tile_edges);
}
}
@@ -500,8 +551,8 @@ struct Rows {
}
/* Shrink vectors to fit the actual data it contains. From now on these vectors should be
* immutable. */
- //copy_tile.groups.resize(copy_tile.groups.size());
- //copy_tile.command_deltas.resize(copy_tile.command_deltas.size());
+ // copy_tile.groups.resize(copy_tile.groups.size());
+ // copy_tile.command_deltas.resize(copy_tile.command_deltas.size());
}
void print_debug() const
@@ -553,7 +604,7 @@ void BKE_pbvh_pixels_copy_update(PBVH &pbvh,
Rows rows(tile_resolution, image.seam_margin, nodes_tile_pixels);
rows.mark_for_evaluation(tile_edges);
- rows.find_copy_source();
+ rows.find_copy_source(tile_edges);
rows.pack_into(copy_tile);
copy_tile.print_compression_rate();
pbvh_data.tiles_copy_pixels.tiles.append(copy_tile);
More information about the Bf-blender-cvs
mailing list