Blender  V2.93
sculpt_multiplane_scrape.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2020 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include "MEM_guardedalloc.h"
25 
26 #include "BLI_blenlib.h"
27 #include "BLI_math.h"
28 #include "BLI_task.h"
29 
30 #include "DNA_brush_types.h"
31 #include "DNA_mesh_types.h"
32 #include "DNA_meshdata_types.h"
33 #include "DNA_object_types.h"
34 
35 #include "BKE_brush.h"
36 #include "BKE_ccg.h"
37 #include "BKE_colortools.h"
38 #include "BKE_context.h"
39 #include "BKE_mesh.h"
40 #include "BKE_multires.h"
41 #include "BKE_node.h"
42 #include "BKE_object.h"
43 #include "BKE_paint.h"
44 #include "BKE_pbvh.h"
45 #include "BKE_scene.h"
46 
47 #include "paint_intern.h"
48 #include "sculpt_intern.h"
49 
50 #include "GPU_immediate.h"
51 #include "GPU_immediate_util.h"
52 #include "GPU_matrix.h"
53 #include "GPU_state.h"
54 
55 #include "bmesh.h"
56 
57 #include <math.h>
58 #include <stdlib.h>
59 
61  float area_cos[2][3];
62  float area_nos[2][3];
63  int area_count[2];
65 
66 static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata,
67  const int n,
68  const TaskParallelTLS *__restrict tls)
69 {
70  SculptThreadedTaskData *data = userdata;
71  SculptSession *ss = data->ob->sculpt;
72  const Brush *brush = data->brush;
73  MultiplaneScrapeSampleData *mssd = tls->userdata_chunk;
74  float(*mat)[4] = data->mat;
75 
76  PBVHVertexIter vd;
77 
78  SculptBrushTest test;
80  ss, &test, brush->falloff_shape);
81  const int thread_id = BLI_task_parallel_thread_id(tls);
82 
83  /* Apply the brush normal radius to the test before sampling. */
84  float test_radius = sqrtf(test.radius_squared);
85  test_radius *= brush->normal_radius_factor;
86  test.radius_squared = test_radius * test_radius;
87 
89 
90  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
91  continue;
92  }
93  float local_co[3];
94  float normal[3];
95  if (vd.no) {
97  }
98  else {
99  copy_v3_v3(normal, vd.fno);
100  }
101  mul_v3_m4v3(local_co, mat, vd.co);
102  /* Use the brush falloff to weight the sampled normals. */
103  const float fade = SCULPT_brush_strength_factor(ss,
104  brush,
105  vd.co,
106  sqrtf(test.dist),
107  vd.no,
108  vd.fno,
109  vd.mask ? *vd.mask : 0.0f,
110  vd.index,
111  thread_id);
112 
113  /* Sample the normal and area of the +X and -X axis individually. */
114  if (local_co[0] > 0.0f) {
115  madd_v3_v3fl(mssd->area_nos[0], normal, fade);
116  add_v3_v3(mssd->area_cos[0], vd.co);
117  mssd->area_count[0]++;
118  }
119  else {
120  madd_v3_v3fl(mssd->area_nos[1], normal, fade);
121  add_v3_v3(mssd->area_cos[1], vd.co);
122  mssd->area_count[1]++;
123  }
125  }
126 }
127 
128 static void calc_multiplane_scrape_surface_reduce(const void *__restrict UNUSED(userdata),
129  void *__restrict chunk_join,
130  void *__restrict chunk)
131 {
132  MultiplaneScrapeSampleData *join = chunk_join;
133  MultiplaneScrapeSampleData *mssd = chunk;
134 
135  add_v3_v3(join->area_cos[0], mssd->area_cos[0]);
136  add_v3_v3(join->area_cos[1], mssd->area_cos[1]);
137 
138  add_v3_v3(join->area_nos[0], mssd->area_nos[0]);
139  add_v3_v3(join->area_nos[1], mssd->area_nos[1]);
140 
141  join->area_count[0] += mssd->area_count[0];
142  join->area_count[1] += mssd->area_count[1];
143 }
144 
145 static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata,
146  const int n,
147  const TaskParallelTLS *__restrict tls)
148 {
149  SculptThreadedTaskData *data = userdata;
150  SculptSession *ss = data->ob->sculpt;
151  const Brush *brush = data->brush;
152  float(*mat)[4] = data->mat;
153  float(*scrape_planes)[4] = data->multiplane_scrape_planes;
154 
155  float angle = data->multiplane_scrape_angle;
156 
157  PBVHVertexIter vd;
158  float(*proxy)[3];
159  const float bstrength = fabsf(ss->cache->bstrength);
160 
161  proxy = BKE_pbvh_node_add_proxy(ss->pbvh, data->nodes[n])->co;
162 
163  SculptBrushTest test;
165  ss, &test, data->brush->falloff_shape);
166  const int thread_id = BLI_task_parallel_thread_id(tls);
167 
168  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
169 
170  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
171  continue;
172  }
173 
174  float local_co[3];
175  bool deform = false;
176 
177  mul_v3_m4v3(local_co, mat, vd.co);
178 
179  if (local_co[0] > 0.0f) {
180  deform = !SCULPT_plane_point_side(vd.co, scrape_planes[0]);
181  }
182  else {
183  deform = !SCULPT_plane_point_side(vd.co, scrape_planes[1]);
184  }
185 
186  if (angle < 0.0f) {
187  deform = true;
188  }
189 
190  if (!deform) {
191  continue;
192  }
193 
194  float intr[3];
195  float val[3];
196 
197  if (local_co[0] > 0.0f) {
198  closest_to_plane_normalized_v3(intr, scrape_planes[0], vd.co);
199  }
200  else {
201  closest_to_plane_normalized_v3(intr, scrape_planes[1], vd.co);
202  }
203 
204  sub_v3_v3v3(val, intr, vd.co);
205  if (!SCULPT_plane_trim(ss->cache, brush, val)) {
206  continue;
207  }
208  /* Deform the local space along the Y axis to avoid artifacts on curved strokes. */
209  /* This produces a not round brush tip. */
210  local_co[1] *= 2.0f;
211  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
212  brush,
213  vd.co,
214  len_v3(local_co),
215  vd.no,
216  vd.fno,
217  vd.mask ? *vd.mask : 0.0f,
218  vd.index,
219  thread_id);
220 
221  mul_v3_v3fl(proxy[vd.i], val, fade);
222 
223  if (vd.mvert) {
225  }
226  }
228 }
229 
230 /* Public functions. */
231 
232 /* Main Brush Function. */
233 void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
234 {
235  SculptSession *ss = ob->sculpt;
236  Brush *brush = BKE_paint_brush(&sd->paint);
237 
238  const bool flip = (ss->cache->bstrength < 0.0f);
239  const float radius = flip ? -ss->cache->radius : ss->cache->radius;
240  const float offset = SCULPT_brush_plane_offset_get(sd, ss);
241  const float displace = -radius * offset;
242 
243  /* The sculpt-plane normal (whatever its set to) */
244  float area_no_sp[3];
245 
246  /* Geometry normal. */
247  float area_no[3];
248  float area_co[3];
249 
250  float temp[3];
251  float mat[4][4];
252 
253  SCULPT_calc_brush_plane(sd, ob, nodes, totnode, area_no_sp, area_co);
254 
255  if (brush->sculpt_plane != SCULPT_DISP_DIR_AREA || (brush->flag & BRUSH_ORIGINAL_NORMAL)) {
256  SCULPT_calc_area_normal(sd, ob, nodes, totnode, area_no);
257  }
258  else {
259  copy_v3_v3(area_no, area_no_sp);
260  }
261 
262  /* Delay the first daub because grab delta is not setup. */
264  ss->cache->multiplane_scrape_angle = 0.0f;
265  return;
266  }
267 
269  return;
270  }
271 
272  mul_v3_v3v3(temp, area_no_sp, ss->cache->scale);
273  mul_v3_fl(temp, displace);
274  add_v3_v3(area_co, temp);
275 
276  /* Init brush local space matrix. */
277  cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry);
278  mat[0][3] = 0.0f;
279  cross_v3_v3v3(mat[1], area_no, mat[0]);
280  mat[1][3] = 0.0f;
281  copy_v3_v3(mat[2], area_no);
282  mat[2][3] = 0.0f;
283  copy_v3_v3(mat[3], ss->cache->location);
284  mat[3][3] = 1.0f;
285  normalize_m4(mat);
286  invert_m4(mat);
287 
288  /* Update matrix for the cursor preview. */
289  if (ss->cache->mirror_symmetry_pass == 0 && ss->cache->radial_symmetry_pass == 0) {
290  copy_m4_m4(ss->cache->stroke_local_mat, mat);
291  }
292 
293  /* Dynamic mode. */
294 
295  if (brush->flag2 & BRUSH_MULTIPLANE_SCRAPE_DYNAMIC) {
296  /* Sample the individual normal and area center of the two areas at both sides of the cursor.
297  */
298  SculptThreadedTaskData sample_data = {
299  .sd = NULL,
300  .ob = ob,
301  .brush = brush,
302  .nodes = nodes,
303  .totnode = totnode,
304  .mat = mat,
305  };
306 
307  MultiplaneScrapeSampleData mssd = {{{0}}};
308 
309  TaskParallelSettings sample_settings;
310  BKE_pbvh_parallel_range_settings(&sample_settings, true, totnode);
312  sample_settings.userdata_chunk = &mssd;
313  sample_settings.userdata_chunk_size = sizeof(MultiplaneScrapeSampleData);
314 
316  0, totnode, &sample_data, calc_multiplane_scrape_surface_task_cb, &sample_settings);
317 
318  float sampled_plane_normals[2][3];
319  float sampled_plane_co[2][3];
320  float sampled_cv[2][3];
321  float mid_co[3];
322 
323  /* Use the area center of both planes to detect if we are sculpting along a concave or convex
324  * edge. */
325  mul_v3_v3fl(sampled_plane_co[0], mssd.area_cos[0], 1.0f / (float)mssd.area_count[0]);
326  mul_v3_v3fl(sampled_plane_co[1], mssd.area_cos[1], 1.0f / (float)mssd.area_count[1]);
327  mid_v3_v3v3(mid_co, sampled_plane_co[0], sampled_plane_co[1]);
328 
329  /* Calculate the scrape planes angle based on the sampled normals. */
330  mul_v3_v3fl(sampled_plane_normals[0], mssd.area_nos[0], 1.0f / (float)mssd.area_count[0]);
331  mul_v3_v3fl(sampled_plane_normals[1], mssd.area_nos[1], 1.0f / (float)mssd.area_count[1]);
332  normalize_v3(sampled_plane_normals[0]);
333  normalize_v3(sampled_plane_normals[1]);
334 
335  float sampled_angle = angle_v3v3(sampled_plane_normals[0], sampled_plane_normals[1]);
336  copy_v3_v3(sampled_cv[0], area_no);
337  sub_v3_v3v3(sampled_cv[1], ss->cache->location, mid_co);
338 
339  sampled_angle += DEG2RADF(brush->multiplane_scrape_angle) * ss->cache->pressure;
340 
341  /* Invert the angle if we are sculpting along a concave edge. */
342  if (dot_v3v3(sampled_cv[0], sampled_cv[1]) < 0.0f) {
343  sampled_angle = -sampled_angle;
344  }
345 
346  /* In dynamic mode, set the angle to 0 when inverting the brush, so you can trim plane
347  * surfaces without changing the brush. */
348  if (flip) {
349  sampled_angle = 0.0f;
350  }
351  else {
352  copy_v3_v3(area_co, ss->cache->location);
353  }
354 
355  /* Interpolate between the previous and new sampled angles to avoid artifacts when if angle
356  * difference between two samples is too big. */
358  RAD2DEGF(sampled_angle), ss->cache->multiplane_scrape_angle, 0.2f);
359  }
360  else {
361 
362  /* Standard mode: Scrape with the brush property fixed angle. */
363  copy_v3_v3(area_co, ss->cache->location);
365  if (flip) {
366  ss->cache->multiplane_scrape_angle *= -1.0f;
367  }
368  }
369 
371  .sd = sd,
372  .ob = ob,
373  .brush = brush,
374  .nodes = nodes,
375  .mat = mat,
376  .multiplane_scrape_angle = ss->cache->multiplane_scrape_angle,
377  };
378 
379  /* Calculate the final left and right scrape planes. */
380  float plane_no[3];
381  float plane_no_rot[3];
382  const float y_axis[3] = {0.0f, 1.0f, 0.0f};
383  float mat_inv[4][4];
384  invert_m4_m4(mat_inv, mat);
385 
386  mul_v3_mat3_m4v3(plane_no, mat, area_no);
388  plane_no_rot, plane_no, y_axis, DEG2RADF(-ss->cache->multiplane_scrape_angle * 0.5f));
389  mul_v3_mat3_m4v3(plane_no, mat_inv, plane_no_rot);
390  normalize_v3(plane_no);
391  plane_from_point_normal_v3(data.multiplane_scrape_planes[1], area_co, plane_no);
392 
393  mul_v3_mat3_m4v3(plane_no, mat, area_no);
395  plane_no_rot, plane_no, y_axis, DEG2RADF(ss->cache->multiplane_scrape_angle * 0.5f));
396  mul_v3_mat3_m4v3(plane_no, mat_inv, plane_no_rot);
397  normalize_v3(plane_no);
398  plane_from_point_normal_v3(data.multiplane_scrape_planes[0], area_co, plane_no);
399 
400  TaskParallelSettings settings;
401  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
403 }
404 
406  Brush *brush,
407  SculptSession *ss,
408  const float outline_col[3],
409  const float outline_alpha)
410 {
412  return;
413  }
414 
415  float local_mat_inv[4][4];
416  invert_m4_m4(local_mat_inv, ss->cache->stroke_local_mat);
417  GPU_matrix_mul(local_mat_inv);
418  float angle = ss->cache->multiplane_scrape_angle;
419  if (ss->cache->pen_flip || ss->cache->invert) {
420  angle = -angle;
421  }
422 
423  float offset = ss->cache->radius * 0.25f;
424 
425  const float p[3] = {0.0f, 0.0f, ss->cache->radius};
426  const float y_axis[3] = {0.0f, 1.0f, 0.0f};
427  float p_l[3];
428  float p_r[3];
429  const float area_center[3] = {0.0f, 0.0f, 0.0f};
430  rotate_v3_v3v3fl(p_r, p, y_axis, DEG2RADF((angle + 180) * 0.5f));
431  rotate_v3_v3v3fl(p_l, p, y_axis, DEG2RADF(-(angle + 180) * 0.5f));
432 
434  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
435  immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
436  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
437  immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
438 
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  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
442  immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
443 
444  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
445  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
446 
447  immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
448  immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
449 
450  immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
451  immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
452 
453  immEnd();
454 
455  immUniformColor3fvAlpha(outline_col, outline_alpha * 0.1f);
456  immBegin(GPU_PRIM_TRIS, 12);
457  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
458  immVertex3f(gpuattr, p_r[0], p_r[1] + offset, p_r[2]);
459  immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
460  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
461  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
462  immVertex3f(gpuattr, p_r[0], p_r[1] - offset, p_r[2]);
463 
464  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
465  immVertex3f(gpuattr, p_l[0], p_l[1] + offset, p_l[2]);
466  immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
467  immVertex3f(gpuattr, area_center[0], area_center[1] + offset, area_center[2]);
468  immVertex3f(gpuattr, area_center[0], area_center[1] - offset, area_center[2]);
469  immVertex3f(gpuattr, p_l[0], p_l[1] - offset, p_l[2]);
470 
471  immEnd();
472 }
typedef float(TangentPoint)[2]
General operations, lookup, etc. for blender objects.
struct Brush * BKE_paint_brush(struct Paint *paint)
Definition: paint.c:604
A BVH for high poly meshes.
#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode)
Definition: BKE_pbvh.h:384
#define BKE_pbvh_vertex_iter_end
Definition: BKE_pbvh.h:457
#define PBVH_ITER_UNIQUE
Definition: BKE_pbvh.h:335
PBVHProxyNode * BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node)
Definition: pbvh.c:2848
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode)
Definition: pbvh.c:3042
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:243
void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3])
Definition: math_geom.c:412
bool invert_m4(float R[4][4])
Definition: math_matrix.c:1187
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1278
void copy_m4_m4(float m1[4][4], const float m2[4][4])
Definition: math_matrix.c:95
void mul_v3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:742
void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:804
void normalize_m4(float R[4][4]) ATTR_NONNULL()
Definition: math_matrix.c:1952
#define DEG2RADF(_deg)
#define RAD2DEGF(_rad)
float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:443
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 normal_short_to_float_v3(float r[3], const short n[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 rotate_v3_v3v3fl(float r[3], const float p[3], const float axis[3], const float angle)
Definition: math_vector.c:953
void mid_v3_v3v3(float r[3], const float a[3], const float b[3])
Definition: math_vector.c:270
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:83
void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, const TaskParallelSettings *settings)
Definition: task_range.cc:110
int BLI_task_parallel_thread_id(const TaskParallelTLS *tls)
#define UNUSED(x)
@ BRUSH_ORIGINAL_NORMAL
@ SCULPT_DISP_DIR_AREA
@ BRUSH_MULTIPLANE_SCRAPE_PLANES_PREVIEW
@ BRUSH_MULTIPLANE_SCRAPE_DYNAMIC
@ ME_VERT_PBVH_UPDATE
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:223
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:36
@ GPU_PRIM_TRIS
Definition: GPU_primitive.h:37
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
#define fabsf(x)
#define sqrtf(x)
int SCULPT_plane_point_side(const float co[3], const float plane[4])
Definition: sculpt.c:4875
SculptBrushTestFn SCULPT_brush_test_init_with_falloff_shape(SculptSession *ss, SculptBrushTest *test, char falloff_shape)
Definition: sculpt.c:1770
float SCULPT_brush_plane_offset_get(Sculpt *sd, SculptSession *ss)
Definition: sculpt.c:4881
float SCULPT_brush_strength_factor(SculptSession *ss, const Brush *br, const float brush_point[3], const float len, const short vno[3], const float fno[3], const float mask, const int vertex_index, const int thread_id)
Definition: sculpt.c:2463
bool SCULPT_stroke_is_first_brush_step_of_symmetry_pass(StrokeCache *cache)
Definition: sculpt.c:935
int SCULPT_plane_trim(const StrokeCache *cache, const Brush *brush, const float val[3])
Definition: sculpt.c:4860
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:4228
void SCULPT_calc_area_normal(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3])
Definition: sculpt.c:2197
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:56
struct MVert * mvert
Definition: BKE_pbvh.h:372
short * no
Definition: BKE_pbvh.h:375
float * co
Definition: BKE_pbvh.h:374
float * fno
Definition: BKE_pbvh.h:376
float * mask
Definition: BKE_pbvh.h:377
struct StrokeCache * cache
Definition: BKE_paint.h:518
struct PBVH * pbvh
Definition: BKE_paint.h:504
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:158
size_t userdata_chunk_size
Definition: BLI_task.h:150
CCL_NAMESPACE_BEGIN ccl_device float fade(float t)
Definition: svm_noise.h:37