Blender  V3.3
sculpt_multiplane_scrape.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2020 Blender Foundation. All rights reserved. */
3 
8 #include "MEM_guardedalloc.h"
9 
10 #include "BLI_blenlib.h"
11 #include "BLI_math.h"
12 #include "BLI_task.h"
13 
14 #include "DNA_brush_types.h"
15 #include "DNA_mesh_types.h"
16 #include "DNA_meshdata_types.h"
17 #include "DNA_object_types.h"
18 
19 #include "BKE_brush.h"
20 #include "BKE_ccg.h"
21 #include "BKE_colortools.h"
22 #include "BKE_context.h"
23 #include "BKE_mesh.h"
24 #include "BKE_multires.h"
25 #include "BKE_node.h"
26 #include "BKE_object.h"
27 #include "BKE_paint.h"
28 #include "BKE_pbvh.h"
29 #include "BKE_scene.h"
30 
31 #include "paint_intern.h"
32 #include "sculpt_intern.h"
33 
34 #include "GPU_immediate.h"
35 #include "GPU_immediate_util.h"
36 #include "GPU_matrix.h"
37 #include "GPU_state.h"
38 
39 #include "bmesh.h"
40 
41 #include <math.h>
42 #include <stdlib.h>
43 
45  float area_cos[2][3];
46  float area_nos[2][3];
47  int area_count[2];
49 
50 static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
51  const int n,
52  const TaskParallelTLS *__restrict tls)
53 {
54  SculptThreadedTaskData *data = userdata;
55  SculptSession *ss = data->ob->sculpt;
56  const Brush *brush = data->brush;
57  MultiplaneScrapeSampleData *mssd = tls->userdata_chunk;
58  float(*mat)[4] = data->mat;
59 
60  PBVHVertexIter vd;
61 
62  SculptBrushTest test;
64  ss, &test, brush->falloff_shape);
65  const int thread_id = BLI_task_parallel_thread_id(tls);
66 
67  /* Apply the brush normal radius to the test before sampling. */
68  float test_radius = sqrtf(test.radius_squared);
69  test_radius *= brush->normal_radius_factor;
70  test.radius_squared = test_radius * test_radius;
71 
73 
74  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
75  continue;
76  }
77  float local_co[3];
78  float normal[3];
79  copy_v3_v3(normal, vd.no ? vd.no : vd.fno);
80  mul_v3_m4v3(local_co, mat, vd.co);
81  /* Use the brush falloff to weight the sampled normals. */
82  const float fade = SCULPT_brush_strength_factor(ss,
83  brush,
84  vd.co,
85  sqrtf(test.dist),
86  vd.no,
87  vd.fno,
88  vd.mask ? *vd.mask : 0.0f,
89  vd.index,
90  thread_id);
91 
92  /* Sample the normal and area of the +X and -X axis individually. */
93  if (local_co[0] > 0.0f) {
94  madd_v3_v3fl(mssd->area_nos[0], normal, fade);
95  add_v3_v3(mssd->area_cos[0], vd.co);
96  mssd->area_count[0]++;
97  }
98  else {
99  madd_v3_v3fl(mssd->area_nos[1], normal, fade);
100  add_v3_v3(mssd->area_cos[1], vd.co);
101  mssd->area_count[1]++;
102  }
104  }
105 }
106 
107 static void calc_multiplane_scrape_surface_reduce(const void *__restrict UNUSED(userdata),
108  void *__restrict chunk_join,
109  void *__restrict chunk)
110 {
111  MultiplaneScrapeSampleData *join = chunk_join;
112  MultiplaneScrapeSampleData *mssd = chunk;
113 
114  add_v3_v3(join->area_cos[0], mssd->area_cos[0]);
115  add_v3_v3(join->area_cos[1], mssd->area_cos[1]);
116 
117  add_v3_v3(join->area_nos[0], mssd->area_nos[0]);
118  add_v3_v3(join->area_nos[1], mssd->area_nos[1]);
119 
120  join->area_count[0] += mssd->area_count[0];
121  join->area_count[1] += mssd->area_count[1];
122 }
123 
124 static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
125  const int n,
126  const TaskParallelTLS *__restrict tls)
127 {
128  SculptThreadedTaskData *data = userdata;
129  SculptSession *ss = data->ob->sculpt;
130  const Brush *brush = data->brush;
131  float(*mat)[4] = data->mat;
132  float(*scrape_planes)[4] = data->multiplane_scrape_planes;
133 
134  float angle = data->multiplane_scrape_angle;
135 
136  PBVHVertexIter vd;
137  float(*proxy)[3];
138  const float bstrength = fabsf(ss->cache->bstrength);
139 
140  proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
141 
142  SculptBrushTest test;
144  ss, &test, data->brush->falloff_shape);
145  const int thread_id = BLI_task_parallel_thread_id(tls);
146 
147  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
148 
149  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
150  continue;
151  }
152 
153  float local_co[3];
154  bool deform = false;
155 
156  mul_v3_m4v3(local_co, mat, vd.co);
157 
158  if (local_co[0] > 0.0f) {
159  deform = !SCULPT_plane_point_side(vd.co, scrape_planes[0]);
160  }
161  else {
162  deform = !SCULPT_plane_point_side(vd.co, scrape_planes[1]);
163  }
164 
165  if (angle < 0.0f) {
166  deform = true;
167  }
168 
169  if (!deform) {
170  continue;
171  }
172 
173  float intr[3];
174  float val[3];
175 
176  if (local_co[0] > 0.0f) {
177  closest_to_plane_normalized_v3(intr, scrape_planes[0], vd.co);
178  }
179  else {
180  closest_to_plane_normalized_v3(intr, scrape_planes[1], vd.co);
181  }
182 
183  sub_v3_v3v3(val, intr, vd.co);
184  if (!SCULPT_plane_trim(ss->cache, brush, val)) {
185  continue;
186  }
187  /* Deform the local space along the Y axis to avoid artifacts on curved strokes. */
188  /* This produces a not round brush tip. */
189  local_co[1] *= 2.0f;
190  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
191  brush,
192  vd.co,
193  len_v3(local_co),
194  vd.no,
195  vd.fno,
196  vd.mask ? *vd.mask : 0.0f,
197  vd.index,
198  thread_id);
199 
200  mul_v3_v3fl(proxy[vd.i], val, fade);
201 
202  if (vd.mvert) {
204  }
205  }
207 }
208 
209 /* Public functions. */
210 
211 void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
212 {
213  SculptSession *ss = ob->sculpt;
214  Brush *brush = BKE_paint_brush(&sd->paint);
215 
216  const bool flip = (ss->cache->bstrength < 0.0f);
217  const float radius = flip ? -ss->cache->radius : ss->cache->radius;
218  const float offset = SCULPT_brush_plane_offset_get(sd, ss);
219  const float displace = -radius * offset;
220 
221  /* The sculpt-plane normal (whatever its set to) */
222  float area_no_sp[3];
223 
224  /* Geometry normal. */
225  float area_no[3];
226  float area_co[3];
227 
228  float temp[3];
229  float mat[4][4];
230 
231  SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no_sp, area_co);
232 
233  if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
234  SCULPT_calc_area_normal(sd, ob, nodes, totnode, area_no);
235  }
236  else {
237  copy_v3_v3(area_no, area_no_sp);
238  }
239 
240  /* Delay the first daub because grab delta is not setup. */
242  ss->cache->multiplane_scrape_angle = 0.0f;
243  return;
244  }
245 
247  return;
248  }
249 
250  mul_v3_v3v3(temp, area_no_sp, ss->cache->scale);
251  mul_v3_fl(temp, displace);
252  add_v3_v3(area_co, temp);
253 
254  /* Init brush local space matrix. */
255  cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry);
256  mat[0][3] = 0.0f;
257  cross_v3_v3v3(mat[1], area_no, mat[0]);
258  mat[1][3] = 0.0f;
259  copy_v3_v3(mat[2], area_no);
260  mat[2][3] = 0.0f;
261  copy_v3_v3(mat[3], ss->cache->location);
262  mat[3][3] = 1.0f;
263  normalize_m4(mat);
264  invert_m4(mat);
265 
266  /* Update matrix for the cursor preview. */
267  if (ss->cache->mirror_symmetry_pass == 0 && ss->cache->radial_symmetry_pass == 0) {
268  copy_m4_m4(ss->cache->stroke_local_mat, mat);
269  }
270 
271  /* Dynamic mode. */
272 
273  if (brush->flag2 & BRUSH_MULTIPLANE_SCRAPE_DYNAMIC) {
274  /* Sample the individual normal and area center of the two areas at both sides of the cursor.
275  */
276  SculptThreadedTaskData sample_data = {
277  .sd = NULL,
278  .ob = ob,
279  .brush = brush,
280  .nodes = nodes,
281  .totnode = totnode,
282  .mat = mat,
283  };
284 
285  MultiplaneScrapeSampleData mssd = {{{0}}};
286 
287  TaskParallelSettings sample_settings;
288  BKE_pbvh_parallel_range_settings(&sample_settings, true, totnode);
290  sample_settings.userdata_chunk = &mssd;
291  sample_settings.userdata_chunk_size = sizeof(MultiplaneScrapeSampleData);
292 
294  0, totnode, &sample_data, calc_multiplane_scrape_surface_task_cb, &sample_settings);
295 
296  float sampled_plane_normals[2][3];
297  float sampled_plane_co[2][3];
298  float sampled_cv[2][3];
299  float mid_co[3];
300 
301  /* Use the area center of both planes to detect if we are sculpting along a concave or convex
302  * edge. */
303  mul_v3_v3fl(sampled_plane_co[0], mssd.area_cos[0], 1.0f / (float)mssd.area_count[0]);
304  mul_v3_v3fl(sampled_plane_co[1], mssd.area_cos[1], 1.0f / (float)mssd.area_count[1]);
305  mid_v3_v3v3(mid_co, sampled_plane_co[0], sampled_plane_co[1]);
306 
307  /* Calculate the scrape planes angle based on the sampled normals. */
308  mul_v3_v3fl(sampled_plane_normals[0], mssd.area_nos[0], 1.0f / (float)mssd.area_count[0]);
309  mul_v3_v3fl(sampled_plane_normals[1], mssd.area_nos[1], 1.0f / (float)mssd.area_count[1]);
310  normalize_v3(sampled_plane_normals[0]);
311  normalize_v3(sampled_plane_normals[1]);
312 
313  float sampled_angle = angle_v3v3(sampled_plane_normals[0], sampled_plane_normals[1]);
314  copy_v3_v3(sampled_cv[0], area_no);
315  sub_v3_v3v3(sampled_cv[1], ss->cache->location, mid_co);
316 
317  sampled_angle += DEG2RADF(brush->multiplane_scrape_angle) * ss->cache->pressure;
318 
319  /* Invert the angle if we are sculpting along a concave edge. */
320  if (dot_v3v3(sampled_cv[0], sampled_cv[1]) < 0.0f) {
321  sampled_angle = -sampled_angle;
322  }
323 
324  /* In dynamic mode, set the angle to 0 when inverting the brush, so you can trim plane
325  * surfaces without changing the brush. */
326  if (flip) {
327  sampled_angle = 0.0f;
328  }
329  else {
330  copy_v3_v3(area_co, ss->cache->location);
331  }
332 
333  /* Interpolate between the previous and new sampled angles to avoid artifacts when if angle
334  * difference between two samples is too big. */
336  RAD2DEGF(sampled_angle), ss->cache->multiplane_scrape_angle, 0.2f);
337  }
338  else {
339 
340  /* Standard mode: Scrape with the brush property fixed angle. */
341  copy_v3_v3(area_co, ss->cache->location);
343  if (flip) {
344  ss->cache->multiplane_scrape_angle *= -1.0f;
345  }
346  }
347 
349  .sd = sd,
350  .ob = ob,
351  .brush = brush,
352  .nodes = nodes,
353  .mat = mat,
354  .multiplane_scrape_angle = ss->cache->multiplane_scrape_angle,
355  };
356 
357  /* Calculate the final left and right scrape planes. */
358  float plane_no[3];
359  float plane_no_rot[3];
360  const float y_axis[3] = {0.0f, 1.0f, 0.0f};
361  float mat_inv[4][4];
362  invert_m4_m4(mat_inv, mat);
363 
364  mul_v3_mat3_m4v3(plane_no, mat, area_no);
366  plane_no_rot, plane_no, y_axis, DEG2RADF(-ss->cache->multiplane_scrape_angle * 0.5f));
367  mul_v3_mat3_m4v3(plane_no, mat_inv, plane_no_rot);
368  normalize_v3(plane_no);
369  plane_from_point_normal_v3(data.multiplane_scrape_planes[1], area_co, plane_no);
370 
371  mul_v3_mat3_m4v3(plane_no, mat, area_no);
373  plane_no_rot, plane_no, y_axis, DEG2RADF(ss->cache->multiplane_scrape_angle * 0.5f));
374  mul_v3_mat3_m4v3(plane_no, mat_inv, plane_no_rot);
375  normalize_v3(plane_no);
376  plane_from_point_normal_v3(data.multiplane_scrape_planes[0], area_co, plane_no);
377 
378  TaskParallelSettings settings;
379  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
381 }
382 
384  Brush *brush,
385  SculptSession *ss,
386  const float outline_col[3],
387  const float outline_alpha)
388 {
390  return;
391  }
392 
393  float local_mat_inv[4][4];
394  invert_m4_m4(local_mat_inv, ss->cache->stroke_local_mat);
395  GPU_matrix_mul(local_mat_inv);
396  float angle = ss->cache->multiplane_scrape_angle;
397  if (ss->cache->pen_flip || ss->cache->invert) {
398  angle = -angle;
399  }
400 
401  float offset = ss->cache->radius * 0.25f;
402 
403  const float p[3] = {0.0f, 0.0f, ss->cache->radius};
404  const float y_axis[3] = {0.0f, 1.0f, 0.0f};
405  float p_l[3];
406  float p_r[3];
407  const float area_center[3] = {0.0f, 0.0f, 0.0f};
408  rotate_v3_v3v3fl(p_r, p, y_axis, DEG2RADF((angle + 180) * 0.5f));
409  rotate_v3_v3v3fl(p_l, p, y_axis, DEG2RADF(-(angle + 180) * 0.5f));
410 
412  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
413  immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
414  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
415  immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
416 
417  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
418  immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
419  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
420  immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
421 
422  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
423  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
424 
425  immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
426  immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
427 
428  immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
429  immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
430 
431  immEnd();
432 
433  immUniformColor3fvAlpha(outline_col, outline_alpha * 0.1f);
434  immBegin(GPU_PRIM_TRIS, 12);
435  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
436  immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
437  immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
438  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
439  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
440  immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
441 
442  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
443  immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
444  immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
445  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
446  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
447  immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
448 
449  immEnd();
450 }
typedef float(TangentPoint)[2]
General operations, lookup, etc. for blender objects.
struct Brush * BKE_paint_brush(struct Paint *paint)
Definition: paint.c:607
A BVH for high poly meshes.
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode)
Definition: BKE_pbvh.h:439
#define BKE_pbvh_vertex_iter_end
Definition: BKE_pbvh.h:509
void BKE_pbvh_vert_tag_update_normal(PBVH *pbvh, int index)
Definition: pbvh.c:1967
#define PBVH_ITER_UNIQUE
Definition: BKE_pbvh.h:391
PBVHProxyNode * BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node)
Definition: pbvh.c:3016
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode)
Definition: pbvh.c:3211
MINLINE float interpf(float a, float b, float t)
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition: math_geom.c:209
void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3])
Definition: math_geom.c:408
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1206
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:77
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:739
void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:800
void normalize_m4(float R[4][4]) ATTR_NONNULL()
Definition: math_matrix.c:1945
#define DEG2RADF(_deg)
#define RAD2DEGF(_rad)
void rotate_v3_v3v3fl(float r[3], const float p[3], const float axis[3], float angle)
Definition: math_vector.c:800
float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:385
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void mul_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:237
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE void add_v3_v3(float r[3], const float a[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
unsigned int uint
Definition: BLI_sys_types.h:67
void BLI_task_parallel_range(int start, int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:94
int BLI_task_parallel_thread_id(const TaskParallelTLS *tls)
#define UNUSED(x)
@ SCULPT_DISP_DIR_AREA
@ BRUSH_ORIGINAL_NORMAL
@ BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW
@ BRUSH_MULTIPLANE_SCRAPE_DYNAMIC
Object is a sort of wrapper for general info.
void immVertex3f(uint attr_id, float x, float y, float z)
void immBegin(GPUPrimType, uint vertex_len)
void immUniformColor3fvAlpha(const float rgb[3], float a)
void immEnd(void)
#define GPU_matrix_mul(x)
Definition: GPU_matrix.h:224
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:20
@ GPU_PRIM_TRIS
Definition: GPU_primitive.h:21
Read Guarded memory(de)allocation.
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
IconTextureDrawCall normal
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
CCL_NAMESPACE_BEGIN ccl_device float fade(float t)
Definition: noise.h:15
int SCULPT_plane_point_side(const float co[3], const float plane[4])
Definition: sculpt.c:2996
SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss, SculptBrushTest *test, char falloff_shape)
Definition: sculpt.c:1686
float SCULPT_brush_strength_factor(SculptSession *ss, const Brush *br, const float brush_point[3], const float len, const float vno[3], const float fno[3], const float mask, const int vertex_index, const int thread_id)
Definition: sculpt.c:2370
float SCULPT_brush_plane_offset_get(Sculpt *sd, SculptSession *ss)
Definition: sculpt.c:3002
bool SCULPT_stroke_is_first_brush_step_of_symmetry_pass(StrokeCache *cache)
Definition: sculpt.c:918
int SCULPT_plane_trim(const StrokeCache *cache, const Brush *brush, const float val[3])
Definition: sculpt.c:2990
void SCULPT_calc_brush_plane(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3], float r_area_co[3])
Definition: sculpt.c:2901
void SCULPT_calc_area_normal(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3])
Definition: sculpt.c:2103
bool(* SculptBrushTestFn)(SculptBrushTest *test, const float co[3])
void SCULPT_multiplane_scrape_preview_draw(const uint gpuattr, Brush *brush, SculptSession *ss, const float outline_col[3], const float outline_alpha)
static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
static void calc_multiplane_scrape_surface_reduce(const void *__restrict UNUSED(userdata), void *__restrict chunk_join, void *__restrict chunk)
struct MultiplaneScrapeSampleData MultiplaneScrapeSampleData
void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
float multiplane_scrape_angle
int sculpt_plane
float normal_radius_factor
char falloff_shape
struct SculptSession * sculpt
float(* co)[3]
Definition: BKE_pbvh.h:47
struct MVert * mvert
Definition: BKE_pbvh.h:428
float * co
Definition: BKE_pbvh.h:430
float * fno
Definition: BKE_pbvh.h:432
float * no
Definition: BKE_pbvh.h:431
float * mask
Definition: BKE_pbvh.h:433
struct StrokeCache * cache
Definition: BKE_paint.h:563
struct PBVH * pbvh
Definition: BKE_paint.h:550
struct Sculpt * sd
Paint paint
float scale[3]
int mirror_symmetry_pass
float multiplane_scrape_angle
float grab_delta_symmetry[3]
float location[3]
float stroke_local_mat[4][4]
int radial_symmetry_pass
TaskParallelReduceFunc func_reduce
Definition: BLI_task.h:181
size_t userdata_chunk_size
Definition: BLI_task.h:169