[Bf-blender-cvs] [0cd71774209] temp-3d-texturing-brush-b: Use different rasterization.

Jeroen Bakker noreply at git.blender.org
Tue Mar 8 15:17:37 CET 2022


Commit: 0cd7177420959f6caf6eab08145e32fe085c685f
Author: Jeroen Bakker
Date:   Tue Mar 8 15:17:33 2022 +0100
Branches: temp-3d-texturing-brush-b
https://developer.blender.org/rB0cd7177420959f6caf6eab08145e32fe085c685f

Use different rasterization.

===================================================================

M	source/blender/editors/sculpt_paint/sculpt.c
M	source/blender/editors/sculpt_paint/sculpt_intern.h
M	source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc

===================================================================

diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index f6b334f2175..f19c3c66c9a 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -3171,6 +3171,10 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
     return;
   }
 
+  if (brush->sculpt_tool == SCULPT_TOOL_TEXTURE_PAINT && type != PBVH_FACES) {
+    return;
+  }
+
   /* Build a list of all nodes that are potentially within the brush's area of influence */
 
   if (SCULPT_tool_needs_all_pbvh_nodes(brush)) {
@@ -3216,6 +3220,11 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe
     }
   }
 
+  if (brush->sculpt_tool == SCULPT_TOOL_TEXTURE_PAINT) {
+    /* TODO should perhaps move to higher level.... doing this per step is not needed. */
+    SCULPT_init_texture_paint(ob);
+  }
+
   /* For anchored brushes with spherical falloff, we start off with zero radius, thus we have no
    * PBVH nodes on the first brush step. */
   if (totnode ||
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 39aaf4d1276..93bb8fb4fe3 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -1614,6 +1614,7 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in
 /* Paint Brush. */
 void SCULPT_do_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
 void SCULPT_do_texture_paint_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode);
+void SCULPT_init_texture_paint(Object *ob);
 void SCULPT_flush_texture_paint(Object *ob);
 
 /* Smear Brush. */
diff --git a/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc b/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc
index 05708cc47bb..de450b061f4 100644
--- a/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc
+++ b/source/blender/editors/sculpt_paint/sculpt_texture_paint_b.cc
@@ -60,20 +60,18 @@ struct NodeData {
     BLI_rcti_init_minmax(&dirty_region);
   }
 
-  void init_pixels(Object *ob, PBVHNode *node, ImBuf *image_buffer);
+  void init_pixels_rasterization(Object *ob, PBVHNode *node, ImBuf *image_buffer);
+
   void flush(ImBuf &image_buffer)
   {
     flags.dirty = false;
-    int pixels_flushed = 0;
     for (PixelData &pixel : pixels) {
       if (pixel.flags.dirty) {
         const int pixel_offset = (pixel.pixel_pos[1] * image_buffer.x + pixel.pixel_pos[0]) * 4;
         copy_v4_v4(&image_buffer.rect_float[pixel_offset], pixel.content);
         pixel.flags.dirty = false;
-        pixels_flushed += 1;
       }
     }
-    printf("%s: %d pixels flushed\n", __func__, pixels_flushed);
   }
 
   void mark_region(Image &image, ImBuf &image_buffer)
@@ -198,9 +196,8 @@ using RasterizerType = Rasterizer<VertexShader, FragmentShader, AddPixel, NodeDa
 
 }  // namespace shaders
 
-void NodeData::init_pixels(Object *ob, PBVHNode *node, ImBuf *image_buffer)
+void NodeData::init_pixels_rasterization(Object *ob, PBVHNode *node, ImBuf *image_buffer)
 {
-  printf("%s\n", __func__);
   Mesh *mesh = static_cast<Mesh *>(ob->data);
   MLoopUV *ldata_uv = static_cast<MLoopUV *>(CustomData_get_layer(&mesh->ldata, CD_MLOOPUV));
   if (ldata_uv == nullptr) {
@@ -228,7 +225,6 @@ void NodeData::init_pixels(Object *ob, PBVHNode *node, ImBuf *image_buffer)
       }
 
       const MLoop *loopstart = &ss->mloop[p->loopstart];
-
       for (int triangle = 0; triangle < p->totloop - 2; triangle++) {
         const int v1_index = loopstart[0].v;
         const int v2_index = loopstart[triangle + 1].v;
@@ -264,6 +260,7 @@ static void do_task_cb_ex(void *__restrict userdata,
   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);
 
   SculptBrushTest test;
   SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape(
@@ -275,10 +272,274 @@ static void do_task_cb_ex(void *__restrict userdata,
     }
     const float falloff_strength = BKE_brush_curve_strength(brush, sqrtf(test.dist), test.radius);
     interp_v3_v3v3(pixel.content, pixel.content, brush->rgb, falloff_strength);
+    pixel.content[3] = 1.0f;
     pixel.flags.dirty = true;
     BLI_rcti_do_minmax_v(&node_data->dirty_region, pixel.pixel_pos);
+    node_data->flags.dirty = true;
   }
-  node_data->flags.dirty = true;
+}
+
+static void init_rasterization_task_cb_ex(void *__restrict userdata,
+                                          const int n,
+                                          const TaskParallelTLS *__restrict UNUSED(tls))
+{
+  TexturePaintingUserData *data = static_cast<TexturePaintingUserData *>(userdata);
+  Object *ob = data->ob;
+  SculptSession *ss = ob->sculpt;
+  PBVHNode *node = data->nodes[n];
+
+  NodeData *node_data = static_cast<NodeData *>(BKE_pbvh_node_texture_paint_data_get(node));
+  // TODO: reinit when texturing on different image?
+  if (node_data != nullptr) {
+    return;
+  }
+
+  TIMEIT_START(init_texture_paint_for_node);
+  node_data = MEM_new<NodeData>(__func__);
+  node_data->init_pixels_rasterization(ob, node, ss->mode.texture_paint.drawing_target);
+  BKE_pbvh_node_texture_paint_data_set(node, node_data, NodeData::free_func);
+  TIMEIT_END(init_texture_paint_for_node);
+}
+
+static void init_using_rasterization(Object *ob, int totnode, PBVHNode **nodes)
+{
+  TIMEIT_START(init_using_rasterization);
+  TexturePaintingUserData data = {nullptr};
+  data.ob = ob;
+  data.nodes = nodes;
+
+  TaskParallelSettings settings;
+  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
+
+  BLI_task_parallel_range(0, totnode, &data, init_rasterization_task_cb_ex, &settings);
+  TIMEIT_END(init_using_rasterization);
+}
+
+struct BucketEntry {
+  PBVHNode *node;
+  const MPoly *poly;
+};
+struct Bucket {
+  static const int Size = 16;
+  Vector<BucketEntry> entries;
+  rctf bounds;
+};
+
+static bool init_using_intersection(SculptSession *ss,
+                                    Bucket &bucket,
+                                    ImBuf *image_buffer,
+                                    MVert *mvert,
+                                    MLoopUV *ldata_uv,
+                                    float2 uv,
+                                    int2 xy)
+{
+  const int pixel_offset = xy[1] * image_buffer->x + xy[0];
+  for (BucketEntry &entry : bucket.entries) {
+    const MPoly *p = entry.poly;
+
+    const MLoop *loopstart = &ss->mloop[p->loopstart];
+    for (int triangle = 0; triangle < p->totloop - 2; triangle++) {
+      const int v1_loop_index = p->loopstart;
+      const int v2_loop_index = p->loopstart + triangle + 1;
+      const int v3_loop_index = p->loopstart + triangle + 2;
+      const float2 v1_uv = ldata_uv[v1_loop_index].uv;
+      const float2 v2_uv = ldata_uv[v2_loop_index].uv;
+      const float2 v3_uv = ldata_uv[v3_loop_index].uv;
+      float3 weights;
+      barycentric_weights_v2(v1_uv, v2_uv, v3_uv, uv, weights);
+      if (weights[0] < 0.0 || weights[0] > 1.0 || weights[1] < 0.0 || weights[1] > 1.0 ||
+          weights[2] < 0.0 || weights[2] > 1.0) {
+        continue;
+      }
+
+      const int v1_index = loopstart[0].v;
+      const int v2_index = loopstart[triangle + 1].v;
+      const int v3_index = loopstart[triangle + 2].v;
+      const float3 v1_pos = mvert[v1_index].co;
+      const float3 v2_pos = mvert[v2_index].co;
+      const float3 v3_pos = mvert[v3_index].co;
+      float3 local_pos;
+      interp_v3_v3v3v3(local_pos, v1_pos, v2_pos, v3_pos, weights);
+
+      PixelData new_pixel;
+      new_pixel.local_pos = local_pos;
+      new_pixel.pixel_pos = xy;
+      copy_v4_fl(&image_buffer->rect_float[pixel_offset * 4], 1.0);
+      new_pixel.content = float4(image_buffer->rect_float[pixel_offset * 4]);
+      new_pixel.flags.dirty = false;
+
+      PBVHNode *node = entry.node;
+      NodeData *node_data = static_cast<NodeData *>(BKE_pbvh_node_texture_paint_data_get(node));
+      node_data->pixels.append(new_pixel);
+      return true;
+    }
+  }
+  return false;
+}
+
+static bool init_using_intersection(SculptSession *ss,
+                                    PBVHNode *node,
+                                    NodeData *node_data,
+                                    ImBuf *image_buffer,
+                                    MVert *mvert,
+                                    MLoopUV *ldata_uv,
+                                    float2 uv,
+                                    int2 xy)
+{
+  const int pixel_offset = xy[1] * image_buffer->x + xy[0];
+  PBVHVertexIter vd;
+  BKE_pbvh_vertex_iter_begin (ss->pbvh, node, vd, PBVH_ITER_UNIQUE) {
+    MeshElemMap *vert_map = &ss->pmap[vd.index];
+    for (int j = 0; j < ss->pmap[vd.index].count; j++) {
+      const MPoly *p = &ss->mpoly[vert_map->indices[j]];
+      if (p->totloop < 3) {
+        continue;
+      }
+
+      const MLoop *loopstart = &ss->mloop[p->loopstart];
+      for (int triangle = 0; triangle < p->totloop - 2; triangle++) {
+        const int v1_loop_index = p->loopstart;
+        const int v2_loop_index = p->loopstart + triangle + 1;
+        const int v3_loop_index = p->loopstart + triangle + 2;
+        const float2 v1_uv = ldata_uv[v1_loop_index].uv;
+        const float2 v2_uv = ldata_uv[v2_loop_index].uv;
+        const float2 v3_uv = ldata_uv[v3_loop_index].uv;
+        float3 weights;
+        barycentric_weights_v2(v1_uv, v2_uv, v3_uv, uv, weights);
+        if (weights[0] < 0.0 || weights[0] > 1.0 || weights[1] < 0.0 || weights[1] > 1.0 ||
+            weights[2] < 0.0 || weights[2] > 1.0) {
+          continue;
+        }
+
+        const int v1_index = loopstart[0].v;
+        const int v2_index = loopstart[triangle + 1].v;
+        const int v3_index = loopstart[triangle + 2].v;
+        const float3 v1_pos = mvert[v1_index].co;
+        const float3 v2_pos = mvert[v2_index].co;
+        const float3 v3_pos = mvert[v3_index].co;
+        float3 local_pos;
+        interp_v2_v2v2v2(local_pos, v1_pos, v2_pos, v3_pos, weights

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list