Refactor: Sculpt: Remove unhelpful image paint data storage abstractions

This commit is contained in:
Hans Goudey
2024-08-06 15:20:21 -04:00
parent 5bf8993661
commit 1a64ed7f7d
3 changed files with 32 additions and 110 deletions
+7 -79
View File
@@ -17,46 +17,9 @@
namespace blender::bke::pbvh::pixels {
/**
* Data shared between pixels that belong to the same triangle.
*
* Data is stored as a list of structs, grouped by usage to improve performance (improves CPU
* cache prefetching).
*/
struct PaintGeometryPrimitives {
/** Data accessed by the inner loop of the painting brush. */
Vector<int3> vert_indices;
public:
void append(const int3 vert_indices)
{
this->vert_indices.append(vert_indices);
}
const int3 &get_vert_indices(const int index) const
{
return vert_indices[index];
}
void clear()
{
vert_indices.clear();
}
int64_t size() const
{
return vert_indices.size();
}
int64_t mem_size() const
{
return this->vert_indices.as_span().size_in_bytes();
}
};
struct UVPrimitivePaintInput {
/** Corresponding index into PaintGeometryPrimitives */
int64_t geometry_primitive_index;
/** Corresponding index into triangles */
int64_t tri_index;
/**
* Delta barycentric coordinates between 2 neighboring UVs in the U direction.
*
@@ -70,47 +33,12 @@ struct UVPrimitivePaintInput {
* delta_barycentric_coord_u is initialized in a later stage as it requires image tile
* dimensions.
*/
UVPrimitivePaintInput(int64_t geometry_primitive_index)
: geometry_primitive_index(geometry_primitive_index), delta_barycentric_coord_u(0.0f, 0.0f)
UVPrimitivePaintInput(int64_t tri_index)
: tri_index(tri_index), delta_barycentric_coord_u(0.0f, 0.0f)
{
}
};
struct PaintUVPrimitives {
/** Data accessed by the inner loop of the painting brush. */
Vector<UVPrimitivePaintInput> paint_input;
void append(int64_t geometry_primitive_index)
{
this->paint_input.append(UVPrimitivePaintInput(geometry_primitive_index));
}
UVPrimitivePaintInput &last()
{
return paint_input.last();
}
const UVPrimitivePaintInput &get_paint_input(uint64_t index) const
{
return paint_input[index];
}
void clear()
{
paint_input.clear();
}
int64_t size() const
{
return paint_input.size();
}
int64_t mem_size() const
{
return size() * sizeof(UVPrimitivePaintInput);
}
};
/**
* Encode sequential pixels to reduce memory footprint.
*/
@@ -179,7 +107,7 @@ struct NodeData {
Vector<UDIMTilePixels> tiles;
Vector<UDIMTileUndo> undo_regions;
PaintUVPrimitives uv_primitives;
Vector<UVPrimitivePaintInput> uv_primitives;
NodeData()
{
@@ -411,14 +339,14 @@ struct CopyPixelTiles {
*/
struct PBVHData {
/* Per UVPRimitive contains the paint data. */
PaintGeometryPrimitives geom_primitives;
Array<int3> vert_tris;
/** Per ImageTile the pixels to copy to fix non-manifold bleeding. */
CopyPixelTiles tiles_copy_pixels;
void clear_data()
{
geom_primitives.clear();
this->vert_tris = {};
}
};
@@ -185,8 +185,8 @@ static void split_pixel_node(
UDIMTilePixels *tile1 = &data1->tiles[i];
UDIMTilePixels *tile2 = &data2->tiles[i];
UVPrimitivePaintInput &uv_prim = data.uv_primitives.paint_input[row.uv_primitive_index];
int3 tri = pbvh_data.geom_primitives.vert_indices[uv_prim.geometry_primitive_index];
const UVPrimitivePaintInput uv_prim = data.uv_primitives[row.uv_primitive_index];
const int3 &tri = pbvh_data.vert_tris[uv_prim.tri_index];
float verts[3][3];
@@ -406,12 +406,9 @@ static void extract_barycentric_pixels(UDIMTilePixels &tile_data,
static void update_geom_primitives(Tree &pbvh, const uv_islands::MeshData &mesh_data)
{
PBVHData &pbvh_data = data_get(pbvh);
pbvh_data.clear_data();
for (const int3 &tri : mesh_data.corner_tris) {
pbvh_data.geom_primitives.append(int3(mesh_data.corner_verts[tri[0]],
mesh_data.corner_verts[tri[1]],
mesh_data.corner_verts[tri[2]]));
}
pbvh_data.vert_tris.reinitialize(mesh_data.corner_tris.size());
bke::mesh::vert_tris_from_corner_tris(
mesh_data.corner_verts, mesh_data.corner_tris, pbvh_data.vert_tris);
}
struct UVPrimitiveLookup {
@@ -154,18 +154,17 @@ template<typename ImageBuffer> class PaintingKernel {
init_brush_test();
}
bool paint(const PaintGeometryPrimitives &geom_primitives,
const PaintUVPrimitives &uv_primitives,
bool paint(const Span<int3> vert_tris,
const Span<UVPrimitivePaintInput> uv_primitives,
const PackedPixelRow &pixel_row,
ImBuf *image_buffer,
auto_mask::NodeData *automask_data)
{
image_accessor_.set_image_position(image_buffer, pixel_row.start_image_coordinate);
const UVPrimitivePaintInput paint_input = uv_primitives.get_paint_input(
pixel_row.uv_primitive_index);
float3 pixel_pos = get_start_pixel_pos(geom_primitives, paint_input, pixel_row);
const UVPrimitivePaintInput paint_input = uv_primitives[pixel_row.uv_primitive_index];
float3 pixel_pos = get_start_pixel_pos(vert_tris, paint_input, pixel_row);
const float3 delta_pixel_pos = get_delta_pixel_pos(
geom_primitives, paint_input, pixel_row, pixel_pos);
vert_tris, paint_input, pixel_row, pixel_pos);
bool pixels_painted = false;
for (int x = 0; x < pixel_row.num_pixels; x++) {
if (!brush_test_fn_(test_, pixel_pos)) {
@@ -249,35 +248,34 @@ template<typename ImageBuffer> class PaintingKernel {
/**
* Extract the starting pixel position from the given encoded_pixels belonging to the triangle.
*/
float3 get_start_pixel_pos(const PaintGeometryPrimitives &geom_primitives,
float3 get_start_pixel_pos(const Span<int3> vert_tris,
const UVPrimitivePaintInput &paint_input,
const PackedPixelRow &encoded_pixels) const
{
return init_pixel_pos(geom_primitives, paint_input, encoded_pixels.start_barycentric_coord);
return init_pixel_pos(vert_tris, paint_input, encoded_pixels.start_barycentric_coord);
}
/**
* Extract the delta pixel position that will be used to advance a Pixel instance to the next
* pixel.
*/
float3 get_delta_pixel_pos(const PaintGeometryPrimitives &geom_primitives,
float3 get_delta_pixel_pos(const Span<int3> vert_tris,
const UVPrimitivePaintInput &paint_input,
const PackedPixelRow &encoded_pixels,
const float3 &start_pixel) const
{
float3 result = init_pixel_pos(geom_primitives,
float3 result = init_pixel_pos(vert_tris,
paint_input,
encoded_pixels.start_barycentric_coord +
paint_input.delta_barycentric_coord_u);
return result - start_pixel;
}
float3 init_pixel_pos(const PaintGeometryPrimitives &geom_primitives,
float3 init_pixel_pos(const Span<int3> vert_tris,
const UVPrimitivePaintInput &paint_input,
const float2 &barycentric_weights) const
{
const int3 &vert_indices = geom_primitives.get_vert_indices(
paint_input.geometry_primitive_index);
const int3 &vert_indices = vert_tris[paint_input.tri_index];
float3 result;
const float3 barycentric(barycentric_weights.x,
barycentric_weights.y,
@@ -292,8 +290,8 @@ template<typename ImageBuffer> class PaintingKernel {
};
static BitVector<> init_uv_primitives_brush_test(SculptSession &ss,
PaintGeometryPrimitives &geom_primitives,
PaintUVPrimitives &uv_primitives,
const Span<int3> vert_tris,
const Span<UVPrimitivePaintInput> uv_primitives,
const Span<float3> positions)
{
BitVector<> brush_test(uv_primitives.size());
@@ -305,10 +303,9 @@ static BitVector<> init_uv_primitives_brush_test(SculptSession &ss,
float3 brush_max_bounds(test.location[0] + test.radius,
test.location[1] + test.radius,
test.location[2] + test.radius);
for (int uv_prim_index = 0; uv_prim_index < uv_primitives.size(); uv_prim_index++) {
const UVPrimitivePaintInput &paint_input = uv_primitives.get_paint_input(uv_prim_index);
const int3 &vert_indices = geom_primitives.get_vert_indices(
paint_input.geometry_primitive_index);
for (const int i : uv_primitives.index_range()) {
const UVPrimitivePaintInput &paint_input = uv_primitives[i];
const int3 &vert_indices = vert_tris[paint_input.tri_index];
float3 triangle_min_bounds(positions[vert_indices[0]]);
float3 triangle_max_bounds(triangle_min_bounds);
@@ -321,7 +318,7 @@ static BitVector<> init_uv_primitives_brush_test(SculptSession &ss,
triangle_max_bounds.y = max_ff(triangle_max_bounds.y, pos.y);
triangle_max_bounds.z = max_ff(triangle_max_bounds.z, pos.z);
}
brush_test[uv_prim_index].set(isect_aabb_aabb_v3(
brush_test[i].set(isect_aabb_aabb_v3(
brush_min_bounds, brush_max_bounds, triangle_min_bounds, triangle_max_bounds));
}
return brush_test;
@@ -340,7 +337,7 @@ static void do_paint_pixels(TexturePaintingUserData *data, const int n)
const Span<float3> positions = SCULPT_mesh_deformed_positions_get(ss);
BitVector<> brush_test = init_uv_primitives_brush_test(
ss, pbvh_data.geom_primitives, node_data.uv_primitives, positions);
ss, pbvh_data.vert_tris, node_data.uv_primitives, positions);
PaintingKernel<ImageBufferFloat4> kernel_float4(ss, brush, thread_id, positions);
PaintingKernel<ImageBufferByte4> kernel_byte4(ss, brush, thread_id, positions);
@@ -390,14 +387,14 @@ static void do_paint_pixels(TexturePaintingUserData *data, const int n)
}
bool pixels_painted = false;
if (image_buffer->float_buffer.data != nullptr) {
pixels_painted = kernel_float4.paint(pbvh_data.geom_primitives,
pixels_painted = kernel_float4.paint(pbvh_data.vert_tris,
node_data.uv_primitives,
pixel_row,
image_buffer,
&automask_data);
}
else {
pixels_painted = kernel_byte4.paint(pbvh_data.geom_primitives,
pixels_painted = kernel_byte4.paint(pbvh_data.vert_tris,
node_data.uv_primitives,
pixel_row,
image_buffer,