Blender  V3.3
sculpt_smooth.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_task.h"
14 
15 #include "DNA_brush_types.h"
16 #include "DNA_mesh_types.h"
17 #include "DNA_meshdata_types.h"
18 
19 #include "BKE_brush.h"
20 #include "BKE_context.h"
21 #include "BKE_mesh.h"
22 #include "BKE_mesh_mapping.h"
23 #include "BKE_object.h"
24 #include "BKE_paint.h"
25 #include "BKE_pbvh.h"
26 #include "BKE_scene.h"
27 
28 #include "DEG_depsgraph.h"
29 
30 #include "WM_api.h"
31 #include "WM_message.h"
32 #include "WM_toolsystem.h"
33 #include "WM_types.h"
34 
35 #include "ED_object.h"
36 #include "ED_screen.h"
37 #include "ED_sculpt.h"
38 #include "paint_intern.h"
39 #include "sculpt_intern.h"
40 
41 #include "RNA_access.h"
42 #include "RNA_define.h"
43 
44 #include "bmesh.h"
45 
46 #include <math.h>
47 #include <stdlib.h>
48 
50 {
51  float avg[3] = {0.0f, 0.0f, 0.0f};
52  int total = 0;
53  int neighbor_count = 0;
54  const bool is_boundary = SCULPT_vertex_is_boundary(ss, index);
55 
57  SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) {
58  neighbor_count++;
59  if (is_boundary) {
60  /* Boundary vertices use only other boundary vertices. */
61  if (SCULPT_vertex_is_boundary(ss, ni.index)) {
62  add_v3_v3(avg, SCULPT_vertex_co_get(ss, ni.index));
63  total++;
64  }
65  }
66  else {
67  /* Interior vertices use all neighbors. */
68  add_v3_v3(avg, SCULPT_vertex_co_get(ss, ni.index));
69  total++;
70  }
71  }
73 
74  /* Do not modify corner vertices. */
75  if (neighbor_count <= 2 && is_boundary) {
77  return;
78  }
79 
80  /* Avoid division by 0 when there are no neighbors. */
81  if (total == 0) {
83  return;
84  }
85 
86  mul_v3_v3fl(result, avg, 1.0f / total);
87 }
88 
89 void SCULPT_bmesh_four_neighbor_average(float avg[3], float direction[3], BMVert *v)
90 {
91 
92  float avg_co[3] = {0.0f, 0.0f, 0.0f};
93  float tot_co = 0.0f;
94 
95  BMIter eiter;
96  BMEdge *e;
97 
98  BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) {
99  if (BM_edge_is_boundary(e)) {
100  copy_v3_v3(avg, v->co);
101  return;
102  }
103  BMVert *v_other = (e->v1 == v) ? e->v2 : e->v1;
104  float vec[3];
105  sub_v3_v3v3(vec, v_other->co, v->co);
106  madd_v3_v3fl(vec, v->no, -dot_v3v3(vec, v->no));
107  normalize_v3(vec);
108 
109  /* fac is a measure of how orthogonal or parallel the edge is
110  * relative to the direction. */
111  float fac = dot_v3v3(vec, direction);
112  fac = fac * fac - 0.5f;
113  fac *= fac;
114  madd_v3_v3fl(avg_co, v_other->co, fac);
115  tot_co += fac;
116  }
117 
118  /* In case vert has no Edge s. */
119  if (tot_co > 0.0f) {
120  mul_v3_v3fl(avg, avg_co, 1.0f / tot_co);
121 
122  /* Preserve volume. */
123  float vec[3];
124  sub_v3_v3(avg, v->co);
125  mul_v3_v3fl(vec, v->no, dot_v3v3(avg, v->no));
126  sub_v3_v3(avg, vec);
127  add_v3_v3(avg, v->co);
128  }
129  else {
130  zero_v3(avg);
131  }
132 }
133 
134 /* Generic functions for laplacian smoothing. These functions do not take boundary vertices into
135  * account. */
136 
138 {
139  float avg[3] = {0.0f, 0.0f, 0.0f};
140  int total = 0;
141 
143  SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) {
144  add_v3_v3(avg, SCULPT_vertex_co_get(ss, ni.index));
145  total++;
146  }
148 
149  if (total > 0) {
150  mul_v3_v3fl(result, avg, 1.0f / total);
151  }
152  else {
154  }
155 }
156 
158 {
159  float avg = 0.0f;
160  int total = 0;
161 
163  SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) {
164  avg += SCULPT_vertex_mask_get(ss, ni.index);
165  total++;
166  }
168 
169  if (total > 0) {
170  return avg / total;
171  }
172  return SCULPT_vertex_mask_get(ss, index);
173 }
174 
175 void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index)
176 {
177  float avg[4] = {0.0f, 0.0f, 0.0f, 0.0f};
178  int total = 0;
179 
181  SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, index, ni) {
182  float tmp[4] = {0};
183 
184  SCULPT_vertex_color_get(ss, ni.index, tmp);
185 
186  add_v4_v4(avg, tmp);
187  total++;
188  }
190 
191  if (total > 0) {
192  mul_v4_v4fl(result, avg, 1.0f / total);
193  }
194  else {
195  SCULPT_vertex_color_get(ss, index, result);
196  }
197 }
198 
199 static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata,
200  const int n,
201  const TaskParallelTLS *__restrict tls)
202 {
203  SculptThreadedTaskData *data = userdata;
204  SculptSession *ss = data->ob->sculpt;
205  Sculpt *sd = data->sd;
206  const Brush *brush = data->brush;
207 
208  PBVHVertexIter vd;
209 
210  float bstrength = ss->cache->bstrength;
211  CLAMP(bstrength, -1.0f, 1.0f);
212 
213  SculptBrushTest test;
215  ss, &test, data->brush->falloff_shape);
216 
217  const int thread_id = BLI_task_parallel_thread_id(tls);
218  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
219  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
220  continue;
221  }
222 
223  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
224  brush,
225  vd.co,
226  sqrtf(test.dist),
227  vd.no,
228  vd.fno,
229  vd.mask ? *vd.mask : 0.0f,
230  vd.index,
231  thread_id);
232 
233  float disp[3];
234  madd_v3_v3v3fl(disp, vd.co, ss->cache->detail_directions[vd.index], fade);
235  SCULPT_clip(sd, ss, vd.co, disp);
236 
237  if (vd.mvert) {
239  }
240  }
242 }
243 
245  Object *ob,
246  PBVHNode **nodes,
247  const int totnode)
248 {
249  SculptSession *ss = ob->sculpt;
250  Brush *brush = BKE_paint_brush(&sd->paint);
251 
254 
256  const int totvert = SCULPT_vertex_count_get(ss);
258  totvert, sizeof(float[3]), "details directions");
259 
260  for (int i = 0; i < totvert; i++) {
261  float avg[3];
262  SCULPT_neighbor_coords_average(ss, avg, i);
264  }
265  }
266 
268  .sd = sd,
269  .ob = ob,
270  .brush = brush,
271  .nodes = nodes,
272  };
273 
274  TaskParallelSettings settings;
275  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
277 }
278 
279 static void do_smooth_brush_task_cb_ex(void *__restrict userdata,
280  const int n,
281  const TaskParallelTLS *__restrict tls)
282 {
283  SculptThreadedTaskData *data = userdata;
284  SculptSession *ss = data->ob->sculpt;
285  Sculpt *sd = data->sd;
286  const Brush *brush = data->brush;
287  const bool smooth_mask = data->smooth_mask;
288  float bstrength = data->strength;
289 
290  PBVHVertexIter vd;
291 
292  CLAMP(bstrength, 0.0f, 1.0f);
293 
294  SculptBrushTest test;
296  ss, &test, data->brush->falloff_shape);
297 
298  const int thread_id = BLI_task_parallel_thread_id(tls);
299 
300  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
301  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
302  continue;
303  }
304  const float fade = bstrength * SCULPT_brush_strength_factor(
305  ss,
306  brush,
307  vd.co,
308  sqrtf(test.dist),
309  vd.no,
310  vd.fno,
311  smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f),
312  vd.index,
313  thread_id);
314  if (smooth_mask) {
315  float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask;
316  val *= fade * bstrength;
317  *vd.mask += val;
318  CLAMP(*vd.mask, 0.0f, 1.0f);
319  }
320  else {
321  float avg[3], val[3];
323  sub_v3_v3v3(val, avg, vd.co);
324  madd_v3_v3v3fl(val, vd.co, val, fade);
325  SCULPT_clip(sd, ss, vd.co, val);
326  if (vd.mvert) {
328  }
329  }
330  }
332 }
333 
335  Object *ob,
336  PBVHNode **nodes,
337  const int totnode,
338  float bstrength,
339  const bool smooth_mask)
340 {
341  SculptSession *ss = ob->sculpt;
342  Brush *brush = BKE_paint_brush(&sd->paint);
343 
344  const int max_iterations = 4;
345  const float fract = 1.0f / max_iterations;
347  int iteration, count;
348  float last;
349 
350  CLAMP(bstrength, 0.0f, 1.0f);
351 
352  count = (int)(bstrength * max_iterations);
353  last = max_iterations * (bstrength - count * fract);
354 
355  if (type == PBVH_FACES && !ss->pmap) {
356  BLI_assert_msg(0, "sculpt smooth: pmap missing");
357  return;
358  }
359 
362 
363  for (iteration = 0; iteration <= count; iteration++) {
364  const float strength = (iteration != count) ? 1.0f : last;
365 
367  .sd = sd,
368  .ob = ob,
369  .brush = brush,
370  .nodes = nodes,
371  .smooth_mask = smooth_mask,
372  .strength = strength,
373  };
374 
375  TaskParallelSettings settings;
376  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
377  BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_task_cb_ex, &settings);
378  }
379 }
380 
381 void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
382 {
383  SculptSession *ss = ob->sculpt;
384 
385  /* NOTE: The enhance brush needs to initialize its state on the first brush step. The stroke
386  * strength can become 0 during the stroke, but it can not change sign (the sign is determined
387  * in the beginning of the stroke. So here it is important to not switch to enhance brush in the
388  * middle of the stroke. */
389  if (ss->cache->bstrength < 0.0f) {
390  /* Invert mode, intensify details. */
391  SCULPT_enhance_details_brush(sd, ob, nodes, totnode);
392  }
393  else {
394  /* Regular mode, smooth. */
395  SCULPT_smooth(sd, ob, nodes, totnode, ss->cache->bstrength, false);
396  }
397 }
398 
399 /* HC Smooth Algorithm. */
400 /* From: Improved Laplacian Smoothing of Noisy Surface Meshes */
401 
403  float *disp,
404  const float co[3],
405  float (*laplacian_disp)[3],
406  const int v_index,
407  const float origco[3],
408  const float alpha)
409 {
410  float laplacian_smooth_co[3];
411  float weigthed_o[3], weigthed_q[3], d[3];
412  SCULPT_neighbor_coords_average(ss, laplacian_smooth_co, v_index);
413 
414  mul_v3_v3fl(weigthed_o, origco, alpha);
415  mul_v3_v3fl(weigthed_q, co, 1.0f - alpha);
416  add_v3_v3v3(d, weigthed_o, weigthed_q);
417  sub_v3_v3v3(laplacian_disp[v_index], laplacian_smooth_co, d);
418 
419  sub_v3_v3v3(disp, laplacian_smooth_co, co);
420 }
421 
423  float *co,
424  float (*laplacian_disp)[3],
425  const int v_index,
426  const float beta,
427  const float fade)
428 {
429  float b_avg[3] = {0.0f, 0.0f, 0.0f};
430  float b_current_vertex[3];
431  int total = 0;
433  SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, v_index, ni) {
434  add_v3_v3(b_avg, laplacian_disp[ni.index]);
435  total++;
436  }
438  if (total > 0) {
439  mul_v3_v3fl(b_current_vertex, b_avg, (1.0f - beta) / total);
440  madd_v3_v3fl(b_current_vertex, laplacian_disp[v_index], beta);
441  mul_v3_fl(b_current_vertex, clamp_f(fade, 0.0f, 1.0f));
442  sub_v3_v3(co, b_current_vertex);
443  }
444 }
445 
447  void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
448 {
449  SculptThreadedTaskData *data = userdata;
450  SculptSession *ss = data->ob->sculpt;
451  const Brush *brush = data->brush;
452  const float bstrength = ss->cache->bstrength;
453  float alpha = brush->surface_smooth_shape_preservation;
454 
455  PBVHVertexIter vd;
456  SculptOrigVertData orig_data;
457 
458  SculptBrushTest test;
460  ss, &test, data->brush->falloff_shape);
461  const int thread_id = BLI_task_parallel_thread_id(tls);
462 
463  SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n], SCULPT_UNDO_COORDS);
464 
465  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
466  SCULPT_orig_vert_data_update(&orig_data, &vd);
467  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
468  continue;
469  }
470  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
471  brush,
472  vd.co,
473  sqrtf(test.dist),
474  vd.no,
475  vd.fno,
476  vd.mask ? *vd.mask : 0.0f,
477  vd.index,
478  thread_id);
479 
480  float disp[3];
482  ss, disp, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, orig_data.co, alpha);
483  madd_v3_v3fl(vd.co, disp, clamp_f(fade, 0.0f, 1.0f));
484  if (vd.mvert) {
486  }
487  }
489 }
490 
492  void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
493 {
494  SculptThreadedTaskData *data = userdata;
495  SculptSession *ss = data->ob->sculpt;
496  const Brush *brush = data->brush;
497  const float bstrength = ss->cache->bstrength;
498  const float beta = brush->surface_smooth_current_vertex;
499 
500  PBVHVertexIter vd;
501 
502  SculptBrushTest test;
504  ss, &test, data->brush->falloff_shape);
505  const int thread_id = BLI_task_parallel_thread_id(tls);
506 
507  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
508  if (!sculpt_brush_test_sq_fn(&test, vd.co)) {
509  continue;
510  }
511  const float fade = bstrength * SCULPT_brush_strength_factor(ss,
512  brush,
513  vd.co,
514  sqrtf(test.dist),
515  vd.no,
516  vd.fno,
517  vd.mask ? *vd.mask : 0.0f,
518  vd.index,
519  thread_id);
521  ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade);
522  }
524 }
525 
526 void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
527 {
528  Brush *brush = BKE_paint_brush(&sd->paint);
529 
530  /* Threaded loop over nodes. */
532  .sd = sd,
533  .ob = ob,
534  .brush = brush,
535  .nodes = nodes,
536  };
537 
538  TaskParallelSettings settings;
539  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
540  for (int i = 0; i < brush->surface_smooth_iterations; i++) {
545  }
546 }
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
PBVHType BKE_pbvh_type(const PBVH *pbvh)
Definition: pbvh.c:1798
#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
PBVHType
Definition: BKE_pbvh.h:233
@ PBVH_FACES
Definition: BKE_pbvh.h:234
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode)
Definition: pbvh.c:3211
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
MINLINE float clamp_f(float value, float min, float max)
MINLINE void add_v4_v4(float r[4], const float a[4])
MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f)
MINLINE float normalize_v3(float r[3])
MINLINE void sub_v3_v3(float r[3], const float a[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 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 add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
MINLINE void zero_v3(float r[3])
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])
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)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define BM_ITER_ELEM(ele, iter, data, itype)
@ BM_EDGES_OF_VERT
BLI_INLINE bool BM_edge_is_boundary(const BMEdge *e) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
int count
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
#define sqrtf(x)
Definition: metal/compat.h:243
static float smooth_mask(float x, float y)
float fract(float a)
Definition: node_math.h:21
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
void SCULPT_boundary_info_ensure(Object *object)
Definition: sculpt.c:5848
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
void SCULPT_vertex_random_access_ensure(SculptSession *ss)
Definition: sculpt.c:103
void SCULPT_vertex_color_get(const SculptSession *ss, int index, float r_color[4])
Definition: sculpt.c:161
bool SCULPT_vertex_is_boundary(const SculptSession *ss, const int index)
Definition: sculpt.c:865
float SCULPT_vertex_mask_get(SculptSession *ss, int index)
Definition: sculpt.c:248
bool SCULPT_stroke_is_first_brush_step(StrokeCache *cache)
Definition: sculpt.c:912
void SCULPT_clip(Sculpt *sd, SculptSession *ss, float co[3], const float val[3])
Definition: sculpt.c:2540
#define SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN(ss, v_index, neighbor_iterator)
bool(* SculptBrushTestFn)(SculptBrushTest *test, const float co[3])
#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator)
@ SCULPT_UNDO_COORDS
void SCULPT_surface_smooth_laplacian_step(SculptSession *ss, float *disp, const float co[3], float(*laplacian_disp)[3], const int v_index, const float origco[3], const float alpha)
static void SCULPT_enhance_details_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode)
static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
void SCULPT_do_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
void SCULPT_neighbor_coords_average(SculptSession *ss, float result[3], int index)
float SCULPT_neighbor_mask_average(SculptSession *ss, int index)
void SCULPT_surface_smooth_displace_step(SculptSession *ss, float *co, float(*laplacian_disp)[3], const int v_index, const float beta, const float fade)
void SCULPT_smooth(Sculpt *sd, Object *ob, PBVHNode **nodes, const int totnode, float bstrength, const bool smooth_mask)
static void do_enhance_details_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
void SCULPT_neighbor_coords_average_interior(SculptSession *ss, float result[3], int index)
Definition: sculpt_smooth.c:49
void SCULPT_neighbor_color_average(SculptSession *ss, float result[4], int index)
void SCULPT_bmesh_four_neighbor_average(float avg[3], float direction[3], BMVert *v)
Definition: sculpt_smooth.c:89
static void do_smooth_brush_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict tls)
float co[3]
Definition: bmesh_class.h:87
float no[3]
Definition: bmesh_class.h:88
int surface_smooth_iterations
float surface_smooth_current_vertex
float surface_smooth_shape_preservation
struct SculptSession * sculpt
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
const float * co
Definition: sculpt_intern.h:87
struct MeshElemMap * pmap
Definition: BKE_paint.h:516
struct StrokeCache * cache
Definition: BKE_paint.h:563
struct PBVH * pbvh
Definition: BKE_paint.h:550
Paint paint
float(* surface_smooth_laplacian_disp)[3]
float(* detail_directions)[3]
ccl_device_inline float beta(float x, float y)
Definition: util/math.h:775