[Bf-blender-cvs] [64e535cab51] temp-3d-texturing-brush-b: Use pixel encoding to reduce memory needs.
Jeroen Bakker
noreply at git.blender.org
Mon Mar 14 14:54:15 CET 2022
Commit: 64e535cab51cd0f8632dc6be756a4ea671961e85
Author: Jeroen Bakker
Date: Mon Mar 14 14:54:06 2022 +0100
Branches: temp-3d-texturing-brush-b
https://developer.blender.org/rB64e535cab51cd0f8632dc6be756a4ea671961e85
Use pixel encoding to reduce memory needs.
===================================================================
M source/blender/editors/sculpt_paint/CMakeLists.txt
A source/blender/editors/sculpt_paint/sculpt_texture_paint_d.cc
M source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh
A source/blender/editors/sculpt_paint/sculpt_texture_paint_pixel_extraction_d.cc
===================================================================
diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt
index 3fa8eed7338..3c82c07c604 100644
--- a/source/blender/editors/sculpt_paint/CMakeLists.txt
+++ b/source/blender/editors/sculpt_paint/CMakeLists.txt
@@ -65,9 +65,11 @@ set(SRC
sculpt_paint_color.c
sculpt_pose.c
sculpt_smooth.c
- sculpt_texture_paint_b.cc
- sculpt_texture_paint_pixel_extraction_b.cc
+ #sculpt_texture_paint_b.cc
+ sculpt_texture_paint_d.cc
+ #sculpt_texture_paint_pixel_extraction_b.cc
#sculpt_texture_paint_pixel_extraction_c.cc
+ sculpt_texture_paint_pixel_extraction_d.cc
sculpt_transform.c
sculpt_undo.c
sculpt_uv.c
diff --git a/source/blender/editors/sculpt_paint/sculpt_texture_paint_d.cc b/source/blender/editors/sculpt_paint/sculpt_texture_paint_d.cc
new file mode 100644
index 00000000000..b28332b3d16
--- /dev/null
+++ b/source/blender/editors/sculpt_paint/sculpt_texture_paint_d.cc
@@ -0,0 +1,269 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup edsculpt
+ */
+
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_brush.h"
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_image.h"
+#include "BKE_material.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_mapping.h"
+#include "BKE_pbvh.h"
+
+#include "PIL_time_utildefines.h"
+
+#include "BLI_math_color_blend.h"
+#include "BLI_task.h"
+#include "BLI_vector.hh"
+
+#include "IMB_rasterizer.hh"
+
+#include "WM_types.h"
+
+#include "bmesh.h"
+
+#include "ED_uvedit.h"
+
+#include "sculpt_intern.h"
+#include "sculpt_texture_paint_intern.hh"
+
+namespace blender::ed::sculpt_paint::texture_paint {
+namespace painting {
+
+static Pixel get_start_pixel(const PixelsPackage &encoded_pixels,
+ const Vector<Triangle> &triangles,
+ const MVert *mvert,
+ const MLoopUV *ldata_uv)
+{
+ Pixel result;
+ const Triangle &triangle = triangles[encoded_pixels.triangle_index];
+ const float3 weights = encoded_pixels.start_edge_coord;
+ interp_v3_v3v3v3(result.pos,
+ mvert[triangle.vert_indices[0]].co,
+ mvert[triangle.vert_indices[1]].co,
+ mvert[triangle.vert_indices[2]].co,
+ weights);
+ interp_v3_v3v3v3(result.uv,
+ ldata_uv[triangle.loop_indices[0]].uv,
+ ldata_uv[triangle.loop_indices[1]].uv,
+ ldata_uv[triangle.loop_indices[2]].uv,
+ weights);
+
+ return result;
+}
+
+static Pixel get_delta_pixel(const PixelsPackage &encoded_pixels,
+ const Vector<Triangle> &triangles,
+ const Pixel &start_pixel,
+ const MVert *mvert,
+ const MLoopUV *ldata_uv
+
+)
+{
+ Pixel result;
+ const Triangle &triangle = triangles[encoded_pixels.triangle_index];
+ const float3 weights = encoded_pixels.start_edge_coord + triangle.add_edge_coord_x;
+ interp_v3_v3v3v3(result.pos,
+ mvert[triangle.vert_indices[0]].co,
+ mvert[triangle.vert_indices[1]].co,
+ mvert[triangle.vert_indices[2]].co,
+ weights);
+ interp_v3_v3v3v3(result.uv,
+ ldata_uv[triangle.loop_indices[0]].uv,
+ ldata_uv[triangle.loop_indices[1]].uv,
+ ldata_uv[triangle.loop_indices[2]].uv,
+ weights);
+ result.pos -= start_pixel.pos;
+ result.uv -= start_pixel.uv;
+ return result;
+}
+
+static void add(Pixel &dst, const Pixel &lh)
+{
+ dst.pos += lh.pos;
+ dst.uv += lh.uv;
+}
+
+static void do_task_cb_ex(void *__restrict userdata,
+ const int n,
+ const TaskParallelTLS *__restrict tls)
+{
+ TexturePaintingUserData *data = static_cast<TexturePaintingUserData *>(userdata);
+ Object *ob = data->ob;
+ SculptSession *ss = ob->sculpt;
+ ImBuf *image_buffer = ss->mode.texture_paint.drawing_target;
+ const Brush *brush = data->brush;
+ PBVHNode *node = data->nodes[n];
+ NodeData *node_data = static_cast<NodeData *>(BKE_pbvh_node_texture_paint_data_get(node));
+ BLI_assert(node_data != nullptr);
+
+ const int thread_id = BLI_task_parallel_thread_id(tls);
+
+ SculptBrushTest test;
+ SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
+ ss, &test, brush->falloff_shape);
+
+ float3 brush_srgb(brush->rgb[0], brush->rgb[1], brush->rgb[2]);
+ float4 brush_linear;
+ srgb_to_linearrgb_v3_v3(brush_linear, brush_srgb);
+ brush_linear[3] = 1.0f;
+ MVert *mvert = SCULPT_mesh_deformed_mverts_get(ss);
+ Mesh *mesh = static_cast<Mesh *>(ob->data);
+ MLoopUV *ldata_uv = static_cast<MLoopUV *>(CustomData_get_layer(&mesh->ldata, CD_MLOOPUV));
+
+ const float brush_strength = ss->cache->bstrength;
+
+ for (PixelsPackage &encoded_pixels : node_data->encoded_pixels) {
+ Triangle &triangle = node_data->triangles[encoded_pixels.triangle_index];
+ int pixel_offset = encoded_pixels.start_image_coordinate.y * image_buffer->x +
+ encoded_pixels.start_image_coordinate.x;
+ float3 edge_coord = encoded_pixels.start_edge_coord;
+ Pixel pixel = get_start_pixel(encoded_pixels, node_data->triangles, mvert, ldata_uv);
+ const Pixel add_pixel = get_delta_pixel(
+ encoded_pixels, node_data->triangles, pixel, mvert, ldata_uv);
+ bool pixels_painted = false;
+ for (int x = 0; x < encoded_pixels.num_pixels; x++) {
+ if (!sculpt_brush_test_sq_fn(&test, pixel.pos)) {
+ add(pixel, add_pixel);
+ pixel_offset += 1;
+ continue;
+ }
+
+ float *color = &image_buffer->rect_float[pixel_offset * 4];
+ const float3 normal(0.0f, 0.0f, 0.0f);
+ const float3 face_normal(0.0f, 0.0f, 0.0f);
+ const float mask = 0.0f;
+ const float falloff_strength = SCULPT_brush_strength_factor(
+ ss, brush, pixel.pos, sqrtf(test.dist), normal, face_normal, mask, 0, thread_id);
+
+ blend_color_interpolate_float(color, color, brush_linear, falloff_strength * brush_strength);
+ pixels_painted = true;
+
+ edge_coord += triangle.add_edge_coord_x;
+ pixel_offset++;
+ add(pixel, add_pixel);
+ }
+
+ if (pixels_painted) {
+ BLI_rcti_do_minmax_v(&node_data->dirty_region, encoded_pixels.start_image_coordinate);
+ BLI_rcti_do_minmax_v(
+ &node_data->dirty_region,
+ int2(encoded_pixels.start_image_coordinate.x + encoded_pixels.num_pixels + 1,
+ encoded_pixels.start_image_coordinate.y));
+ node_data->flags.dirty = true;
+ }
+ }
+}
+} // namespace painting
+
+struct ImageData {
+ void *lock = nullptr;
+ Image *image = nullptr;
+ ImageUser *image_user = nullptr;
+ ImBuf *image_buffer = nullptr;
+
+ ~ImageData()
+ {
+ BKE_image_release_ibuf(image, image_buffer, lock);
+ }
+
+ static bool init_active_image(Object *ob, ImageData *r_image_data)
+ {
+ ED_object_get_active_image(
+ ob, 1, &r_image_data->image, &r_image_data->image_user, nullptr, nullptr);
+ if (r_image_data->image == nullptr) {
+ return false;
+ }
+ r_image_data->image_buffer = BKE_image_acquire_ibuf(
+ r_image_data->image, r_image_data->image_user, &r_image_data->lock);
+ if (r_image_data->image_buffer == nullptr) {
+ return false;
+ }
+ return true;
+ }
+};
+
+extern "C" {
+void SCULPT_do_texture_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+{
+ SculptSession *ss = ob->sculpt;
+ Brush *brush = BKE_paint_brush(&sd->paint);
+
+ ImageData image_data;
+ if (!ImageData::init_active_image(ob, &image_data)) {
+ return;
+ }
+
+ ss->mode.texture_paint.drawing_target = image_data.image_buffer;
+
+ TexturePaintingUserData data = {nullptr};
+ data.ob = ob;
+ data.brush = brush;
+ data.nodes = nodes;
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+
+ TIMEIT_START(texture_painting);
+ BLI_task_parallel_range(0, totnode, &data, painting::do_task_cb_ex, &settings);
+ TIMEIT_END(texture_painting);
+
+ ss->mode.texture_paint.drawing_target = nullptr;
+}
+
+void SCULPT_init_texture_paint(Object *ob)
+{
+ SculptSession *ss = ob->sculpt;
+ ImageData image_data;
+ if (!ImageData::init_active_image(ob, &image_data)) {
+ return;
+ }
+ ss->mode.texture_paint.drawing_target = image_data.image_buffer;
+ PBVHNode **nodes;
+ int totnode;
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ SCULPT_extract_pixels(ob, nodes, totnode);
+
+ MEM_freeN(nodes);
+
+ ss->mode.texture_paint.drawing_target = nullptr;
+}
+
+void SCULPT_flush_texture_paint(Object *ob)
+{
+ ImageData image_data;
+ if (!ImageData::init_active_image(ob, &image_data)) {
+ return;
+ }
+
+ SculptSession *ss = ob->sculpt;
+ PBVHNode **nodes;
+ int totnode;
+ BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode);
+ for (int n = 0; n < totnode; n++) {
+ PBVHNode *node = nodes[n];
+ NodeData *data = static_cast<NodeData *>(BKE_pbvh_node_texture_paint_data_get(node));
+ if (data == nullptr) {
+ continue;
+ }
+
+ if (data->flags.dirty) {
+ data->flush(*image_data.image_buffer);
+ data->mark_region(*image_data.image, *image_data.image_buffer);
+ }
+ }
+
+ MEM_freeN(nodes);
+}
+}
+} // namespace blender::ed::sculpt_paint::texture_paint
diff --git a/source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh b/source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh
index 31864148588..12aa041ab69 100644
--- a/source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh
+++ b/source/blender/editors/sculpt_paint/sculpt_texture_paint_intern.hh
@@ -1,5 +1,27 @@
namespace blender::ed::sculpt_paint::texture_paint {
+struct Polygon {
+};
+
+struct Triangle {
+ int3 loop_indices;
+ int3 vert_indices;
+ int poly_index;
+ float3 add_edge_coord_x;
+};
+
+struct
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list