44template<CoordSpace Space>
struct Vertex {
48template<CoordSpace Space>
struct Edge {
66 bounds.
xmin -= margin;
67 bounds.
xmax += margin;
68 bounds.
ymin -= margin;
69 bounds.
ymax += margin;
76 BLI_rcti_init(&clamping_bounds, 0, resolution.x - 1, 0, resolution.y - 1);
82 const int2 tile_resolution)
90 const int2 tile_resolution)
104 int num_non_manifold_edges = count_non_manifold_edges(mesh_data);
105 reserve(num_non_manifold_edges);
108 if (is_manifold(mesh_data, edge_id)) {
112 const int2 mesh_edge = mesh_data.
edges[edge_id];
115 edge.
vertex_1.coordinate = find_uv(mesh_data, tri, mesh_edge[0]);
116 edge.vertex_2.coordinate = find_uv(mesh_data, tri, mesh_edge[1]);
121 "Incorrect number of non manifold edges added. ");
125 const int2 tile_resolution)
const
130 uv_edge, image_tile, tile_resolution);
131 result.append(tile_edge);
140 for (
const int primitive_id : mesh_data.corner_tris.
index_range()) {
141 for (
const int edge_id : mesh_data.primitive_to_edge_map[primitive_id]) {
142 if (is_manifold(mesh_data, edge_id)) {
151 static bool is_manifold(
const uv_islands::MeshData &mesh_data,
const int edge_id)
153 return mesh_data.edge_to_primitive_map[edge_id].size() == 2;
156 static float2 find_uv(
const uv_islands::MeshData &mesh_data,
const int3 &tri,
int vertex_i)
158 for (
int i = 0; i < 3; i++) {
159 const int loop_i = tri[i];
160 const int vert = mesh_data.corner_verts[loop_i];
161 if (vert == vertex_i) {
162 return mesh_data.uv_map[loop_i];
174 reserve(count_nodes(pbvh, image_tile));
179 if (should_add_node(node, image_tile)) {
196 if (node.pixels_ ==
nullptr) {
199 NodeData &node_data = *
static_cast<NodeData *
>(node.pixels_);
200 if (node_data.find_tile_data(image_tile) ==
nullptr) {
207 const image::ImageTileWrapper &image_tile)
213 if (should_add_node(node, image_tile)) {
259 distance = std::numeric_limits<float>::max();
292 pixels[index++].init(position);
305 tile_pixels.pixel_rows, [&](
const PackedPixelRow &encoded_pixels) {
306 for (int x = encoded_pixels.start_image_coordinate.x;
307 x < encoded_pixels.start_image_coordinate.x + encoded_pixels.num_pixels;
310 int64_t index = encoded_pixels.start_image_coordinate.y * resolution.x + x;
311 pixels[index].type = PixelType::Brush;
312 pixels[index].distance = 0.0f;
332 max_ii(first_source.x - 1, 0),
333 min_ii(first_source.x + 1, resolution.x - 1),
334 max_ii(first_source.y - 1, 0),
335 min_ii(first_source.y + 1, resolution.y - 1));
338 int2 found_source = first_source;
339 float found_distance = std::numeric_limits<float>().max();
344 if (source == first_source) {
347 int pixel_index = sy * resolution.y + sx;
348 if (pixels[pixel_index].type != PixelType::Brush) {
353 if (new_distance < found_distance) {
354 found_distance = new_distance;
355 found_source = source;
368 if (source_1 == source_2) {
374 clamped_to_edge,
float2(destination), edge.vertex_1.coordinate, edge.vertex_2.coordinate);
376 clamped_to_edge,
float2(source_1), edge.vertex_1.coordinate, edge.vertex_2.coordinate);
378 clamped_to_edge,
float2(source_2), edge.vertex_1.coordinate, edge.vertex_2.coordinate);
381 (destination_lambda - source_1_lambda) / (source_2_lambda - source_1_lambda), 0.0f, 1.0f);
386 BLI_assert(pixel.type == PixelType::SelectedForCloserExamination);
390 pixel.copy_command.destination.x,
391 pixel.copy_command.destination.x,
392 pixel.copy_command.destination.y,
393 pixel.copy_command.destination.y);
395 clamp(bounds, resolution);
397 float found_distance = std::numeric_limits<float>().max();
398 int2 found_source(0);
401 int pixel_index = sy * resolution.x;
403 Pixel &source = pixels[pixel_index + sx];
404 if (source.
type != PixelType::Brush) {
408 float2(pixel.copy_command.destination));
409 if (new_distance < found_distance) {
410 found_source =
int2(sx, sy);
411 found_distance = new_distance;
416 if (found_distance == std::numeric_limits<float>().
max()) {
419 pixel.type = PixelType::CopyFromClosestEdge;
420 pixel.distance = found_distance;
421 pixel.copy_command.source_1 = found_source;
422 pixel.copy_command.source_2 = find_second_source(pixel.copy_command.destination, found_source);
423 pixel.copy_command.mix_factor = determine_mix_factor(pixel.copy_command.destination,
424 pixel.copy_command.source_1,
425 pixel.copy_command.source_2,
426 tile_edges[pixel.edge_index]);
434 for (int selected_pixel_index : range) {
435 Pixel ¤t_pixel = selected_pixels[selected_pixel_index];
436 find_copy_source(current_pixel, tile_edges);
445 selected_pixels.
reserve(10000);
447 for (
int tile_edge_index : tile_edges.
index_range()) {
451 clamp(edge_bounds, resolution);
455 const int64_t index = sy * resolution.x + sx;
456 Pixel &pixel = pixels[index];
457 if (pixel.type == PixelType::Brush) {
461 "PixelType::CopyFromClosestEdge isn't allowed to be set as it is set "
462 "when finding the pixels to copy.");
465 float2 closest_edge_point;
470 float distance_to_edge =
math::distance(closest_edge_point, point);
471 if (distance_to_edge < margin && distance_to_edge < pixel.distance) {
472 if (pixel.type != PixelType::SelectedForCloserExamination) {
473 selected_pixels.
append(std::reference_wrapper<Pixel>(pixel));
475 pixel.type = PixelType::SelectedForCloserExamination;
476 pixel.distance = distance_to_edge;
477 pixel.edge_index = tile_edge_index;
482 return selected_pixels;
488 std::optional<std::reference_wrapper<CopyPixelGroup>> last_group = std::nullopt;
489 std::optional<CopyPixelCommand> last_command = std::nullopt;
491 for (
const Pixel &elem : selected_pixels) {
492 if (elem.type == PixelType::CopyFromClosestEdge) {
493 if (!last_command.has_value() || !last_command->can_be_extended(elem.copy_command)) {
495 elem.copy_command.source_1,
498 copy_tile.
groups.append(new_group);
499 last_group = copy_tile.
groups.last();
505 last_group->get().num_deltas++;
506 last_command = elem.copy_command;
520 if (non_manifold_edges.
is_empty()) {
531 if (tile_buffer ==
nullptr) {
536 int2 tile_resolution(tile_buffer->
x, tile_buffer->
y);
543 Rows rows(tile_resolution, image.seam_margin);
550 rows.
pack_into(selected_pixels, copy_tile);
563 std::optional<std::reference_wrapper<CopyPixelTile>> pixel_tile =
565 if (!pixel_tile.has_value()) {
571 tile_user.
tile = tile_number;
573 if (tile_buffer ==
nullptr) {
580 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])
Contains defines and structs used throughout the imbuf module.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
constexpr IndexRange index_range() const
void append(const T &value)
IndexRange index_range() const
void reserve(const int64_t min_capacity)
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)
ccl_global const KernelWorkTile * tile
static void clamp(rcti &bounds, int2 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 const Vertex< CoordSpace::Tile > convert_coord_space(const Vertex< CoordSpace::UV > &uv_vertex, const image::ImageTileWrapper image_tile, const int2 tile_resolution)
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
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
ccl_device_inline int clamp(int a, int mn, int mx)