Blender  V3.3
sculpt_paint_color.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_hash.h"
12 #include "BLI_math.h"
13 #include "BLI_math_color_blend.h"
14 #include "BLI_task.h"
15 
16 #include "DNA_mesh_types.h"
17 #include "DNA_meshdata_types.h"
18 
19 #include "BKE_brush.h"
20 #include "BKE_colorband.h"
21 #include "BKE_colortools.h"
22 #include "BKE_context.h"
23 #include "BKE_mesh.h"
24 #include "BKE_mesh_mapping.h"
25 #include "BKE_object.h"
26 #include "BKE_paint.h"
27 #include "BKE_pbvh.h"
28 #include "BKE_scene.h"
29 
30 #include "DEG_depsgraph.h"
31 
32 #include "IMB_colormanagement.h"
33 
34 #include "WM_api.h"
35 #include "WM_message.h"
36 #include "WM_toolsystem.h"
37 #include "WM_types.h"
38 
39 #include "ED_object.h"
40 #include "ED_screen.h"
41 #include "ED_sculpt.h"
42 #include "paint_intern.h"
43 #include "sculpt_intern.h"
44 
45 #include "RNA_access.h"
46 #include "RNA_define.h"
47 
48 #include "UI_interface.h"
49 
50 #include "IMB_imbuf.h"
51 
52 #include "bmesh.h"
53 
54 #include <math.h>
55 #include <stdlib.h>
56 
57 static void do_color_smooth_task_cb_exec(void *__restrict userdata,
58  const int n,
59  const TaskParallelTLS *__restrict tls)
60 {
61  SculptThreadedTaskData *data = userdata;
62  SculptSession *ss = data->ob->sculpt;
63  const Brush *brush = data->brush;
64  const float bstrength = ss->cache->bstrength;
65 
66  PBVHVertexIter vd;
67 
68  SculptBrushTest test;
70  ss, &test, data->brush->falloff_shape);
71  const int thread_id = BLI_task_parallel_thread_id(tls);
72 
74  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
75  continue;
76  }
77  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
78  brush,
79  vd.co,
80  sqrtf(test.dist),
81  vd.no,
82  vd.fno,
83  vd.mask ? *vd.mask : 0.0f,
84  vd.index,
85  thread_id);
86 
87  float smooth_color[4];
88  SCULPT_neighbor_color_average(ss, smooth_color, vd.index);
89  float col[4];
90 
92  blend_color_interpolate_float(col, col, smooth_color, fade);
94  }
96 }
97 
98 static void do_paint_brush_task_cb_ex(void *__restrict userdata,
99  const int n,
100  const TaskParallelTLS *__restrict tls)
101 {
102  SculptThreadedTaskData *data = userdata;
103  SculptSession *ss = data->ob->sculpt;
104  const Brush *brush = data->brush;
105  const float bstrength = fabsf(ss->cache->bstrength);
106 
107  PBVHVertexIter vd;
108  PBVHColorBufferNode *color_buffer;
109 
110  SculptOrigVertData orig_data;
111  SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COLOR);
112 
113  color_buffer = BKE_pbvh_node_color_buffer_get(data->nodes[n]);
114 
115  SculptBrushTest test;
117  ss, &test, data->brush->falloff_shape);
118  const int thread_id = BLI_task_parallel_thread_id(tls);
119 
120  float brush_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
121 
122  copy_v3_v3(brush_color,
123  ss->cache->invert ? BKE_brush_secondary_color_get(ss->scene, brush) :
124  BKE_brush_color_get(ss->scene, brush));
125 
126  IMB_colormanagement_srgb_to_scene_linear_v3(brush_color, brush_color);
127 
128  if (brush->flag & BRUSH_USE_GRADIENT) {
129  switch (brush->gradient_stroke_mode) {
131  BKE_colorband_evaluate(brush->gradient, ss->cache->pressure, brush_color);
132  break;
134  float coord = fmod(ss->cache->stroke_distance / brush->gradient_spacing, 1.0);
135  BKE_colorband_evaluate(brush->gradient, coord, brush_color);
136  break;
137  }
140  brush->gradient, ss->cache->stroke_distance / brush->gradient_spacing, brush_color);
141  break;
142  }
143  }
144  }
145 
146  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
147  SCULPT_orig_vert_data_update(&orig_data, &vd);
148 
149  bool affect_vertex = false;
150  float distance_to_stroke_location = 0.0f;
151  if (brush->tip_roundness < 1.0f) {
152  affect_vertex = SCULPT_brush_test_cube(&test, vd.co, data->mat, brush->tip_roundness);
153  distance_to_stroke_location = ss->cache->radius * test.dist;
154  }
155  else {
156  affect_vertex = sculpt_brush_test_sq_fn(&test, vd.co);
157  distance_to_stroke_location = sqrtf(test.dist);
158  }
159 
160  if (!affect_vertex) {
161  continue;
162  }
163 
164  float fade = bstrength * SCULPT_brush_strength_factor(ss,
165  brush,
166  vd.co,
167  distance_to_stroke_location,
168  vd.no,
169  vd.fno,
170  vd.mask ? *vd.mask : 0.0f,
171  vd.index,
172  thread_id);
173 
174  /* Density. */
175  float noise = 1.0f;
176  const float density = ss->cache->paint_brush.density;
177  if (density < 1.0f) {
178  const float hash_noise = (float)BLI_hash_int_01(ss->cache->density_seed * 1000 * vd.index);
179  if (hash_noise > density) {
180  noise = density * hash_noise;
181  fade = fade * noise;
182  }
183  }
184 
185  /* Brush paint color, brush test falloff and flow. */
186  float paint_color[4];
187  float wet_mix_color[4];
188  float buffer_color[4];
189 
190  mul_v4_v4fl(paint_color, brush_color, fade * ss->cache->paint_brush.flow);
191  mul_v4_v4fl(wet_mix_color, data->wet_mix_sampled_color, fade * ss->cache->paint_brush.flow);
192 
193  /* Interpolate with the wet_mix color for wet paint mixing. */
195  paint_color, paint_color, wet_mix_color, ss->cache->paint_brush.wet_mix);
196  blend_color_mix_float(color_buffer->color[vd.i], color_buffer->color[vd.i], paint_color);
197 
198  /* Final mix over the original color using brush alpha. */
199  mul_v4_v4fl(buffer_color, color_buffer->color[vd.i], brush->alpha);
200 
201  float col[4];
203  IMB_blend_color_float(col, orig_data.col, buffer_color, brush->blend);
204  CLAMP4(col, 0.0f, 1.0f);
206  }
208 }
209 
210 typedef struct SampleWetPaintTLSData {
212  float color[4];
214 
215 static void do_sample_wet_paint_task_cb(void *__restrict userdata,
216  const int n,
217  const TaskParallelTLS *__restrict tls)
218 {
219  SculptThreadedTaskData *data = userdata;
220  SculptSession *ss = data->ob->sculpt;
221  SampleWetPaintTLSData *swptd = tls->userdata_chunk;
222  PBVHVertexIter vd;
223 
224  SculptBrushTest test;
226  ss, &test, data->brush->falloff_shape);
227 
228  test.radius *= data->brush->wet_paint_radius_factor;
229  test.radius_squared = test.radius * test.radius;
230 
231  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
232  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
233  continue;
234  }
235 
236  float col[4];
238 
239  add_v4_v4(swptd->color, col);
240  swptd->tot_samples++;
241  }
243 }
244 
245 static void sample_wet_paint_reduce(const void *__restrict UNUSED(userdata),
246  void *__restrict chunk_join,
247  void *__restrict chunk)
248 {
249  SampleWetPaintTLSData *join = chunk_join;
250  SampleWetPaintTLSData *swptd = chunk;
251 
252  join->tot_samples += swptd->tot_samples;
253  add_v4_v4(join->color, swptd->color);
254 }
255 
257  PaintModeSettings *paint_mode_settings, Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
258 {
259  if (SCULPT_use_image_paint_brush(paint_mode_settings, ob)) {
260  SCULPT_do_paint_brush_image(paint_mode_settings, sd, ob, nodes, totnode);
261  return;
262  }
263 
264  Brush *brush = BKE_paint_brush(&sd->paint);
265  SculptSession *ss = ob->sculpt;
266 
267  if (!SCULPT_has_colors(ss)) {
268  return;
269  }
270 
273  ss->cache->density_seed = (float)BLI_hash_int_01(ss->cache->location[0] * 1000);
274  }
275  return;
276  }
277 
279 
280  float area_no[3];
281  float mat[4][4];
282  float scale[4][4];
283  float tmat[4][4];
284 
285  /* If the brush is round the tip does not need to be aligned to the surface, so this saves a
286  * whole iteration over the affected nodes. */
287  if (brush->tip_roundness < 1.0f) {
288  SCULPT_calc_area_normal(sd, ob, nodes, totnode, area_no);
289 
290  cross_v3_v3v3(mat[0], area_no, ss->cache->grab_delta_symmetry);
291  mat[0][3] = 0;
292  cross_v3_v3v3(mat[1], area_no, mat[0]);
293  mat[1][3] = 0;
294  copy_v3_v3(mat[2], area_no);
295  mat[2][3] = 0;
296  copy_v3_v3(mat[3], ss->cache->location);
297  mat[3][3] = 1;
298  normalize_m4(mat);
299 
300  scale_m4_fl(scale, ss->cache->radius);
301  mul_m4_m4m4(tmat, mat, scale);
302  mul_v3_fl(tmat[1], brush->tip_scale_x);
303  invert_m4_m4(mat, tmat);
304  if (is_zero_m4(mat)) {
305  return;
306  }
307  }
308 
309  /* Smooth colors mode. */
310  if (ss->cache->alt_smooth) {
312  .sd = sd,
313  .ob = ob,
314  .brush = brush,
315  .nodes = nodes,
316  .mat = mat,
317  };
318 
319  TaskParallelSettings settings;
320  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
322  return;
323  }
324 
325  /* Regular Paint mode. */
326 
327  /* Wet paint color sampling. */
328  float wet_color[4] = {0.0f};
329  if (ss->cache->paint_brush.wet_mix > 0.0f) {
330  SculptThreadedTaskData task_data = {
331  .sd = sd,
332  .ob = ob,
333  .nodes = nodes,
334  .brush = brush,
335  };
336 
337  SampleWetPaintTLSData swptd;
338  swptd.tot_samples = 0;
339  zero_v4(swptd.color);
340 
341  TaskParallelSettings settings_sample;
342  BKE_pbvh_parallel_range_settings(&settings_sample, true, totnode);
343  settings_sample.func_reduce = sample_wet_paint_reduce;
344  settings_sample.userdata_chunk = &swptd;
345  settings_sample.userdata_chunk_size = sizeof(SampleWetPaintTLSData);
346  BLI_task_parallel_range(0, totnode, &task_data, do_sample_wet_paint_task_cb, &settings_sample);
347 
348  if (swptd.tot_samples > 0 && is_finite_v4(swptd.color)) {
349  copy_v4_v4(wet_color, swptd.color);
350  mul_v4_fl(wet_color, 1.0f / swptd.tot_samples);
351  CLAMP4(wet_color, 0.0f, 1.0f);
352 
353  if (ss->cache->first_time) {
354  copy_v4_v4(ss->cache->wet_mix_prev_color, wet_color);
355  }
357  wet_color,
360  copy_v4_v4(ss->cache->wet_mix_prev_color, wet_color);
361  CLAMP4(ss->cache->wet_mix_prev_color, 0.0f, 1.0f);
362  }
363  }
364 
365  /* Threaded loop over nodes. */
367  .sd = sd,
368  .ob = ob,
369  .brush = brush,
370  .nodes = nodes,
371  .wet_mix_sampled_color = wet_color,
372  .mat = mat,
373  };
374 
375  TaskParallelSettings settings;
376  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
377  BLI_task_parallel_range(0, totnode, &data, do_paint_brush_task_cb_ex, &settings);
378 }
379 
380 static void do_smear_brush_task_cb_exec(void *__restrict userdata,
381  const int n,
382  const TaskParallelTLS *__restrict tls)
383 {
384  SculptThreadedTaskData *data = userdata;
385  SculptSession *ss = data->ob->sculpt;
386  const Brush *brush = data->brush;
387  const float bstrength = ss->cache->bstrength;
388 
389  PBVHVertexIter vd;
390 
391  SculptBrushTest test;
393  ss, &test, data->brush->falloff_shape);
394  const int thread_id = BLI_task_parallel_thread_id(tls);
395 
396  float brush_delta[3];
397 
398  if (brush->flag & BRUSH_ANCHORED) {
399  copy_v3_v3(brush_delta, ss->cache->grab_delta_symmetry);
400  }
401  else {
402  sub_v3_v3v3(brush_delta, ss->cache->location, ss->cache->last_location);
403  }
404 
405  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
406  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
407  continue;
408  }
409  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
410  brush,
411  vd.co,
412  sqrtf(test.dist),
413  vd.no,
414  vd.fno,
415  vd.mask ? *vd.mask : 0.0f,
416  vd.index,
417  thread_id);
418 
419  float current_disp[3];
420  float current_disp_norm[3];
421  float interp_color[4];
422  copy_v4_v4(interp_color, ss->cache->prev_colors[vd.index]);
423 
424  float no[3];
425  SCULPT_vertex_normal_get(ss, vd.index, no);
426 
427  switch (brush->smear_deform_type) {
429  copy_v3_v3(current_disp, brush_delta);
430  break;
432  sub_v3_v3v3(current_disp, ss->cache->location, vd.co);
433  break;
435  sub_v3_v3v3(current_disp, vd.co, ss->cache->location);
436  break;
437  }
438 
439  /* Project into vertex plane. */
440  madd_v3_v3fl(current_disp, no, -dot_v3v3(current_disp, no));
441 
442  normalize_v3_v3(current_disp_norm, current_disp);
443  mul_v3_v3fl(current_disp, current_disp_norm, bstrength);
444 
445  float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
446  float totw = 0.0f;
447 
448  /*
449  * NOTE: we have to do a nested iteration here to avoid
450  * blocky artifacts on quad topologies. The runtime cost
451  * is not as bad as it seems due to neighbor iteration
452  * in the sculpt code being cache bound; once the data is in
453  * the cache iterating over it a few more times is not terribly
454  * costly.
455  */
456 
459  const float *nco = SCULPT_vertex_co_get(ss, ni2.index);
460 
463  if (ni.index == vd.index) {
464  continue;
465  }
466 
467  float vertex_disp[3];
468  float vertex_disp_norm[3];
469 
470  sub_v3_v3v3(vertex_disp, SCULPT_vertex_co_get(ss, ni.index), vd.co);
471 
472  /* Weight by how close we are to our target distance from vd.co. */
473  float w = (1.0f + fabsf(len_v3(vertex_disp) / bstrength - 1.0f));
474 
475  /* TODO: use cotangents (or at least face areas) here. */
476  float len = len_v3v3(SCULPT_vertex_co_get(ss, ni.index), nco);
477  if (len > 0.0f) {
478  len = bstrength / len;
479  }
480  else { /* Coincident point. */
481  len = 1.0f;
482  }
483 
484  /* Multiply weight with edge lengths (in the future this will be
485  * cotangent weights or face areas). */
486  w *= len;
487 
488  /* Build directional weight. */
489 
490  /* Project into vertex plane. */
491  madd_v3_v3fl(vertex_disp, no, -dot_v3v3(no, vertex_disp));
492  normalize_v3_v3(vertex_disp_norm, vertex_disp);
493 
494  if (dot_v3v3(current_disp_norm, vertex_disp_norm) >= 0.0f) {
495  continue;
496  }
497 
498  const float *neighbor_color = ss->cache->prev_colors[ni.index];
499  float color_interp = -dot_v3v3(current_disp_norm, vertex_disp_norm);
500 
501  /* Square directional weight to get a somewhat sharper result. */
502  w *= color_interp * color_interp;
503 
504  madd_v4_v4fl(accum, neighbor_color, w);
505  totw += w;
506  }
508  }
510 
511  if (totw != 0.0f) {
512  mul_v4_fl(accum, 1.0f / totw);
513  }
514 
515  blend_color_mix_float(interp_color, interp_color, accum);
516 
517  float col[4];
519  blend_color_interpolate_float(col, ss->cache->prev_colors[vd.index], interp_color, fade);
521  }
523 }
524 
525 static void do_smear_store_prev_colors_task_cb_exec(void *__restrict userdata,
526  const int n,
527  const TaskParallelTLS *__restrict UNUSED(tls))
528 {
529  SculptThreadedTaskData *data = userdata;
530  SculptSession *ss = data->ob->sculpt;
531 
532  PBVHVertexIter vd;
533  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
535  }
537 }
538 
539 void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
540 {
541  Brush *brush = BKE_paint_brush(&sd->paint);
542  SculptSession *ss = ob->sculpt;
543 
544  if (!SCULPT_has_colors(ss) || ss->cache->bstrength == 0.0f) {
545  return;
546  }
547 
548  const int totvert = SCULPT_vertex_count_get(ss);
549 
550  if (!ss->cache->prev_colors) {
551  ss->cache->prev_colors = MEM_callocN(sizeof(float[4]) * totvert, "prev colors");
552  for (int i = 0; i < totvert; i++) {
553  SCULPT_vertex_color_get(ss, i, ss->cache->prev_colors[i]);
554  }
555  }
556 
558 
560  .sd = sd,
561  .ob = ob,
562  .brush = brush,
563  .nodes = nodes,
564  };
565 
566  TaskParallelSettings settings;
567  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
568 
569  /* Smooth colors mode. */
570  if (ss->cache->alt_smooth) {
572  }
573  else {
574  /* Smear mode. */
576  BLI_task_parallel_range(0, totnode, &data, do_smear_brush_task_cb_exec, &settings);
577  }
578 }
typedef float(TangentPoint)[2]
const float * BKE_brush_secondary_color_get(const struct Scene *scene, const struct Brush *brush)
Definition: brush.cc:2216
const float * BKE_brush_color_get(const struct Scene *scene, const struct Brush *brush)
Definition: brush.cc:2210
bool BKE_colorband_evaluate(const struct ColorBand *coba, float in, float out[4])
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1235
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
#define PBVH_ITER_UNIQUE
Definition: BKE_pbvh.h:391
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode)
Definition: pbvh.c:3211
PBVHColorBufferNode * BKE_pbvh_node_color_buffer_get(PBVHNode *node)
Definition: pbvh.c:3079
BLI_INLINE float BLI_hash_int_01(unsigned int k)
Definition: BLI_hash.h:94
MINLINE void blend_color_mix_float(float dst[4], const float src1[4], const float src2[4])
MINLINE void blend_color_interpolate_float(float dst[4], const float src1[4], const float src2[4], float t)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
Definition: math_matrix.c:259
bool invert_m4_m4(float R[4][4], const float A[4][4])
Definition: math_matrix.c:1287
void scale_m4_fl(float R[4][4], float scale)
Definition: math_matrix.c:2297
bool is_zero_m4(const float mat[4][4])
Definition: math_matrix.c:2520
void normalize_m4(float R[4][4]) ATTR_NONNULL()
Definition: math_matrix.c:1945
MINLINE void mul_v4_fl(float r[4], float f)
MINLINE void add_v4_v4(float r[4], const float a[4])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
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 mul_v4_v4fl(float r[4], const float a[4], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
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])
MINLINE void zero_v4(float r[4])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
bool is_finite_v4(const float a[4]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:354
MINLINE void madd_v4_v4fl(float r[4], const float a[4], float f)
MINLINE void mul_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
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)
#define CLAMP4(vec, b, c)
@ BRUSH_SMEAR_DEFORM_PINCH
@ BRUSH_SMEAR_DEFORM_EXPAND
@ BRUSH_SMEAR_DEFORM_DRAG
@ BRUSH_ANCHORED
@ BRUSH_USE_GRADIENT
@ BRUSH_GRADIENT_SPACING_CLAMP
@ BRUSH_GRADIENT_PRESSURE
@ BRUSH_GRADIENT_SPACING_REPEAT
BLI_INLINE void IMB_colormanagement_srgb_to_scene_linear_v3(float scene_linear[3], const float srgb[3])
void IMB_blend_color_float(float dst[4], const float src1[4], const float src2[4], IMB_BlendMode mode)
Definition: rectop.c:112
Read Guarded memory(de)allocation.
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
int len
Definition: draw_manager.c:108
uint col
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
static const pxr::TfToken density("density", pxr::TfToken::Immortal)
static float noise(int n)
CCL_NAMESPACE_BEGIN ccl_device float fade(float t)
Definition: noise.h:15
const float * SCULPT_vertex_co_get(SculptSession *ss, int index)
Definition: sculpt.c:125
int SCULPT_vertex_count_get(SculptSession *ss)
Definition: sculpt.c:111
void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter)
Definition: sculpt.c:1300
void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node, SculptUndoType type)
Definition: sculpt.c:1290
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
bool SCULPT_brush_test_cube(SculptBrushTest *test, const float co[3], const float local[4][4], const float roundness)
Definition: sculpt.c:1639
void SCULPT_vertex_color_set(SculptSession *ss, int index, const float color[4])
Definition: sculpt.c:166
void SCULPT_vertex_color_get(const SculptSession *ss, int index, float r_color[4])
Definition: sculpt.c:161
void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3])
Definition: sculpt.c:171
bool SCULPT_stroke_is_first_brush_step_of_symmetry_pass(StrokeCache *cache)
Definition: sculpt.c:918
void SCULPT_calc_area_normal(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, float r_area_no[3])
Definition: sculpt.c:2103
bool SCULPT_stroke_is_first_brush_step(StrokeCache *cache)
Definition: sculpt.c:912
bool SCULPT_has_colors(const SculptSession *ss)
Definition: sculpt.c:156
#define SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN(ss, v_index, neighbor_iterator)
bool SCULPT_use_image_paint_brush(struct PaintModeSettings *settings, Object *ob) ATTR_NONNULL()
bool(* SculptBrushTestFn)(SculptBrushTest *test, const float co[3])
#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator)
void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index)
void SCULPT_do_paint_brush_image(struct PaintModeSettings *paint_mode_settings, Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) ATTR_NONNULL()
@ SCULPT_UNDO_COLOR
void SCULPT_do_paint_brush(PaintModeSettings *paint_mode_settings, Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_do_smear_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
static void do_color_smooth_task_cb_exec(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
static void do_smear_brush_task_cb_exec(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
struct SampleWetPaintTLSData SampleWetPaintTLSData
static void sample_wet_paint_reduce(const void *__restrict UNUSED(userdata), void *__restrict chunk_join, void *__restrict chunk)
static void do_smear_store_prev_colors_task_cb_exec(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
static void do_sample_wet_paint_task_cb(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
static void do_paint_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
float alpha
struct ColorBand * gradient
struct CurveMapping * curve
float tip_scale_x
short blend
char gradient_stroke_mode
int gradient_spacing
int smear_deform_type
float tip_roundness
struct SculptSession * sculpt
float(* color)[4]
Definition: BKE_pbvh.h:51
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
const float * col
Definition: sculpt_intern.h:90
struct Scene * scene
Definition: BKE_paint.h:591
struct StrokeCache * cache
Definition: BKE_paint.h:563
struct PBVH * pbvh
Definition: BKE_paint.h:550
struct Sculpt * sd
Paint paint
float wet_mix_prev_color[4]
float last_location[3]
float density_seed
struct StrokeCache::@514 paint_brush
float grab_delta_symmetry[3]
float location[3]
float stroke_distance
float(* prev_colors)[4]
float wet_persistence
TaskParallelReduceFunc func_reduce
Definition: BLI_task.h:181
size_t userdata_chunk_size
Definition: BLI_task.h:169