Blender  V2.93
sculpt_boundary.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_edgehash.h"
28 #include "BLI_math.h"
29 #include "BLI_task.h"
30 
31 #include "DNA_brush_types.h"
32 #include "DNA_mesh_types.h"
33 #include "DNA_meshdata_types.h"
34 #include "DNA_object_types.h"
35 
36 #include "BKE_brush.h"
37 #include "BKE_ccg.h"
38 #include "BKE_colortools.h"
39 #include "BKE_context.h"
40 #include "BKE_mesh.h"
41 #include "BKE_multires.h"
42 #include "BKE_node.h"
43 #include "BKE_object.h"
44 #include "BKE_paint.h"
45 #include "BKE_pbvh.h"
46 #include "BKE_scene.h"
47 
48 #include "paint_intern.h"
49 #include "sculpt_intern.h"
50 
51 #include "GPU_immediate.h"
52 #include "GPU_immediate_util.h"
53 #include "GPU_matrix.h"
54 #include "GPU_state.h"
55 
56 #include "bmesh.h"
57 
58 #include <math.h>
59 #include <stdlib.h>
60 
61 #define BOUNDARY_VERTEX_NONE -1
62 #define BOUNDARY_STEPS_NONE -1
63 
69  float radius_sq;
71 
73  SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
74 {
76 
77  if (!SCULPT_vertex_visible_get(ss, to_v)) {
78  return false;
79  }
80 
81  if (!is_duplicate) {
82  data->floodfill_steps[to_v] = data->floodfill_steps[from_v] + 1;
83  }
84  else {
85  data->floodfill_steps[to_v] = data->floodfill_steps[from_v];
86  }
87 
88  if (SCULPT_vertex_is_boundary(ss, to_v)) {
89  if (data->floodfill_steps[to_v] < data->boundary_initial_vertex_steps) {
90  data->boundary_initial_vertex_steps = data->floodfill_steps[to_v];
91  data->boundary_initial_vertex = to_v;
92  }
93  }
94 
95  const float len_sq = len_squared_v3v3(SCULPT_vertex_co_get(ss, data->initial_vertex),
96  SCULPT_vertex_co_get(ss, to_v));
97  return len_sq < data->radius_sq;
98 }
99 
100 /* From a vertex index anywhere in the mesh, returns the closest vertex in a mesh boundary inside
101  * the given radius, if it exists. */
103  const int initial_vertex,
104  const float radius)
105 {
106 
107  if (SCULPT_vertex_is_boundary(ss, initial_vertex)) {
108  return initial_vertex;
109  }
110 
111  SculptFloodFill flood;
112  SCULPT_floodfill_init(ss, &flood);
113  SCULPT_floodfill_add_initial(&flood, initial_vertex);
114 
116  .initial_vertex = initial_vertex,
117  .boundary_initial_vertex = BOUNDARY_VERTEX_NONE,
118  .boundary_initial_vertex_steps = INT_MAX,
119  .radius_sq = radius * radius,
120  };
121 
123  SCULPT_vertex_count_get(ss), sizeof(int), "floodfill steps");
124 
126  SCULPT_floodfill_free(&flood);
127 
128  MEM_freeN(fdata.floodfill_steps);
129  return fdata.boundary_initial_vertex;
130 }
131 
132 /* Used to allocate the memory of the boundary index arrays. This was decided considered the most
133  * common use cases for the brush deformers, taking into account how many vertices those
134  * deformations usually need in the boundary. */
136 
138  const int new_index,
139  const float distance,
140  GSet *included_vertices)
141 {
142 
143  boundary->vertices[boundary->num_vertices] = new_index;
144  if (boundary->distance) {
145  boundary->distance[new_index] = distance;
146  }
147  if (included_vertices) {
148  BLI_gset_add(included_vertices, POINTER_FROM_INT(new_index));
149  }
150  boundary->num_vertices++;
151  if (boundary->num_vertices >= boundary->vertices_capacity) {
153  boundary->vertices = MEM_reallocN_id(
154  boundary->vertices, boundary->vertices_capacity * sizeof(int), "boundary indices");
155  }
156 };
157 
158 static void sculpt_boundary_preview_edge_add(SculptBoundary *boundary, const int v1, const int v2)
159 {
160 
161  boundary->edges[boundary->num_edges].v1 = v1;
162  boundary->edges[boundary->num_edges].v2 = v2;
163  boundary->num_edges++;
164 
165  if (boundary->num_edges >= boundary->edges_capacity) {
167  boundary->edges = MEM_reallocN_id(boundary->edges,
168  boundary->edges_capacity * sizeof(SculptBoundaryPreviewEdge),
169  "boundary edges");
170  }
171 };
172 
178  const int initial_vertex)
179 {
180 
181  if (!SCULPT_vertex_visible_get(ss, initial_vertex)) {
182  return false;
183  }
184 
185  int neighbor_count = 0;
186  int boundary_vertex_count = 0;
188  SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN (ss, initial_vertex, ni) {
189  if (SCULPT_vertex_visible_get(ss, ni.index)) {
190  neighbor_count++;
191  if (SCULPT_vertex_is_boundary(ss, ni.index)) {
192  boundary_vertex_count++;
193  }
194  }
195  }
197 
198  /* Corners are ambiguous as it can't be decide which boundary should be active. The flood fill
199  * should also stop at corners. */
200  if (neighbor_count <= 2) {
201  return false;
202  }
203 
204  /* Non manifold geometry in the mesh boundary.
205  * The deformation result will be unpredictable and not very useful. */
206  if (boundary_vertex_count > 2) {
207  return false;
208  }
209 
210  return true;
211 }
212 
213 /* Flood fill that adds to the boundary data all the vertices from a boundary and its duplicates.
214  */
215 
216 typedef struct BoundaryFloodFillData {
220 
222 
224 
226  SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
227 {
228  BoundaryFloodFillData *data = userdata;
229  SculptBoundary *boundary = data->boundary;
230  if (!SCULPT_vertex_is_boundary(ss, to_v)) {
231  return false;
232  }
233  const float edge_len = len_v3v3(SCULPT_vertex_co_get(ss, from_v),
234  SCULPT_vertex_co_get(ss, to_v));
235  const float distance_boundary_to_dst = boundary->distance ?
236  boundary->distance[from_v] + edge_len :
237  0.0f;
238  sculpt_boundary_index_add(boundary, to_v, distance_boundary_to_dst, data->included_vertices);
239  if (!is_duplicate) {
240  sculpt_boundary_preview_edge_add(boundary, from_v, to_v);
241  }
243 }
244 
246  SculptBoundary *boundary,
247  const bool init_boundary_distances,
248  const int initial_boundary_index)
249 {
250 
251  const int totvert = SCULPT_vertex_count_get(ss);
252  boundary->vertices = MEM_malloc_arrayN(
253  BOUNDARY_INDICES_BLOCK_SIZE, sizeof(int), "boundary indices");
254  if (init_boundary_distances) {
255  boundary->distance = MEM_calloc_arrayN(totvert, sizeof(float), "boundary distances");
256  }
257  boundary->edges = MEM_malloc_arrayN(
258  BOUNDARY_INDICES_BLOCK_SIZE, sizeof(SculptBoundaryPreviewEdge), "boundary edges");
259 
260  GSet *included_vertices = BLI_gset_int_new_ex("included vertices", BOUNDARY_INDICES_BLOCK_SIZE);
261  SculptFloodFill flood;
262  SCULPT_floodfill_init(ss, &flood);
263 
264  boundary->initial_vertex = initial_boundary_index;
266  SCULPT_vertex_co_get(ss, boundary->initial_vertex));
267  sculpt_boundary_index_add(boundary, initial_boundary_index, 0.0f, included_vertices);
268  SCULPT_floodfill_add_initial(&flood, initial_boundary_index);
269 
270  BoundaryFloodFillData fdata = {
271  .boundary = boundary,
272  .included_vertices = included_vertices,
273  .last_visited_vertex = BOUNDARY_VERTEX_NONE,
274 
275  };
276 
277  SCULPT_floodfill_execute(ss, &flood, boundary_floodfill_cb, &fdata);
278  SCULPT_floodfill_free(&flood);
279 
280  /* Check if the boundary loops into itself and add the extra preview edge to close the loop. */
285  if (BLI_gset_haskey(included_vertices, POINTER_FROM_INT(ni.index)) &&
288  boundary->forms_loop = true;
289  }
290  }
292  }
293 
294  BLI_gset_free(included_vertices, NULL);
295 }
296 
304  SculptBoundary *boundary,
305  const int initial_vertex,
306  const float radius)
307 {
308  const int totvert = SCULPT_vertex_count_get(ss);
309 
310  const bool has_duplicates = BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS;
311 
312  boundary->edit_info = MEM_malloc_arrayN(
313  totvert, sizeof(SculptBoundaryEditInfo), "Boundary edit info");
314 
315  for (int i = 0; i < totvert; i++) {
318  }
319 
320  GSQueue *current_iteration = BLI_gsqueue_new(sizeof(int));
321  GSQueue *next_iteration = BLI_gsqueue_new(sizeof(int));
322 
323  /* Initialized the first iteration with the vertices already in the boundary. This is propagation
324  * step 0. */
325  BLI_bitmap *visited_vertices = BLI_BITMAP_NEW(SCULPT_vertex_count_get(ss), "visited_vertices");
326  for (int i = 0; i < boundary->num_vertices; i++) {
327  boundary->edit_info[boundary->vertices[i]].original_vertex = boundary->vertices[i];
328  boundary->edit_info[boundary->vertices[i]].num_propagation_steps = 0;
329 
330  /* This ensures that all duplicate vertices in the boundary have the same original_vertex
331  * index, so the deformation for them will be the same. */
332  if (has_duplicates) {
333  SculptVertexNeighborIter ni_duplis;
334  SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN (ss, boundary->vertices[i], ni_duplis) {
335  if (ni_duplis.is_duplicate) {
336  boundary->edit_info[ni_duplis.index].original_vertex = boundary->vertices[i];
337  }
338  }
340  }
341 
342  BLI_gsqueue_push(current_iteration, &boundary->vertices[i]);
343  }
344 
345  int num_propagation_steps = 0;
346  float accum_distance = 0.0f;
347 
348  while (true) {
349  /* Stop adding steps to edit info. This happens when a steps is further away from the boundary
350  * than the brush radius or when the entire mesh was already processed. */
351  if (accum_distance > radius || BLI_gsqueue_is_empty(current_iteration)) {
352  boundary->max_propagation_steps = num_propagation_steps;
353  break;
354  }
355 
356  while (!BLI_gsqueue_is_empty(current_iteration)) {
357  int from_v;
358  BLI_gsqueue_pop(current_iteration, &from_v);
359 
362  const bool is_visible = SCULPT_vertex_visible_get(ss, ni.index);
363  if (!is_visible ||
365  continue;
366  }
367  boundary->edit_info[ni.index].original_vertex =
368  boundary->edit_info[from_v].original_vertex;
369 
370  BLI_BITMAP_ENABLE(visited_vertices, ni.index);
371 
372  if (ni.is_duplicate) {
373  /* Grids duplicates handling. */
374  boundary->edit_info[ni.index].num_propagation_steps =
375  boundary->edit_info[from_v].num_propagation_steps;
376  }
377  else {
378  boundary->edit_info[ni.index].num_propagation_steps =
379  boundary->edit_info[from_v].num_propagation_steps + 1;
380 
381  BLI_gsqueue_push(next_iteration, &ni.index);
382 
383  /* When copying the data to the neighbor for the next iteration, it has to be copied to
384  * all its duplicates too. This is because it is not possible to know if the updated
385  * neighbor or one if its uninitialized duplicates is going to come first in order to
386  * copy the data in the from_v neighbor iterator. */
387  if (has_duplicates) {
388  SculptVertexNeighborIter ni_duplis;
390  if (ni_duplis.is_duplicate) {
391  boundary->edit_info[ni_duplis.index].original_vertex =
392  boundary->edit_info[from_v].original_vertex;
393  boundary->edit_info[ni_duplis.index].num_propagation_steps =
394  boundary->edit_info[from_v].num_propagation_steps + 1;
395  }
396  }
398  }
399 
400  /* Check the distance using the vertex that was propagated from the initial vertex that
401  * was used to initialize the boundary. */
402  if (boundary->edit_info[from_v].original_vertex == initial_vertex) {
403  boundary->pivot_vertex = ni.index;
405  accum_distance += len_v3v3(SCULPT_vertex_co_get(ss, from_v),
406  SCULPT_vertex_co_get(ss, ni.index));
407  }
408  }
409  }
411  }
412 
413  /* Copy the new vertices to the queue to be processed in the next iteration. */
414  while (!BLI_gsqueue_is_empty(next_iteration)) {
415  int next_v;
416  BLI_gsqueue_pop(next_iteration, &next_v);
417  BLI_gsqueue_push(current_iteration, &next_v);
418  }
419 
420  num_propagation_steps++;
421  }
422 
423  MEM_SAFE_FREE(visited_vertices);
424 
425  BLI_gsqueue_free(current_iteration);
426  BLI_gsqueue_free(next_iteration);
427 }
428 
429 /* This functions assigns a falloff factor to each one of the SculptBoundaryEditInfo structs based
430  * on the brush curve and its propagation steps. The falloff goes from the boundary into the mesh.
431  */
433  SculptBoundary *boundary,
434  Brush *brush,
435  const float radius)
436 {
437  const int totvert = SCULPT_vertex_count_get(ss);
439 
440  for (int i = 0; i < totvert; i++) {
441  if (boundary->edit_info[i].num_propagation_steps != -1) {
443  brush, boundary->edit_info[i].num_propagation_steps, boundary->max_propagation_steps);
444  }
445 
446  if (boundary->edit_info[i].original_vertex == boundary->initial_vertex) {
447  /* All vertices that are propagated from the original vertex won't be affected by the
448  * boundary falloff, so there is no need to calculate anything else. */
449  continue;
450  }
451 
452  if (!boundary->distance) {
453  /* There are falloff modes that do not require to modify the previously calculated falloff
454  * based on boundary distances. */
455  continue;
456  }
457 
458  const float boundary_distance = boundary->distance[boundary->edit_info[i].original_vertex];
459  float falloff_distance = 0.0f;
460  float direction = 1.0f;
461 
462  switch (brush->boundary_falloff_type) {
464  falloff_distance = boundary_distance;
465  break;
467  const int div = boundary_distance / radius;
468  const float mod = fmodf(boundary_distance, radius);
469  falloff_distance = div % 2 == 0 ? mod : radius - mod;
470  } break;
472  const int div = boundary_distance / radius;
473  const float mod = fmodf(boundary_distance, radius);
474  falloff_distance = div % 2 == 0 ? mod : radius - mod;
475  /* Inverts the faloff in the intervals 1 2 5 6 9 10 ... */
476  if (((div - 1) & 2) == 0) {
477  direction = -1.0f;
478  }
479  } break;
481  /* For constant falloff distances are not allocated, so this should never happen. */
482  BLI_assert(false);
483  }
484 
485  boundary->edit_info[i].strength_factor *= direction * BKE_brush_curve_strength(
486  brush, falloff_distance, radius);
487  }
488 }
489 
490 /* Main function to get SculptBoundary data both for brush deformation and viewport preview. Can
491  * return NULL if there is no boundary from the given vertex using the given radius. */
493  Brush *brush,
494  const int initial_vertex,
495  const float radius)
496 {
497  SculptSession *ss = object->sculpt;
498 
499  if (initial_vertex == BOUNDARY_VERTEX_NONE) {
500  return NULL;
501  }
502 
505 
506  const int boundary_initial_vertex = sculpt_boundary_get_closest_boundary_vertex(
507  ss, initial_vertex, radius);
508 
509  if (boundary_initial_vertex == BOUNDARY_VERTEX_NONE) {
510  return NULL;
511  }
512 
513  /* Starting from a vertex that is the limit of a boundary is ambiguous, so return NULL instead of
514  * forcing a random active boundary from a corner. */
515  if (!sculpt_boundary_is_vertex_in_editable_boundary(ss, initial_vertex)) {
516  return NULL;
517  }
518 
519  SculptBoundary *boundary = MEM_callocN(sizeof(SculptBoundary), "Boundary edit data");
520 
521  const bool init_boundary_distances = brush ? brush->boundary_falloff_type !=
523  false;
524 
525  sculpt_boundary_indices_init(ss, boundary, init_boundary_distances, boundary_initial_vertex);
526 
527  const float boundary_radius = brush ? radius * (1.0f + brush->boundary_offset) : radius;
528  sculpt_boundary_edit_data_init(ss, boundary, boundary_initial_vertex, boundary_radius);
529 
530  return boundary;
531 }
532 
534 {
535  MEM_SAFE_FREE(boundary->vertices);
536  MEM_SAFE_FREE(boundary->edges);
537  MEM_SAFE_FREE(boundary->distance);
538  MEM_SAFE_FREE(boundary->edit_info);
541  MEM_SAFE_FREE(boundary->slide.directions);
542  MEM_SAFE_FREE(boundary);
543 }
544 
545 /* These functions initialize the required vectors for the desired deformation using the
546  * SculptBoundaryEditInfo. They calculate the data using the vertices that have the
547  * max_propagation_steps value and them this data is copied to the rest of the vertices using the
548  * original vertex index. */
550 {
551  const int totvert = SCULPT_vertex_count_get(ss);
553  totvert, 3 * sizeof(float), "pivot rotation axis");
555  totvert, 3 * sizeof(float), "pivot positions");
556 
557  for (int i = 0; i < totvert; i++) {
558  if (boundary->edit_info[i].num_propagation_steps != boundary->max_propagation_steps) {
559  continue;
560  }
561  float dir[3];
562  float normal[3];
564  sub_v3_v3v3(dir,
566  SCULPT_vertex_co_get(ss, i));
568  boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex], dir, normal);
570  copy_v3_v3(boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex],
571  SCULPT_vertex_co_get(ss, i));
572  }
573 
574  for (int i = 0; i < totvert; i++) {
576  continue;
577  }
578  copy_v3_v3(boundary->bend.pivot_positions[i],
579  boundary->bend.pivot_positions[boundary->edit_info[i].original_vertex]);
580  copy_v3_v3(boundary->bend.pivot_rotation_axis[i],
581  boundary->bend.pivot_rotation_axis[boundary->edit_info[i].original_vertex]);
582  }
583 }
584 
586 {
587  const int totvert = SCULPT_vertex_count_get(ss);
588  boundary->slide.directions = MEM_calloc_arrayN(totvert, 3 * sizeof(float), "slide directions");
589 
590  for (int i = 0; i < totvert; i++) {
591  if (boundary->edit_info[i].num_propagation_steps != boundary->max_propagation_steps) {
592  continue;
593  }
594  sub_v3_v3v3(boundary->slide.directions[boundary->edit_info[i].original_vertex],
596  SCULPT_vertex_co_get(ss, i));
597  normalize_v3(boundary->slide.directions[boundary->edit_info[i].original_vertex]);
598  }
599 
600  for (int i = 0; i < totvert; i++) {
602  continue;
603  }
604  copy_v3_v3(boundary->slide.directions[i],
605  boundary->slide.directions[boundary->edit_info[i].original_vertex]);
606  }
607 }
608 
610 {
611  zero_v3(boundary->twist.pivot_position);
612  float(*poly_verts)[3] = MEM_malloc_arrayN(
613  boundary->num_vertices, sizeof(float) * 3, "poly verts");
614  for (int i = 0; i < boundary->num_vertices; i++) {
615  add_v3_v3(boundary->twist.pivot_position, SCULPT_vertex_co_get(ss, boundary->vertices[i]));
616  copy_v3_v3(poly_verts[i], SCULPT_vertex_co_get(ss, boundary->vertices[i]));
617  }
618  mul_v3_fl(boundary->twist.pivot_position, 1.0f / boundary->num_vertices);
619  if (boundary->forms_loop) {
620  normal_poly_v3(boundary->twist.rotation_axis, poly_verts, boundary->num_vertices);
621  }
622  else {
623  sub_v3_v3v3(boundary->twist.rotation_axis,
624  SCULPT_vertex_co_get(ss, boundary->pivot_vertex),
625  SCULPT_vertex_co_get(ss, boundary->initial_vertex));
626  normalize_v3(boundary->twist.rotation_axis);
627  }
628  MEM_freeN(poly_verts);
629 }
630 
632  SculptBoundary *boundary)
633 {
634  float plane[4];
635  float pos[3];
636  float normal[3];
641  return dist_signed_to_plane_v3(pos, plane);
642 }
643 
644 /* Deformation tasks callbacks. */
645 static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata,
646  const int n,
647  const TaskParallelTLS *__restrict UNUSED(tls))
648 {
649  SculptThreadedTaskData *data = userdata;
650  SculptSession *ss = data->ob->sculpt;
651  const int symm_area = ss->cache->mirror_symmetry_pass;
652  SculptBoundary *boundary = ss->cache->boundaries[symm_area];
654  const Brush *brush = data->brush;
655 
656  const float strength = ss->cache->bstrength;
657 
658  PBVHVertexIter vd;
659  SculptOrigVertData orig_data;
660  SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
661 
662  const float disp = strength * sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
663  float angle_factor = disp / ss->cache->radius;
664  /* Angle Snapping when inverting the brush. */
665  if (ss->cache->invert) {
666  angle_factor = floorf(angle_factor * 10) / 10.0f;
667  }
668  const float angle = angle_factor * M_PI;
669 
670  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
671  if (boundary->edit_info[vd.index].num_propagation_steps == -1) {
672  continue;
673  }
674 
675  SCULPT_orig_vert_data_update(&orig_data, &vd);
677  orig_data.co, boundary->initial_vertex_position, symm)) {
678  continue;
679  }
680 
681  const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
682  const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index);
683  float t_orig_co[3];
684  float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
685  sub_v3_v3v3(t_orig_co, orig_data.co, boundary->bend.pivot_positions[vd.index]);
686  rotate_v3_v3v3fl(target_co,
687  t_orig_co,
688  boundary->bend.pivot_rotation_axis[vd.index],
689  angle * boundary->edit_info[vd.index].strength_factor * mask * automask);
690  add_v3_v3(target_co, boundary->bend.pivot_positions[vd.index]);
691 
692  if (vd.mvert) {
694  }
695  }
697 }
698 
699 static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata,
700  const int n,
701  const TaskParallelTLS *__restrict UNUSED(tls))
702 {
703  SculptThreadedTaskData *data = userdata;
704  SculptSession *ss = data->ob->sculpt;
705  const int symm_area = ss->cache->mirror_symmetry_pass;
706  SculptBoundary *boundary = ss->cache->boundaries[symm_area];
708  const Brush *brush = data->brush;
709 
710  const float strength = ss->cache->bstrength;
711 
712  PBVHVertexIter vd;
713  SculptOrigVertData orig_data;
714  SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
715 
716  const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
717 
718  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
719  if (boundary->edit_info[vd.index].num_propagation_steps == -1) {
720  continue;
721  }
722 
723  SCULPT_orig_vert_data_update(&orig_data, &vd);
725  orig_data.co, boundary->initial_vertex_position, symm)) {
726  continue;
727  }
728 
729  const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
730  const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index);
731  float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
732  madd_v3_v3v3fl(target_co,
733  orig_data.co,
734  boundary->slide.directions[vd.index],
735  boundary->edit_info[vd.index].strength_factor * disp * mask * automask *
736  strength);
737 
738  if (vd.mvert) {
740  }
741  }
743 }
744 
745 static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata,
746  const int n,
747  const TaskParallelTLS *__restrict UNUSED(tls))
748 {
749  SculptThreadedTaskData *data = userdata;
750  SculptSession *ss = data->ob->sculpt;
751  const int symm_area = ss->cache->mirror_symmetry_pass;
752  SculptBoundary *boundary = ss->cache->boundaries[symm_area];
754  const Brush *brush = data->brush;
755 
756  const float strength = ss->cache->bstrength;
757 
758  PBVHVertexIter vd;
759  SculptOrigVertData orig_data;
760  SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
761 
762  const float disp = sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
763 
764  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
765  if (boundary->edit_info[vd.index].num_propagation_steps == -1) {
766  continue;
767  }
768 
769  SCULPT_orig_vert_data_update(&orig_data, &vd);
771  orig_data.co, boundary->initial_vertex_position, symm)) {
772  continue;
773  }
774 
775  const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
776  const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index);
777  float normal[3];
778  normal_short_to_float_v3(normal, orig_data.no);
779  float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
780  madd_v3_v3v3fl(target_co,
781  orig_data.co,
782  normal,
783  boundary->edit_info[vd.index].strength_factor * disp * mask * automask *
784  strength);
785 
786  if (vd.mvert) {
788  }
789  }
791 }
792 
793 static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata,
794  const int n,
795  const TaskParallelTLS *__restrict UNUSED(tls))
796 {
797  SculptThreadedTaskData *data = userdata;
798  SculptSession *ss = data->ob->sculpt;
799  const int symm_area = ss->cache->mirror_symmetry_pass;
800  SculptBoundary *boundary = ss->cache->boundaries[symm_area];
802  const Brush *brush = data->brush;
803 
804  const float strength = ss->cache->bstrength;
805 
806  PBVHVertexIter vd;
807  SculptOrigVertData orig_data;
808  SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
809 
810  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
811  if (boundary->edit_info[vd.index].num_propagation_steps == -1) {
812  continue;
813  }
814 
815  SCULPT_orig_vert_data_update(&orig_data, &vd);
817  orig_data.co, boundary->initial_vertex_position, symm)) {
818  continue;
819  }
820 
821  const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
822  const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index);
823  float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
824  madd_v3_v3v3fl(target_co,
825  orig_data.co,
827  boundary->edit_info[vd.index].strength_factor * mask * automask * strength);
828 
829  if (vd.mvert) {
831  }
832  }
834 }
835 
836 static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata,
837  const int n,
838  const TaskParallelTLS *__restrict UNUSED(tls))
839 {
840  SculptThreadedTaskData *data = userdata;
841  SculptSession *ss = data->ob->sculpt;
842  const int symm_area = ss->cache->mirror_symmetry_pass;
843  SculptBoundary *boundary = ss->cache->boundaries[symm_area];
845  const Brush *brush = data->brush;
846 
847  const float strength = ss->cache->bstrength;
848 
849  PBVHVertexIter vd;
850  SculptOrigVertData orig_data;
851  SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
852 
853  const float disp = strength * sculpt_boundary_displacement_from_grab_delta_get(ss, boundary);
854  float angle_factor = disp / ss->cache->radius;
855  /* Angle Snapping when inverting the brush. */
856  if (ss->cache->invert) {
857  angle_factor = floorf(angle_factor * 10) / 10.0f;
858  }
859  const float angle = angle_factor * M_PI;
860 
861  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
862  if (boundary->edit_info[vd.index].num_propagation_steps == -1) {
863  continue;
864  }
865 
866  SCULPT_orig_vert_data_update(&orig_data, &vd);
868  orig_data.co, boundary->initial_vertex_position, symm)) {
869  continue;
870  }
871 
872  const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
873  const float automask = SCULPT_automasking_factor_get(ss->cache->automasking, ss, vd.index);
874  float t_orig_co[3];
875  float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
876  sub_v3_v3v3(t_orig_co, orig_data.co, boundary->twist.pivot_position);
877  rotate_v3_v3v3fl(target_co,
878  t_orig_co,
879  boundary->twist.rotation_axis,
880  angle * mask * automask * boundary->edit_info[vd.index].strength_factor);
881  add_v3_v3(target_co, boundary->twist.pivot_position);
882 
883  if (vd.mvert) {
885  }
886  }
888 }
889 
890 static void do_boundary_brush_smooth_task_cb_ex(void *__restrict userdata,
891  const int n,
892  const TaskParallelTLS *__restrict UNUSED(tls))
893 {
894  SculptThreadedTaskData *data = userdata;
895  SculptSession *ss = data->ob->sculpt;
896  const int symmetry_pass = ss->cache->mirror_symmetry_pass;
897  const SculptBoundary *boundary = ss->cache->boundaries[symmetry_pass];
899  const Brush *brush = data->brush;
900 
901  const float strength = ss->cache->bstrength;
902 
903  PBVHVertexIter vd;
904  SculptOrigVertData orig_data;
905  SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]);
906 
907  BKE_pbvh_vertex_iter_begin (ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) {
908  if (boundary->edit_info[vd.index].num_propagation_steps == -1) {
909  continue;
910  }
911 
912  SCULPT_orig_vert_data_update(&orig_data, &vd);
914  orig_data.co, boundary->initial_vertex_position, symm)) {
915  continue;
916  }
917 
918  float coord_accum[3] = {0.0f, 0.0f, 0.0f};
919  int total_neighbors = 0;
920  const int current_propagation_steps = boundary->edit_info[vd.index].num_propagation_steps;
923  if (current_propagation_steps == boundary->edit_info[ni.index].num_propagation_steps) {
924  add_v3_v3(coord_accum, SCULPT_vertex_co_get(ss, ni.index));
925  total_neighbors++;
926  }
927  }
929 
930  if (total_neighbors == 0) {
931  continue;
932  }
933  float disp[3];
934  float avg[3];
935  const float mask = vd.mask ? 1.0f - *vd.mask : 1.0f;
936  mul_v3_v3fl(avg, coord_accum, 1.0f / total_neighbors);
937  sub_v3_v3v3(disp, avg, vd.co);
938  float *target_co = SCULPT_brush_deform_target_vertex_co_get(ss, brush->deform_target, &vd);
940  target_co, vd.co, disp, boundary->edit_info[vd.index].strength_factor * mask * strength);
941 
942  if (vd.mvert) {
944  }
945  }
947 }
948 
949 /* Main Brush Function. */
950 void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
951 {
952  SculptSession *ss = ob->sculpt;
953  Brush *brush = BKE_paint_brush(&sd->paint);
954 
955  const int symm_area = ss->cache->mirror_symmetry_pass;
957 
958  int initial_vertex;
959  if (ss->cache->mirror_symmetry_pass == 0) {
960  initial_vertex = SCULPT_active_vertex_get(ss);
961  }
962  else {
963  float location[3];
964  flip_v3_v3(location, SCULPT_active_vertex_co_get(ss), symm_area);
965  initial_vertex = SCULPT_nearest_vertex_get(
966  sd, ob, location, ss->cache->radius_squared, false);
967  }
968 
969  ss->cache->boundaries[symm_area] = SCULPT_boundary_data_init(
970  ob, brush, initial_vertex, ss->cache->initial_radius);
971 
972  if (ss->cache->boundaries[symm_area]) {
973 
974  switch (brush->boundary_deform_type) {
976  sculpt_boundary_bend_data_init(ss, ss->cache->boundaries[symm_area]);
977  break;
979  sculpt_boundary_slide_data_init(ss, ss->cache->boundaries[symm_area]);
980  break;
982  sculpt_boundary_twist_data_init(ss, ss->cache->boundaries[symm_area]);
983  break;
986  /* Do nothing. These deform modes don't need any extra data to be precomputed. */
987  break;
988  }
989 
991  ss, ss->cache->boundaries[symm_area], brush, ss->cache->initial_radius);
992  }
993  }
994 
995  /* No active boundary under the cursor. */
996  if (!ss->cache->boundaries[symm_area]) {
997  return;
998  }
999 
1001  .sd = sd,
1002  .ob = ob,
1003  .brush = brush,
1004  .nodes = nodes,
1005  };
1006 
1007  TaskParallelSettings settings;
1008  BKE_pbvh_parallel_range_settings(&settings, true, totnode);
1009 
1010  switch (brush->boundary_deform_type) {
1013  break;
1016  break;
1019  break;
1022  break;
1025  break;
1028  break;
1029  }
1030 }
1031 
1033  SculptSession *ss,
1034  const float outline_col[3],
1035  const float outline_alpha)
1036 {
1037  if (!ss->boundary_preview) {
1038  return;
1039  }
1040  immUniformColor3fvAlpha(outline_col, outline_alpha);
1041  GPU_line_width(2.0f);
1043  for (int i = 0; i < ss->boundary_preview->num_edges; i++) {
1046  }
1047  immEnd();
1048 }
1049 
1051 {
1052  if (!ss->boundary_preview) {
1053  return;
1054  }
1055  immUniformColor4f(1.0f, 1.0f, 1.0f, 0.8f);
1056  GPU_line_width(2.0f);
1060  immEnd();
1061 }
typedef float(TangentPoint)[2]
float BKE_brush_curve_strength(const struct Brush *br, float p, const float len)
void BKE_curvemapping_init(struct CurveMapping *cumap)
Definition: colortools.c:1200
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
PBVHType BKE_pbvh_type(const PBVH *pbvh)
Definition: pbvh.c:1661
#define BKE_pbvh_vertex_iter_end
Definition: BKE_pbvh.h:457
#define PBVH_ITER_UNIQUE
Definition: BKE_pbvh.h:335
@ PBVH_GRIDS
Definition: BKE_pbvh.h:211
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode)
Definition: pbvh.c:3042
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define BLI_BITMAP_ENABLE(_bitmap, _index)
Definition: BLI_bitmap.h:78
#define BLI_BITMAP_NEW(_tot, _alloc_string)
Definition: BLI_bitmap.h:50
unsigned int BLI_bitmap
Definition: BLI_bitmap.h:32
struct GSet GSet
Definition: BLI_ghash.h:189
bool BLI_gset_haskey(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT
Definition: BLI_ghash.c:1216
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
Definition: BLI_ghash.c:1253
bool BLI_gset_add(GSet *gs, void *key)
Definition: BLI_ghash.c:1160
GSet * BLI_gset_int_new_ex(const char *info, const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
void BLI_gsqueue_free(GSQueue *queue)
Definition: gsqueue.c:107
void BLI_gsqueue_push(GSQueue *queue, const void *item)
Definition: gsqueue.c:122
GSQueue * BLI_gsqueue_new(const size_t elem_size)
Definition: gsqueue.c:83
void BLI_gsqueue_pop(GSQueue *queue, void *r_item)
Definition: gsqueue.c:162
bool BLI_gsqueue_is_empty(const GSQueue *queue)
Definition: gsqueue.c:193
#define M_PI
Definition: BLI_math_base.h:38
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
float dist_signed_to_plane_v3(const float p[3], const float plane[4])
Definition: math_geom.c:468
float normal_poly_v3(float n[3], const float verts[][3], unsigned int nr)
Definition: math_geom.c:94
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE float normalize_v3(float r[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
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 void add_v3_v3v3(float r[3], const float a[3], const float b[3])
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
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])
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
#define POINTER_FROM_INT(i)
#define UNUSED(x)
@ BRUSH_BOUNDARY_DEFORM_GRAB
@ BRUSH_BOUNDARY_DEFORM_TWIST
@ BRUSH_BOUNDARY_DEFORM_BEND
@ BRUSH_BOUNDARY_DEFORM_EXPAND
@ BRUSH_BOUNDARY_DEFORM_INFLATE
@ BRUSH_BOUNDARY_DEFORM_SMOOTH
@ BRUSH_BOUNDARY_FALLOFF_CONSTANT
@ BRUSH_BOUNDARY_FALLOFF_LOOP
@ BRUSH_BOUNDARY_FALLOFF_LOOP_INVERT
@ BRUSH_BOUNDARY_FALLOFF_RADIUS
@ ME_VERT_PBVH_UPDATE
Object is a sort of wrapper for general info.
ePaintSymmetryFlags
void immUniformColor4f(float r, float g, float b, float a)
void immVertex3fv(uint attr_id, const float data[3])
void immBegin(GPUPrimType, uint vertex_len)
void immUniformColor3fvAlpha(const float rgb[3], float a)
void immEnd(void)
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
@ GPU_PRIM_LINES
Definition: GPU_primitive.h:36
void GPU_line_width(float width)
Definition: gpu_state.cc:173
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
SIMD_FORCE_INLINE btScalar angle(const btVector3 &v) const
Return the angle between this and another vector.
Definition: btVector3.h:356
uint pos
IconTextureDrawCall normal
#define fmodf(x, y)
#define floorf(x)
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:48
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_calloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:46
void *(* MEM_reallocN_id)(void *vmemh, size_t len, const char *str)
Definition: mallocn.c:43
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void flip_v3_v3(float out[3], const float in[3], const enum ePaintSymmetryFlags symm)
Definition: paint_utils.c:407
const float * SCULPT_vertex_co_get(SculptSession *ss, int index)
Definition: sculpt.c:134
int SCULPT_vertex_count_get(SculptSession *ss)
Definition: sculpt.c:120
void SCULPT_orig_vert_data_update(SculptOrigVertData *orig_data, PBVHVertexIter *iter)
Definition: sculpt.c:1310
void SCULPT_boundary_info_ensure(Object *object)
Definition: sculpt.c:9039
int SCULPT_active_vertex_get(SculptSession *ss)
Definition: sculpt.c:277
int SCULPT_nearest_vertex_get(Sculpt *sd, Object *ob, const float co[3], float max_distance, bool use_original)
Definition: sculpt.c:1000
void SCULPT_floodfill_init(SculptSession *ss, SculptFloodFill *flood)
Definition: sculpt.c:1085
void SCULPT_floodfill_add_initial(SculptFloodFill *flood, int index)
Definition: sculpt.c:1094
const float * SCULPT_active_vertex_co_get(SculptSession *ss)
Definition: sculpt.c:285
void SCULPT_vertex_random_access_ensure(SculptSession *ss)
Definition: sculpt.c:112
bool SCULPT_vertex_visible_get(SculptSession *ss, int index)
Definition: sculpt.c:362
float * SCULPT_brush_deform_target_vertex_co_get(SculptSession *ss, const int deform_target, PBVHVertexIter *iter)
Definition: sculpt.c:310
void SCULPT_vertex_normal_get(SculptSession *ss, int index, float no[3])
Definition: sculpt.c:172
bool SCULPT_vertex_is_boundary(const SculptSession *ss, const int index)
Definition: sculpt.c:868
void SCULPT_floodfill_free(SculptFloodFill *flood)
Definition: sculpt.c:1188
bool SCULPT_stroke_is_first_brush_step_of_symmetry_pass(StrokeCache *cache)
Definition: sculpt.c:935
char SCULPT_mesh_symmetry_xyz_get(Object *object)
Definition: sculpt.c:323
bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3], const char symm)
Definition: sculpt.c:940
void SCULPT_floodfill_execute(SculptSession *ss, SculptFloodFill *flood, bool(*func)(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata), void *userdata)
Definition: sculpt.c:1157
void SCULPT_orig_vert_data_init(SculptOrigVertData *data, Object *ob, PBVHNode *node)
Definition: sculpt.c:1300
float SCULPT_automasking_factor_get(AutomaskingCache *automasking, SculptSession *ss, int vert)
static void sculpt_boundary_falloff_factor_init(SculptSession *ss, SculptBoundary *boundary, Brush *brush, const float radius)
static void sculpt_boundary_preview_edge_add(SculptBoundary *boundary, const int v1, const int v2)
static bool boundary_initial_vertex_floodfill_cb(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
static bool boundary_floodfill_cb(SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
void SCULPT_boundary_data_free(SculptBoundary *boundary)
#define BOUNDARY_STEPS_NONE
static void sculpt_boundary_slide_data_init(SculptSession *ss, SculptBoundary *boundary)
static void do_boundary_brush_smooth_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
static int sculpt_boundary_get_closest_boundary_vertex(SculptSession *ss, const int initial_vertex, const float radius)
static void do_boundary_brush_slide_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
#define BOUNDARY_VERTEX_NONE
static void sculpt_boundary_twist_data_init(SculptSession *ss, SculptBoundary *boundary)
void SCULPT_boundary_pivot_line_preview_draw(const uint gpuattr, SculptSession *ss)
static void do_boundary_brush_bend_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
void SCULPT_do_boundary_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
static void do_boundary_brush_inflate_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
struct BoundaryFloodFillData BoundaryFloodFillData
static void sculpt_boundary_index_add(SculptBoundary *boundary, const int new_index, const float distance, GSet *included_vertices)
struct BoundaryInitialVertexFloodFillData BoundaryInitialVertexFloodFillData
static int BOUNDARY_INDICES_BLOCK_SIZE
static void do_boundary_brush_twist_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
static float sculpt_boundary_displacement_from_grab_delta_get(SculptSession *ss, SculptBoundary *boundary)
SculptBoundary * SCULPT_boundary_data_init(Object *object, Brush *brush, const int initial_vertex, const float radius)
static void sculpt_boundary_bend_data_init(SculptSession *ss, SculptBoundary *boundary)
static void do_boundary_brush_grab_task_cb_ex(void *__restrict userdata, const int n, const TaskParallelTLS *__restrict UNUSED(tls))
void SCULPT_boundary_edges_preview_draw(const uint gpuattr, SculptSession *ss, const float outline_col[3], const float outline_alpha)
static void sculpt_boundary_edit_data_init(SculptSession *ss, SculptBoundary *boundary, const int initial_vertex, const float radius)
static bool sculpt_boundary_is_vertex_in_editable_boundary(SculptSession *ss, const int initial_vertex)
static void sculpt_boundary_indices_init(SculptSession *ss, SculptBoundary *boundary, const bool init_boundary_distances, const int initial_boundary_index)
#define SCULPT_VERTEX_NEIGHBORS_ITER_BEGIN(ss, v_index, neighbor_iterator)
#define SCULPT_VERTEX_NEIGHBORS_ITER_END(neighbor_iterator)
#define SCULPT_VERTEX_DUPLICATES_AND_NEIGHBORS_ITER_BEGIN(ss, v_index, neighbor_iterator)
SculptBoundary * boundary
struct CurveMapping * curve
int boundary_falloff_type
float boundary_offset
int deform_target
int boundary_deform_type
struct SculptSession * sculpt
struct MVert * mvert
Definition: BKE_pbvh.h:372
float * co
Definition: BKE_pbvh.h:374
float * mask
Definition: BKE_pbvh.h:377
struct SculptBoundary::@52 twist
float rotation_axis[3]
Definition: BKE_paint.h:431
int vertices_capacity
Definition: BKE_paint.h:381
int initial_vertex
Definition: BKE_paint.h:398
int max_propagation_steps
Definition: BKE_paint.h:412
struct SculptBoundaryEditInfo * edit_info
Definition: BKE_paint.h:416
float pivot_position[3]
Definition: BKE_paint.h:432
float initial_vertex_position[3]
Definition: BKE_paint.h:408
float(* pivot_rotation_axis)[3]
Definition: BKE_paint.h:420
float initial_pivot_position[3]
Definition: BKE_paint.h:409
struct SculptBoundary::@50 bend
struct SculptBoundary::@51 slide
int * vertices
Definition: BKE_paint.h:380
int edges_capacity
Definition: BKE_paint.h:391
float * distance
Definition: BKE_paint.h:387
SculptBoundaryPreviewEdge * edges
Definition: BKE_paint.h:390
float(* directions)[3]
Definition: BKE_paint.h:426
float(* pivot_positions)[3]
Definition: BKE_paint.h:421
const float * co
const short * no
SculptBoundary * boundary_preview
Definition: BKE_paint.h:557
struct StrokeCache * cache
Definition: BKE_paint.h:518
struct PBVH * pbvh
Definition: BKE_paint.h:504
Paint paint
float initial_radius
float initial_location[3]
float radius_squared
int mirror_symmetry_pass
struct SculptBoundary * boundaries[PAINT_SYMM_AREAS]
float grab_delta_symmetry[3]
AutomaskingCache * automasking
ccl_device_inline int mod(int x, int m)
Definition: util_math.h:405
ccl_device_inline float distance(const float2 &a, const float2 &b)
ccl_device_inline float4 mask(const int4 &mask, const float4 &a)