42template<CoordSpace Space>
struct Vertex {
46template<CoordSpace Space>
struct Edge {
74 BLI_rcti_init(&clamping_bounds, 0, resolution.x - 1, 0, resolution.y - 1);
80 const int2 tile_resolution)
88 const int2 tile_resolution)
102 int num_non_manifold_edges = count_non_manifold_edges(mesh_data);
103 reserve(num_non_manifold_edges);
104 for (
const int primitive_id : mesh_data.
corner_tris.index_range()) {
106 if (is_manifold(mesh_data, edge_id)) {
110 const int2 mesh_edge = mesh_data.
edges[edge_id];
113 edge.
vertex_1.coordinate = find_uv(mesh_data, tri, mesh_edge[0]);
114 edge.
vertex_2.coordinate = find_uv(mesh_data, tri, mesh_edge[1]);
119 "Incorrect number of non manifold edges added. ");
123 const int2 tile_resolution)
const
128 uv_edge, image_tile, tile_resolution);
138 for (
const int primitive_id : mesh_data.
corner_tris.index_range()) {
140 if (is_manifold(mesh_data, edge_id)) {
149 static bool is_manifold(
const uv_islands::MeshData &mesh_data,
const int edge_id)
151 return mesh_data.edge_to_primitive_map[edge_id].size() == 2;
154 static float2 find_uv(
const uv_islands::MeshData &mesh_data,
const int3 &tri,
int vertex_i)
156 for (
int i = 0;
i < 3;
i++) {
157 const int loop_i = tri[
i];
158 const int vert = mesh_data.corner_verts[loop_i];
159 if (vert == vertex_i) {
160 return mesh_data.uv_map[loop_i];
177 if (should_add_node(node, image_tile)) {
197 NodeData &node_data = *
static_cast<NodeData *
>(node.
pixels_);
198 if (node_data.find_tile_data(image_tile) ==
nullptr) {
205 const image::ImageTileWrapper &image_tile)
211 if (should_add_node(node, image_tile)) {
257 distance = std::numeric_limits<float>::max();
290 pixels[index++].init(position);
303 tile_pixels.pixel_rows, [&](
const PackedPixelRow &encoded_pixels) {
304 for (int x = encoded_pixels.start_image_coordinate.x;
305 x < encoded_pixels.start_image_coordinate.x + encoded_pixels.num_pixels;
308 int64_t index = encoded_pixels.start_image_coordinate.y * resolution.x + x;
309 pixels[index].type = PixelType::Brush;
310 pixels[index].distance = 0.0f;
330 max_ii(first_source.x - 1, 0),
332 max_ii(first_source.y - 1, 0),
336 int2 found_source = first_source;
337 float found_distance = std::numeric_limits<float>::max();
342 if (source == first_source) {
351 if (new_distance < found_distance) {
352 found_distance = new_distance;
353 found_source = source;
366 if (source_1 == source_2) {
379 (destination_lambda - source_1_lambda) / (source_2_lambda - source_1_lambda), 0.0f, 1.0f);
395 float found_distance = std::numeric_limits<float>::max();
396 int2 found_source(0);
407 if (new_distance < found_distance) {
408 found_source =
int2(sx, sy);
409 found_distance = new_distance;
414 if (found_distance == std::numeric_limits<float>::max()) {
432 for (int selected_pixel_index : range) {
433 Pixel ¤t_pixel = selected_pixels[selected_pixel_index];
434 find_copy_source(current_pixel, tile_edges);
443 selected_pixels.
reserve(10000);
445 for (
int tile_edge_index : tile_edges.
index_range()) {
459 "PixelType::CopyFromClosestEdge isn't allowed to be set as it is set "
460 "when finding the pixels to copy.");
462 const float2 point(sx, sy);
463 float2 closest_edge_point;
468 float distance_to_edge =
math::distance(closest_edge_point, point);
469 if (distance_to_edge <
margin && distance_to_edge < pixel.
distance) {
471 selected_pixels.
append(std::reference_wrapper<Pixel>(pixel));
480 return selected_pixels;
486 std::optional<std::reference_wrapper<CopyPixelGroup>> last_group = std::nullopt;
487 std::optional<CopyPixelCommand> last_command = std::nullopt;
489 for (
const Pixel &elem : selected_pixels) {
491 if (!last_command.has_value() || !last_command->can_be_extended(elem.copy_command)) {
493 elem.copy_command.source_1,
496 copy_tile.
groups.append(new_group);
497 last_group = copy_tile.
groups.last();
503 last_group->get().num_deltas++;
504 last_command = elem.copy_command;
518 if (non_manifold_edges.
is_empty()) {
529 if (tile_buffer ==
nullptr) {
534 int2 tile_resolution(tile_buffer->
x, tile_buffer->
y);
541 Rows rows(tile_resolution,
image.seam_margin);
548 rows.
pack_into(selected_pixels, copy_tile);
561 std::optional<std::reference_wrapper<CopyPixelTile>> pixel_tile =
563 if (!pixel_tile.has_value()) {
569 tile_user.
tile = tile_number;
571 if (tile_buffer ==
nullptr) {
578 tile.copy_pixels(*tile_buffer, range);
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
A BVH for high poly meshes.
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
#define LISTBASE_FOREACH(type, var, list)
MINLINE int min_ii(int a, int b)
MINLINE float clamp_f(float value, float min, float max)
MINLINE int max_ii(int a, int b)
float closest_to_line_segment_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2])
float closest_to_line_v2(float r_close[2], const float p[2], const float l1[2], const float l2[2])
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
void BLI_rcti_init_minmax(struct rcti *rect)
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
bool BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest)
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
void BLI_rcti_do_minmax_v(struct rcti *rect, const int xy[2])
void append(const Edge< CoordSpace::UV > &value)
IndexRange index_range() const
void reserve(const int64_t min_capacity)
void append(const T &value)
void reserve(const int64_t min_capacity)
pixels::NodeData * pixels_
std::variant< Vector< MeshNode >, Vector< GridsNode >, Vector< BMeshNode > > nodes_
NonManifoldTileEdges extract_tile_edges(const image::ImageTileWrapper image_tile, const int2 tile_resolution) const
NonManifoldUVEdges(const uv_islands::MeshData &mesh_data)
PixelNodesTileData(blender::bke::pbvh::Tree &pbvh, const image::ImageTileWrapper &image_tile)
constexpr T clamp(T, U, U) RET
const ccl_global KernelWorkTile * tile
static void clamp(rcti &bounds, int2 resolution)
static Vertex< CoordSpace::Tile > convert_coord_space(const Vertex< CoordSpace::UV > &uv_vertex, const image::ImageTileWrapper image_tile, const int2 tile_resolution)
static void add_margin(rcti &bounds, int margin)
void copy_update(blender::bke::pbvh::Tree &pbvh, Image &image, ImageUser &image_user, const uv_islands::MeshData &mesh_data)
void copy_pixels(blender::bke::pbvh::Tree &pbvh, Image &image, ImageUser &image_user, image::TileNumber tile_number)
static rcti get_bounds(const Edge< CoordSpace::Tile > &tile_edge)
const int THREADING_GRAIN_SIZE
PBVHData & data_get(blender::bke::pbvh::Tree &pbvh)
T distance(const T &a, const T &b)
void parallel_for_each(Range &&range, const Function &function)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< int32_t, 3 > int3
TileNumber get_tile_number() const
int2 get_tile_offset() const
Vector< CopyPixelGroup > groups
void print_compression_rate()
Vector< DeltaCopyPixelCommand > command_deltas
Vector< CopyPixelTile > tiles
std::optional< std::reference_wrapper< CopyPixelTile > > find_tile(image::TileNumber tile_number)
UDIMTilePixels * find_tile_data(const image::ImageTileWrapper &image_tile)
CopyPixelTiles tiles_copy_pixels
CopyPixelCommand copy_command
void init(int2 coordinate)
MutableSpan< Pixel > pixels
RowView(Rows &rows, int64_t row_number)
void pack_into(const Span< std::reference_wrapper< Pixel > > selected_pixels, CopyPixelTile ©_tile) const
@ SelectedForCloserExamination
Vector< std::reference_wrapper< Pixel > > filter_pixels_for_closer_examination(const NonManifoldTileEdges &tile_edges)
void mark_pixels_effected_by_brush(const PixelNodesTileData &nodes_tile_pixels)
Rows(int2 resolution, int margin)
void find_copy_source(Pixel &pixel, const NonManifoldTileEdges &tile_edges)
void find_copy_source(Vector< std::reference_wrapper< Pixel > > &selected_pixels, const NonManifoldTileEdges &tile_edges)
float determine_mix_factor(const int2 destination, const int2 source_1, const int2 source_2, const Edge< CoordSpace::Tile > &edge)
int2 find_second_source(int2 destination, int2 first_source)
TriangleToEdgeMap primitive_to_edge_map