Blender V4.3
sculpt.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2006 by Nicholas Bishop. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9
10#include <cmath>
11#include <cstdlib>
12#include <cstring>
13#include <iostream>
14
15#include "MEM_guardedalloc.h"
16
17#include "CLG_log.h"
18
19#include "BLI_array_utils.hh"
21#include "BLI_bit_span_ops.hh"
22#include "BLI_blenlib.h"
23#include "BLI_dial_2d.h"
25#include "BLI_ghash.h"
26#include "BLI_math_geom.h"
27#include "BLI_math_matrix.h"
28#include "BLI_math_matrix.hh"
29#include "BLI_math_rotation.h"
30#include "BLI_math_rotation.hh"
31#include "BLI_set.hh"
32#include "BLI_span.hh"
33#include "BLI_task.h"
34#include "BLI_task.hh"
35#include "BLI_utildefines.h"
36#include "BLI_vector.hh"
37
38#include "DNA_brush_types.h"
40#include "DNA_key_types.h"
41#include "DNA_node_types.h"
42#include "DNA_object_types.h"
43#include "DNA_scene_types.h"
44
45#include "BKE_attribute.hh"
46#include "BKE_brush.hh"
47#include "BKE_ccg.hh"
48#include "BKE_colortools.hh"
49#include "BKE_context.hh"
50#include "BKE_customdata.hh"
51#include "BKE_global.hh"
52#include "BKE_image.hh"
53#include "BKE_key.hh"
54#include "BKE_layer.hh"
55#include "BKE_mesh.hh"
56#include "BKE_modifier.hh"
57#include "BKE_multires.hh"
58#include "BKE_node_runtime.hh"
59#include "BKE_object.hh"
60#include "BKE_object_types.hh"
61#include "BKE_paint.hh"
62#include "BKE_pbvh_api.hh"
63#include "BKE_report.hh"
64#include "BKE_subdiv_ccg.hh"
65#include "BKE_subsurf.hh"
66#include "BLI_math_vector.hh"
67
68#include "NOD_texture.h"
69
70#include "DEG_depsgraph.hh"
71
72#include "WM_api.hh"
73#include "WM_toolsystem.hh"
74#include "WM_types.hh"
75
76#include "ED_gpencil_legacy.hh"
77#include "ED_paint.hh"
78#include "ED_screen.hh"
79#include "ED_sculpt.hh"
80#include "ED_view3d.hh"
81
82#include "paint_intern.hh"
83#include "sculpt_automask.hh"
84#include "sculpt_boundary.hh"
85#include "sculpt_cloth.hh"
86#include "sculpt_color.hh"
87#include "sculpt_dyntopo.hh"
88#include "sculpt_face_set.hh"
89#include "sculpt_filter.hh"
90#include "sculpt_hide.hh"
91#include "sculpt_intern.hh"
92#include "sculpt_islands.hh"
93#include "sculpt_pose.hh"
94#include "sculpt_undo.hh"
95
96#include "RNA_access.hh"
97#include "RNA_define.hh"
98
99#include "bmesh.hh"
100
102#include "mesh_brush_common.hh"
103#include "sculpt_automask.hh"
104
105using blender::float3;
107using blender::Set;
108using blender::Span;
109using blender::Vector;
110
111static CLG_LogRef LOG = {"ed.sculpt_paint"};
112
114
116 const Brush &brush,
117 const Scene &scene,
118 const float3 location)
119{
120 if (!BKE_brush_use_locked_size(&scene, &brush)) {
121 return paint_calc_object_space_radius(vc, location, BKE_brush_size_get(&scene, &brush));
122 }
123 else {
124 return BKE_brush_unprojected_radius_get(&scene, &brush);
125 }
126}
127
129{
130 SculptSession &ss = *ob.sculpt;
131
133 if (reports) {
134 BKE_reportf(reports, RPT_ERROR, "The active shape key of %s is locked", ob.id.name + 2);
135 }
136 return true;
137 }
138
139 return false;
140}
141
142} // namespace blender::ed::sculpt_paint
143
152
154{
155 const SculptSession &ss = *object.sculpt;
156 switch (blender::bke::object::pbvh_get(object)->type()) {
158 BLI_assert(object.type == OB_MESH);
159 return static_cast<const Mesh *>(object.data)->verts_num;
161 return BM_mesh_elem_count(ss.bm, BM_VERT);
163 return BKE_pbvh_get_grid_num_verts(object);
164 }
165
166 return 0;
167}
168
170
172{
173 const SculptSession &ss = *object.sculpt;
175 if (ss.shapekey_active) {
176 /* Always grab active shape key if the sculpt happens on shapekey. */
178 }
179 /* Otherwise use the base mesh positions. */
180 const Mesh &mesh = *static_cast<const Mesh *>(object.data);
181 return mesh.vert_positions();
182}
183
184} // namespace blender::ed::sculpt_paint
185
187{
188 const Mesh *mesh = static_cast<const Mesh *>(object.data);
189 return ePaintSymmetryFlags(mesh->symmetry);
190}
191
192/* Sculpt Face Sets and Visibility. */
193
195
196namespace face_set {
197
198int active_face_set_get(const Object &object)
199{
200 const SculptSession &ss = *object.sculpt;
201 switch (bke::object::pbvh_get(object)->type()) {
203 const Mesh &mesh = *static_cast<const Mesh *>(object.data);
204 const bke::AttributeAccessor attributes = mesh.attributes();
205 const VArray face_sets = *attributes.lookup<int>(".sculpt_face_set", bke::AttrDomain::Face);
206 if (!face_sets || !ss.active_face_index) {
208 }
209 return face_sets[*ss.active_face_index];
210 }
212 const Mesh &mesh = *static_cast<const Mesh *>(object.data);
213 const bke::AttributeAccessor attributes = mesh.attributes();
214 const VArray face_sets = *attributes.lookup<int>(".sculpt_face_set", bke::AttrDomain::Face);
215 if (!face_sets || !ss.active_grid_index) {
217 }
218 const int face_index = BKE_subdiv_ccg_grid_to_face_index(*ss.subdiv_ccg,
220 return face_sets[face_index];
221 }
224 }
226}
227
228} // namespace face_set
229
230namespace face_set {
231
232int vert_face_set_get(const GroupedSpan<int> vert_to_face_map,
233 const Span<int> face_sets,
234 const int vert)
235{
237 for (const int face : vert_to_face_map[vert]) {
238 face_set = std::max(face_sets[face], face_set);
239 }
240 return face_set;
241}
242
243int vert_face_set_get(const SubdivCCG &subdiv_ccg, const Span<int> face_sets, const int grid)
244{
245 const int face = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, grid);
246 return face_sets[face];
247}
248
249int vert_face_set_get(const int /*face_set_offset*/, const BMVert & /*vert*/)
250{
252}
253
254bool vert_has_face_set(const GroupedSpan<int> vert_to_face_map,
255 const Span<int> face_sets,
256 const int vert,
257 const int face_set)
258{
259 if (face_sets.is_empty()) {
261 }
262 const Span<int> faces = vert_to_face_map[vert];
263 return std::any_of(
264 faces.begin(), faces.end(), [&](const int face) { return face_sets[face] == face_set; });
265}
266
267bool vert_has_face_set(const SubdivCCG &subdiv_ccg,
268 const Span<int> face_sets,
269 const int grid,
270 const int face_set)
271{
272 if (face_sets.is_empty()) {
274 }
275 const int face = BKE_subdiv_ccg_grid_to_face_index(subdiv_ccg, grid);
276 return face_sets[face] == face_set;
277}
278
279bool vert_has_face_set(const int face_set_offset, const BMVert &vert, const int face_set)
280{
281 if (face_set_offset == -1) {
282 return false;
283 }
284 BMIter iter;
285 BMFace *face;
286 BM_ITER_ELEM (face, &iter, &const_cast<BMVert &>(vert), BM_FACES_OF_VERT) {
287 if (BM_ELEM_CD_GET_INT(face, face_set_offset) == face_set) {
288 return true;
289 }
290 }
291 return false;
292}
293
294bool vert_has_unique_face_set(const GroupedSpan<int> vert_to_face_map,
295 const Span<int> face_sets,
296 int vert)
297{
298 /* TODO: Move this check higher out of this function. */
299 if (face_sets.is_empty()) {
300 return true;
301 }
302 int face_set = -1;
303 for (const int face_index : vert_to_face_map[vert]) {
304 if (face_set == -1) {
305 face_set = face_sets[face_index];
306 }
307 else {
308 if (face_sets[face_index] != face_set) {
309 return false;
310 }
311 }
312 }
313 return true;
314}
315
321 const GroupedSpan<int> vert_to_face_map,
322 const Span<int> face_sets,
323 const Span<int> corner_verts,
325 int v1,
326 int v2)
327{
328 const Span<int> vert_map = vert_to_face_map[v1];
329 int p1 = -1, p2 = -1;
330 for (int i = 0; i < vert_map.size(); i++) {
331 const int face_i = vert_map[i];
332 for (const int corner : faces[face_i]) {
333 if (corner_verts[corner] == v2) {
334 if (p1 == -1) {
335 p1 = vert_map[i];
336 break;
337 }
338
339 if (p2 == -1) {
340 p2 = vert_map[i];
341 break;
342 }
343 }
344 }
345 }
346
347 if (p1 != -1 && p2 != -1) {
348 return face_sets[p1] == face_sets[p2];
349 }
350 return true;
351}
352
354 const Span<int> corner_verts,
355 const GroupedSpan<int> vert_to_face_map,
356 const Span<int> face_sets,
357 const SubdivCCG &subdiv_ccg,
358 SubdivCCGCoord coord)
359{
360 /* TODO: Move this check higher out of this function. */
361 if (face_sets.is_empty()) {
362 return true;
363 }
364 int v1, v2;
366 subdiv_ccg, coord, corner_verts, faces, v1, v2);
367 switch (adjacency) {
369 return vert_has_unique_face_set(vert_to_face_map, face_sets, v1);
372 vert_to_face_map, face_sets, corner_verts, faces, v1, v2);
374 return true;
375 }
377 return true;
378}
379
380bool vert_has_unique_face_set(const int /*face_set_offset*/, const BMVert & /*vert*/)
381{
382 /* TODO: Obviously not fully implemented yet. Needs to be implemented for Relax Face Sets brush
383 * to work. */
384 return true;
385}
386
387} // namespace face_set
388
390{
391 r_neighbors.clear();
392 BMIter liter;
393 BMLoop *l;
394 BM_ITER_ELEM (l, &liter, &vert, BM_LOOPS_OF_VERT) {
395 for (BMVert *other_vert : {l->prev->v, l->next->v}) {
396 if (other_vert != &vert) {
397 r_neighbors.append(other_vert);
398 }
399 }
400 }
401 return r_neighbors;
402}
403
405{
406 r_neighbors.clear();
407 BMIter liter;
408 BMLoop *l;
409 BM_ITER_ELEM (l, &liter, &vert, BM_LOOPS_OF_VERT) {
410 for (BMVert *other_vert : {l->prev->v, l->next->v}) {
411 if (other_vert != &vert) {
412 r_neighbors.append(other_vert);
413 }
414 }
415 }
416
417 if (BM_vert_is_boundary(&vert)) {
418 if (r_neighbors.size() == 2) {
419 /* Do not include neighbors of corner vertices. */
420 r_neighbors.clear();
421 }
422 else {
423 /* Only include other boundary vertices as neighbors of boundary vertices. */
424 r_neighbors.remove_if([&](const BMVert *vert) { return !BM_vert_is_boundary(vert); });
425 }
426 }
427
428 return r_neighbors;
429}
430
432 const Span<int> corner_verts,
433 const GroupedSpan<int> vert_to_face,
434 const Span<bool> hide_poly,
435 const int vert,
436 Vector<int> &r_neighbors)
437{
438 r_neighbors.clear();
439
440 for (const int face : vert_to_face[vert]) {
441 if (!hide_poly.is_empty() && hide_poly[face]) {
442 continue;
443 }
444 const int2 verts = bke::mesh::face_find_adjacent_verts(faces[face], corner_verts, vert);
445 r_neighbors.append_non_duplicates(verts[0]);
446 r_neighbors.append_non_duplicates(verts[1]);
447 }
448
449 return r_neighbors.as_span();
450}
451
452namespace boundary {
453
454bool vert_is_boundary(const GroupedSpan<int> vert_to_face_map,
455 const Span<bool> hide_poly,
456 const BitSpan boundary,
457 const int vert)
458{
459 if (!hide::vert_all_faces_visible_get(hide_poly, vert_to_face_map, vert)) {
460 return true;
461 }
462 return boundary[vert].test();
463}
464
466 const Span<int> corner_verts,
467 const BitSpan boundary,
468 const SubdivCCG &subdiv_ccg,
469 const SubdivCCGCoord vert)
470{
471 /* TODO: Unlike the base mesh implementation this method does NOT take into account face
472 * visibility. Either this should be noted as a intentional limitation or fixed.*/
473 int v1, v2;
475 subdiv_ccg, vert, corner_verts, faces, v1, v2);
476 switch (adjacency) {
478 return boundary[v1].test();
480 return boundary[v1].test() && boundary[v2].test();
482 return false;
483 }
485 return false;
486}
487
489{
490 /* TODO: Unlike the base mesh implementation this method does NOT take into account face
491 * visibility. Either this should be noted as a intentional limitation or fixed.*/
492 return BM_vert_is_boundary(vert);
493}
494
495} // namespace boundary
496
497} // namespace blender::ed::sculpt_paint
498
499/* Utilities */
500
502{
503 return cache.mirror_symmetry_pass == 0 && cache.radial_symmetry_pass == 0 &&
504 cache.tile_pass == 0;
505}
506
508{
509 return cache.first_time && cache.mirror_symmetry_pass == 0 && cache.radial_symmetry_pass == 0 &&
510 cache.tile_pass == 0;
511}
512
518
519bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3], const char symm)
520{
521 bool is_in_symmetry_area = true;
522 for (int i = 0; i < 3; i++) {
523 char symm_it = 1 << i;
524 if (symm & symm_it) {
525 if (pco[i] == 0.0f) {
526 if (vco[i] > 0.0f) {
527 is_in_symmetry_area = false;
528 }
529 }
530 if (vco[i] * pco[i] < 0.0f) {
531 is_in_symmetry_area = false;
532 }
533 }
534 }
535 return is_in_symmetry_area;
536}
537
539 const float normal_weight,
540 float grab_delta[3])
541{
542 /* Signed to support grabbing in (to make a hole) as well as out. */
543 const float len_signed = dot_v3v3(ss.cache->sculpt_normal_symm, grab_delta);
544
545 /* This scale effectively projects the offset so dragging follows the cursor,
546 * as the normal points towards the view, the scale increases. */
547 float len_view_scale;
548 {
549 float view_aligned_normal[3];
551 view_aligned_normal, ss.cache->sculpt_normal_symm, ss.cache->view_normal_symm);
552 len_view_scale = fabsf(dot_v3v3(view_aligned_normal, ss.cache->sculpt_normal_symm));
553 len_view_scale = (len_view_scale > FLT_EPSILON) ? 1.0f / len_view_scale : 1.0f;
554 }
555
556 mul_v3_fl(grab_delta, 1.0f - normal_weight);
558 grab_delta, ss.cache->sculpt_normal_symm, (len_signed * normal_weight) * len_view_scale);
559}
560
562
563std::optional<int> nearest_vert_calc_mesh(const bke::pbvh::Tree &pbvh,
564 const Span<float3> vert_positions,
565 const Span<bool> hide_vert,
566 const float3 &location,
567 const float max_distance,
568 const bool use_original)
569{
570 const float max_distance_sq = max_distance * max_distance;
571 IndexMaskMemory memory;
572 const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
573 pbvh, memory, [&](const bke::pbvh::Node &node) {
574 return node_in_sphere(node, location, max_distance_sq, use_original);
575 });
576 if (nodes_in_sphere.is_empty()) {
577 return std::nullopt;
578 }
579
580 struct NearestData {
581 int vert = -1;
582 float distance_sq = std::numeric_limits<float>::max();
583 };
584
586 const NearestData nearest = threading::parallel_reduce(
587 nodes_in_sphere.index_range(),
588 1,
589 NearestData(),
590 [&](const IndexRange range, NearestData nearest) {
591 nodes_in_sphere.slice(range).foreach_index([&](const int i) {
592 for (const int vert : nodes[i].verts()) {
593 if (!hide_vert.is_empty() && hide_vert[vert]) {
594 continue;
595 }
596 const float distance_sq = math::distance_squared(vert_positions[vert], location);
597 if (distance_sq < nearest.distance_sq) {
598 nearest = {vert, distance_sq};
599 }
600 }
601 });
602 return nearest;
603 },
604 [](const NearestData a, const NearestData b) {
605 return a.distance_sq < b.distance_sq ? a : b;
606 });
607 return nearest.vert;
608}
609
610std::optional<SubdivCCGCoord> nearest_vert_calc_grids(const bke::pbvh::Tree &pbvh,
611 const SubdivCCG &subdiv_ccg,
612 const float3 &location,
613 const float max_distance,
614 const bool use_original)
615{
616 const float max_distance_sq = max_distance * max_distance;
617 IndexMaskMemory memory;
618 const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
619 pbvh, memory, [&](const bke::pbvh::Node &node) {
620 return node_in_sphere(node, location, max_distance_sq, use_original);
621 });
622 if (nodes_in_sphere.is_empty()) {
623 return std::nullopt;
624 }
625
626 struct NearestData {
627 SubdivCCGCoord coord = {};
628 float distance_sq = std::numeric_limits<float>::max();
629 };
630
631 const BitGroupVector<> grid_hidden = subdiv_ccg.grid_hidden;
632 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
633 const Span<float3> positions = subdiv_ccg.positions;
634
636 const NearestData nearest = threading::parallel_reduce(
637 nodes_in_sphere.index_range(),
638 1,
639 NearestData(),
640 [&](const IndexRange range, NearestData nearest) {
641 nodes_in_sphere.slice(range).foreach_index([&](const int i) {
642 for (const int grid : nodes[i].grids()) {
643 const IndexRange grid_range = bke::ccg::grid_range(key, grid);
644 BKE_subdiv_ccg_foreach_visible_grid_vert(key, grid_hidden, grid, [&](const int i) {
645 const float distance_sq = math::distance_squared(positions[grid_range[i]], location);
646 if (distance_sq < nearest.distance_sq) {
647 SubdivCCGCoord coord{};
648 coord.grid_index = grid;
649 coord.x = i % key.grid_size;
650 coord.y = i / key.grid_size;
651 nearest = {coord, distance_sq};
652 }
653 });
654 }
655 });
656 return nearest;
657 },
658 [](const NearestData a, const NearestData b) {
659 return a.distance_sq < b.distance_sq ? a : b;
660 });
661 return nearest.coord;
662}
663
664std::optional<BMVert *> nearest_vert_calc_bmesh(const bke::pbvh::Tree &pbvh,
665 const float3 &location,
666 const float max_distance,
667 const bool use_original)
668{
669 const float max_distance_sq = max_distance * max_distance;
670 IndexMaskMemory memory;
671 const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
672 pbvh, memory, [&](const bke::pbvh::Node &node) {
673 return node_in_sphere(node, location, max_distance_sq, use_original);
674 });
675 if (nodes_in_sphere.is_empty()) {
676 return std::nullopt;
677 }
678
679 struct NearestData {
680 BMVert *vert = nullptr;
681 float distance_sq = std::numeric_limits<float>::max();
682 };
683
685 const NearestData nearest = threading::parallel_reduce(
686 nodes_in_sphere.index_range(),
687 1,
688 NearestData(),
689 [&](const IndexRange range, NearestData nearest) {
690 nodes_in_sphere.slice(range).foreach_index([&](const int i) {
691 for (BMVert *vert :
693 {
695 continue;
696 }
697 const float distance_sq = math::distance_squared(float3(vert->co), location);
698 if (distance_sq < nearest.distance_sq) {
699 nearest = {vert, distance_sq};
700 }
701 }
702 });
703 return nearest;
704 },
705 [](const NearestData a, const NearestData b) {
706 return a.distance_sq < b.distance_sq ? a : b;
707 });
708 return nearest.vert;
709}
710
711} // namespace blender::ed::sculpt_paint
712
714{
715 return i == 0 || (symm & i && (symm != 5 || i != 3) && (symm != 6 || !ELEM(i, 3, 5)));
716}
717
719 const float br_co[3],
720 float radius,
721 char symm)
722{
723 for (char i = 0; i <= symm; ++i) {
725 continue;
726 }
728 if (len_squared_v3v3(location, vertex) < radius * radius) {
729 return true;
730 }
731 }
732 return false;
733}
734
750
752
754
755/* -------------------------------------------------------------------- */
761
775
776static bool brush_uses_topology_rake(const SculptSession &ss, const Brush &brush)
777{
779 (brush.topology_rake_factor > 0.0f) && (ss.bm != nullptr);
780}
781
807
808static bool brush_needs_rake_rotation(const Brush &brush)
809{
810 return SCULPT_BRUSH_TYPE_HAS_RAKE(brush.sculpt_brush_type) && (brush.rake_factor != 0.0f);
811}
812
814
815static void rake_data_update(SculptRakeData *srd, const float co[3])
816{
817 float rake_dist = len_v3v3(srd->follow_co, co);
818 if (rake_dist > srd->follow_dist) {
819 interp_v3_v3v3(srd->follow_co, srd->follow_co, co, rake_dist - srd->follow_dist);
820 }
821}
822
823/* -------------------------------------------------------------------- */
826
827namespace dyntopo {
828
829bool stroke_is_dyntopo(const Object &object, const Brush &brush)
830{
831 const SculptSession &ss = *object.sculpt;
832 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
833 return ((pbvh.type() == bke::pbvh::Type::BMesh) &&
834
835 (!ss.cache || (!ss.cache->alt_smooth)) &&
836
837 /* Requires mesh restore, which doesn't work with
838 * dynamic-topology. */
839 !(brush.flag & BRUSH_ANCHORED) && !(brush.flag & BRUSH_DRAG_DOT) &&
840
842}
843
844} // namespace dyntopo
845
847
848/* -------------------------------------------------------------------- */
851
852namespace undo {
853
855{
856 SculptSession &ss = *object.sculpt;
857 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
858 IndexMaskMemory memory;
859 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
860
861 Array<bool> node_changed(node_mask.min_array_size(), false);
862
863 switch (pbvh.type()) {
866 Mesh &mesh = *static_cast<Mesh *>(object.data);
867 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
869 ".sculpt_mask", bke::AttrDomain::Point);
870 node_mask.foreach_index(GrainSize(1), [&](const int i) {
871 if (const std::optional<Span<float>> orig_data = orig_mask_data_lookup_mesh(object,
872 nodes[i]))
873 {
874 const Span<int> verts = nodes[i].verts();
875 scatter_data_mesh(*orig_data, verts, mask.span);
877 node_changed[i] = true;
878 }
879 });
880 mask.finish();
881 break;
882 }
885 const int offset = CustomData_get_offset_named(&ss.bm->vdata, CD_PROP_FLOAT, ".sculpt_mask");
886 if (offset != -1) {
887 node_mask.foreach_index(GrainSize(1), [&](const int i) {
889 if (const float *orig_mask = BM_log_find_original_vert_mask(ss.bm_log, vert)) {
890 BM_ELEM_CD_SET_FLOAT(vert, offset, *orig_mask);
892 node_changed[i] = true;
893 }
894 }
895 });
896 }
897 break;
898 }
901 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
902 const BitGroupVector<> grid_hidden = subdiv_ccg.grid_hidden;
903 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
904 MutableSpan<float> masks = subdiv_ccg.masks;
905 node_mask.foreach_index(GrainSize(1), [&](const int i) {
906 if (const std::optional<Span<float>> orig_data = orig_mask_data_lookup_grids(object,
907 nodes[i]))
908 {
909 int index = 0;
910 for (const int grid : nodes[i].grids()) {
911 const IndexRange grid_range = bke::ccg::grid_range(key, grid);
912 for (const int i : IndexRange(key.grid_area)) {
913 if (grid_hidden.is_empty() || !grid_hidden[grid][i]) {
914 masks[grid_range[i]] = (*orig_data)[index];
915 }
916 index++;
917 }
918 }
920 node_changed[i] = true;
921 }
922 });
923 break;
924 }
925 }
926 pbvh.tag_masks_changed(IndexMask::from_bools(node_changed, memory));
927}
928
930{
931 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
933 IndexMaskMemory memory;
934 const IndexMask node_mask = IndexMask::from_predicate(
935 nodes.index_range(), GrainSize(64), memory, [&](const int i) {
936 return orig_color_data_lookup_mesh(object, nodes[i]).has_value();
937 });
938
940 Mesh &mesh = *static_cast<Mesh *>(object.data);
941 const OffsetIndices<int> faces = mesh.faces();
942 const Span<int> corner_verts = mesh.corner_verts();
943 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
945 node_mask.foreach_index(GrainSize(1), [&](const int i) {
946 const Span<float4> orig_data = *orig_color_data_lookup_mesh(object, nodes[i]);
947 const Span<int> verts = nodes[i].verts();
948 for (const int i : verts.index_range()) {
950 corner_verts,
951 vert_to_face_map,
952 color_attribute.domain,
953 verts[i],
954 orig_data[i],
955 color_attribute.span);
956 }
957 });
958 pbvh.tag_attribute_changed(node_mask, mesh.active_color_attribute);
959 color_attribute.finish();
960}
961
963{
964 SculptSession &ss = *object.sculpt;
965 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
966 IndexMaskMemory memory;
967 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
968
969 Array<bool> node_changed(node_mask.min_array_size(), false);
970
971 switch (pbvh.type()) {
975 *static_cast<Mesh *>(object.data));
976 node_mask.foreach_index(GrainSize(1), [&](const int i) {
977 if (const std::optional<Span<int>> orig_data = orig_face_set_data_lookup_mesh(object,
978 nodes[i]))
979 {
980 scatter_data_mesh(*orig_data, nodes[i].faces(), attribute.span);
981 node_changed[i] = true;
982 }
983 });
984 attribute.finish();
985 break;
986 }
988 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
991 *static_cast<Mesh *>(object.data));
993 node_mask.foreach_index(GrainSize(1), [&](const int i) {
994 Vector<int> &tls = all_tls.local();
995 if (const std::optional<Span<int>> orig_data = orig_face_set_data_lookup_grids(object,
996 nodes[i]))
997 {
999 subdiv_ccg, nodes[i], tls);
1000 scatter_data_mesh(*orig_data, faces, attribute.span);
1001 node_changed[i] = true;
1002 }
1003 });
1004 attribute.finish();
1005 break;
1006 }
1008 break;
1009 }
1010
1011 pbvh.tag_face_sets_changed(IndexMask::from_bools(node_changed, memory));
1012}
1013
1014void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object)
1015{
1016 SculptSession &ss = *object.sculpt;
1017 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
1018 IndexMaskMemory memory;
1019
1020 switch (pbvh.type()) {
1021 case bke::pbvh::Type::Mesh: {
1023 Mesh &mesh = *static_cast<Mesh *>(object.data);
1025 MutableSpan positions_orig = mesh.vert_positions_for_write();
1026
1027 const IndexMask node_mask = IndexMask::from_predicate(
1028 nodes.index_range(), GrainSize(64), memory, [&](const int i) {
1029 return orig_position_data_lookup_mesh(object, nodes[i]).has_value();
1030 });
1031
1032 struct LocalData {
1033 Vector<float3> translations;
1034 };
1035
1036 const KeyBlock *active_key = BKE_keyblock_from_object(&object);
1037 const bool need_translations = !ss.deform_imats.is_empty() || active_key;
1038
1040 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1042 LocalData &tls = all_tls.local();
1043 const OrigPositionData orig_data = *orig_position_data_lookup_mesh(object, nodes[i]);
1044
1045 const Span<int> verts = nodes[i].verts();
1046 const Span<float3> undo_positions = orig_data.positions;
1047 if (need_translations) {
1048 tls.translations.resize(verts.size());
1050 undo_positions, verts, positions_eval, tls.translations);
1051 }
1052
1053 scatter_data_mesh(undo_positions, verts, positions_eval);
1054
1055 if (positions_eval.data() != positions_orig.data()) {
1056 /* When the evaluated positions and original mesh positions don't point to the same
1057 * array, they must both be updated. */
1058 if (ss.deform_imats.is_empty()) {
1059 scatter_data_mesh(undo_positions, verts, positions_orig);
1060 }
1061 else {
1062 /* Because brush deformation is calculated for the evaluated deformed positions,
1063 * the translations have to be transformed to the original space. */
1065 if (ELEM(active_key, nullptr, mesh.key->refkey)) {
1066 /* We only ever want to propagate changes back to the base mesh if we either have
1067 * no shape key active, or we are working on the basis shape key.
1068 * See #126199 for more information. */
1069 apply_translations(tls.translations, verts, positions_orig);
1070 }
1071 }
1072 }
1073
1074 if (active_key) {
1075 update_shape_keys(object, mesh, *active_key, verts, tls.translations, positions_orig);
1076 }
1077 });
1078 });
1079 pbvh.tag_positions_changed(node_mask);
1080 break;
1081 }
1085 return;
1086 }
1087 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
1088 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1089 for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[i])) {
1090 if (const float *orig_co = BM_log_find_original_vert_co(ss.bm_log, vert)) {
1091 copy_v3_v3(vert->co, orig_co);
1092 }
1093 }
1094 });
1095 pbvh.tag_positions_changed(node_mask);
1096 break;
1097 }
1100
1101 const IndexMask node_mask = IndexMask::from_predicate(
1102 nodes.index_range(), GrainSize(64), memory, [&](const int i) {
1103 return orig_position_data_lookup_grids(object, nodes[i]).has_value();
1104 });
1105
1106 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1107 const BitGroupVector<> grid_hidden = subdiv_ccg.grid_hidden;
1108 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
1109 MutableSpan<float3> positions = subdiv_ccg.positions;
1110 node_mask.foreach_index(GrainSize(1), [&](const int i) {
1111 const OrigPositionData orig_data = *orig_position_data_lookup_grids(object, nodes[i]);
1112 int index = 0;
1113 for (const int grid : nodes[i].grids()) {
1114 const IndexRange grid_range = bke::ccg::grid_range(key, grid);
1115 for (const int i : IndexRange(key.grid_area)) {
1116 if (grid_hidden.is_empty() || !grid_hidden[grid][i]) {
1117 positions[grid_range[i]] = orig_data.positions[index];
1118 }
1119 index++;
1120 }
1121 }
1122 });
1123 pbvh.tag_positions_changed(node_mask);
1124 break;
1125 }
1126 }
1127
1128 /* Update normals for potentially-changed positions. Theoretically this may be unnecessary if
1129 * the brush restoring to the initial state doesn't use the normals, but we have no easy way to
1130 * know that from here. */
1131 bke::pbvh::update_normals(depsgraph, object, pbvh);
1132}
1133
1134static void restore_from_undo_step(const Depsgraph &depsgraph, const Sculpt &sd, Object &object)
1135{
1136 SculptSession &ss = *object.sculpt;
1137 const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
1138
1139 switch (brush->sculpt_brush_type) {
1142 break;
1146 break;
1148 if (ss.cache->alt_smooth) {
1150 }
1151 else {
1153 }
1154 break;
1155 default:
1157 break;
1158 }
1159 /* Disable multi-threading when dynamic-topology is enabled. Otherwise,
1160 * new entries might be inserted by #undo::push_node() into the #GHash
1161 * used internally by #BM_log_original_vert_co() by a different thread. See #33787. */
1162}
1163
1164} // namespace undo
1165
1166} // namespace blender::ed::sculpt_paint
1167
1168/*** BVH Tree ***/
1169
1171{
1172 /* Expand redraw \a rect with redraw \a rect from previous step to
1173 * prevent partial-redraw issues caused by fast strokes. This is
1174 * needed here (not in sculpt_flush_update) as it was before
1175 * because redraw rectangle should be the same in both of
1176 * optimized bke::pbvh::Tree draw function and 3d view redraw, if not -- some
1177 * mesh parts could disappear from screen (sergey). */
1178 SculptSession &ss = *ob.sculpt;
1179
1180 if (!ss.cache) {
1181 return;
1182 }
1183
1185 return;
1186 }
1187
1188 BLI_rcti_union(&rect, &ss.cache->previous_r);
1189}
1190
1192 const RegionView3D &rv3d,
1193 const Object &ob,
1194 rcti &rect)
1195{
1196 using namespace blender;
1197 const bke::pbvh::Tree *pbvh = bke::object::pbvh_get(ob);
1198 if (!pbvh) {
1199 return false;
1200 }
1201
1203
1204 /* Convert 3D bounding box to screen space. */
1205 if (!paint_convert_bb_to_rect(&rect, bounds.min, bounds.max, region, rv3d, ob)) {
1206 return false;
1207 }
1208
1209 return true;
1210}
1211
1213 char falloff_shape)
1214{
1215 if (falloff_shape == PAINT_FALLOFF_SHAPE_SPHERE) {
1216 return ss.cache->sculpt_normal_symm;
1217 }
1218 BLI_assert(falloff_shape == PAINT_FALLOFF_SHAPE_TUBE);
1219 return ss.cache->view_normal_symm;
1220}
1221
1222/* ===== Sculpting =====
1223 */
1224
1226 const ePaintSymmetryFlags symm,
1227 const char axis,
1228 const float angle)
1229{
1231
1232 if (axis != 0) {
1233 float mat[3][3];
1234 axis_angle_to_mat3_single(mat, axis, angle);
1235 mul_m3_v3(mat, mirror);
1236 }
1237
1238 const float distsq = len_squared_v3v3(mirror, cache.location);
1239
1240 if (distsq <= 4.0f * (cache.radius_squared)) {
1241 return (2.0f * (cache.radius) - sqrtf(distsq)) / (2.0f * (cache.radius));
1242 }
1243 return 0.0f;
1244}
1245
1248 const ePaintSymmetryFlags symm,
1249 const char axis)
1250{
1251 float overlap = 0.0f;
1252
1253 for (int i = 1; i < sd.radial_symm[axis - 'X']; i++) {
1254 const float angle = 2.0f * M_PI * i / sd.radial_symm[axis - 'X'];
1255 overlap += calc_overlap(cache, symm, axis, angle);
1256 }
1257
1258 return overlap;
1259}
1260
1261static float calc_symmetry_feather(const Sculpt &sd,
1263{
1265 return 1.0f;
1266 }
1267 float overlap;
1268 const int symm = cache.symmetry;
1269
1270 overlap = 0.0f;
1271 for (int i = 0; i <= symm; i++) {
1272 if (!SCULPT_is_symmetry_iteration_valid(i, symm)) {
1273 continue;
1274 }
1275
1276 overlap += calc_overlap(cache, ePaintSymmetryFlags(i), 0, 0);
1277
1278 overlap += calc_radial_symmetry_feather(sd, cache, ePaintSymmetryFlags(i), 'X');
1279 overlap += calc_radial_symmetry_feather(sd, cache, ePaintSymmetryFlags(i), 'Y');
1280 overlap += calc_radial_symmetry_feather(sd, cache, ePaintSymmetryFlags(i), 'Z');
1281 }
1282 return 1.0f / overlap;
1283}
1284
1286
1287/* -------------------------------------------------------------------- */
1300
1301namespace blender::ed::sculpt_paint {
1302
1304 /* 0 = towards view, 1 = flipped */
1305 std::array<float3, 2> area_cos;
1306 std::array<int, 2> count_co;
1307
1308 std::array<float3, 2> area_nos;
1309 std::array<int, 2> count_no;
1310};
1311
1313{
1314 float test_radius = ss.cache ? ss.cache->radius : ss.cursor_radius;
1315 if (brush.ob_mode == OB_MODE_SCULPT) {
1316 test_radius *= brush.normal_radius_factor;
1317 }
1318 return test_radius;
1319}
1320
1322 const Brush &brush)
1323{
1324 float test_radius = ss.cache ? ss.cache->radius : ss.cursor_radius;
1325 if (brush.ob_mode == OB_MODE_SCULPT) {
1326 /* Layer brush produces artifacts with normal and area radius */
1327 /* Enable area radius control only on Scrape for now */
1329 brush.area_radius_factor > 0.0f)
1330 {
1331 test_radius *= brush.area_radius_factor;
1332 if (ss.cache && brush.flag2 & BRUSH_AREA_RADIUS_PRESSURE) {
1333 test_radius *= ss.cache->pressure;
1334 }
1335 }
1336 else {
1337 test_radius *= brush.normal_radius_factor;
1338 }
1339 }
1340 return test_radius;
1341}
1342
1343/* Weight the normals towards the center. */
1344static float area_normal_calc_weight(const float distance, const float radius_inv)
1345{
1346 float p = 1.0f - (distance * radius_inv);
1347 return std::clamp(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f);
1348}
1349
1350/* Weight the coordinates towards the center. */
1351static float3 area_center_calc_weighted(const float3 &test_location,
1352 const float distance,
1353 const float radius_inv,
1354 const float3 &co)
1355{
1356 /* Weight the coordinates towards the center. */
1357 float p = 1.0f - (distance * radius_inv);
1358 const float afactor = std::clamp(3.0f * p * p - 2.0f * p * p * p, 0.0f, 1.0f);
1359
1360 const float3 disp = (co - test_location) * (1.0f - afactor);
1361 return test_location + disp;
1362}
1363
1364static void accumulate_area_center(const float3 &test_location,
1365 const float3 &position,
1366 const float distance,
1367 const float radius_inv,
1368 const int flip_index,
1369 AreaNormalCenterData &anctd)
1370{
1371 anctd.area_cos[flip_index] += area_center_calc_weighted(
1372 test_location, distance, radius_inv, position);
1373 anctd.count_co[flip_index] += 1;
1374}
1375
1376static void accumulate_area_normal(const float3 &normal,
1377 const float distance,
1378 const float radius_inv,
1379 const int flip_index,
1380 AreaNormalCenterData &anctd)
1381{
1382 anctd.area_nos[flip_index] += normal * area_normal_calc_weight(distance, radius_inv);
1383 anctd.count_no[flip_index] += 1;
1384}
1385
1390
1392 const Span<float3> vert_positions,
1393 const Span<float3> vert_normals,
1394 const Span<bool> hide_vert,
1395 const Brush &brush,
1396 const bool use_area_nos,
1397 const bool use_area_cos,
1398 const bke::pbvh::MeshNode &node,
1399 SampleLocalData &tls,
1400 AreaNormalCenterData &anctd)
1401{
1402 const SculptSession &ss = *object.sculpt;
1403 const float3 &location = ss.cache ? ss.cache->location_symm : ss.cursor_location;
1404 const float3 &view_normal = ss.cache ? ss.cache->view_normal_symm : ss.cursor_view_normal;
1405 const float position_radius = area_normal_and_center_get_position_radius(ss, brush);
1406 const float position_radius_sq = position_radius * position_radius;
1407 const float position_radius_inv = math::rcp(position_radius);
1408 const float normal_radius = area_normal_and_center_get_normal_radius(ss, brush);
1409 const float normal_radius_sq = normal_radius * normal_radius;
1410 const float normal_radius_inv = math::rcp(normal_radius);
1411
1412 const Span<int> verts = node.verts();
1413
1414 if (ss.cache && !ss.cache->accum) {
1415 if (const std::optional<OrigPositionData> orig_data = orig_position_data_lookup_mesh(object,
1416 node))
1417 {
1418 const Span<float3> orig_positions = orig_data->positions;
1419 const Span<float3> orig_normals = orig_data->normals;
1420
1421 tls.distances.reinitialize(verts.size());
1422 const MutableSpan<float> distances_sq = tls.distances;
1424 ss, orig_positions, eBrushFalloffShape(brush.falloff_shape), distances_sq);
1425
1426 for (const int i : verts.index_range()) {
1427 const int vert = verts[i];
1428 if (!hide_vert.is_empty() && hide_vert[vert]) {
1429 continue;
1430 }
1431 const bool normal_test_r = use_area_nos && distances_sq[i] <= normal_radius_sq;
1432 const bool area_test_r = use_area_cos && distances_sq[i] <= position_radius_sq;
1433 if (!normal_test_r && !area_test_r) {
1434 continue;
1435 }
1436 const float3 &normal = orig_normals[i];
1437 const float distance = std::sqrt(distances_sq[i]);
1438 const int flip_index = math::dot(view_normal, normal) <= 0.0f;
1439 if (area_test_r) {
1441 location, orig_positions[i], distance, position_radius_inv, flip_index, anctd);
1442 }
1443 if (normal_test_r) {
1444 accumulate_area_normal(normal, distance, normal_radius_inv, flip_index, anctd);
1445 }
1446 }
1447 return;
1448 }
1449 }
1450
1451 tls.distances.reinitialize(verts.size());
1452 const MutableSpan<float> distances_sq = tls.distances;
1454 ss, vert_positions, verts, eBrushFalloffShape(brush.falloff_shape), distances_sq);
1455
1456 for (const int i : verts.index_range()) {
1457 const int vert = verts[i];
1458 if (!hide_vert.is_empty() && hide_vert[vert]) {
1459 continue;
1460 }
1461 const bool normal_test_r = distances_sq[i] <= normal_radius_sq;
1462 const bool area_test_r = distances_sq[i] <= position_radius_sq;
1463 if (!normal_test_r && !area_test_r) {
1464 continue;
1465 }
1466 const float3 &normal = vert_normals[vert];
1467 const float distance = std::sqrt(distances_sq[i]);
1468 const int flip_index = math::dot(view_normal, normal) <= 0.0f;
1469 if (area_test_r) {
1471 location, vert_positions[vert], distance, position_radius_inv, flip_index, anctd);
1472 }
1473 if (normal_test_r) {
1474 accumulate_area_normal(normal, distance, normal_radius_inv, flip_index, anctd);
1475 }
1476 }
1477}
1478
1480 const Brush &brush,
1481 const bool use_area_nos,
1482 const bool use_area_cos,
1483 const bke::pbvh::GridsNode &node,
1484 SampleLocalData &tls,
1485 AreaNormalCenterData &anctd)
1486{
1487 const SculptSession &ss = *object.sculpt;
1488 const float3 &location = ss.cache ? ss.cache->location_symm : ss.cursor_location;
1489 const float3 &view_normal = ss.cache ? ss.cache->view_normal_symm : ss.cursor_view_normal;
1490 const float position_radius = area_normal_and_center_get_position_radius(ss, brush);
1491 const float position_radius_sq = position_radius * position_radius;
1492 const float position_radius_inv = math::rcp(position_radius);
1493 const float normal_radius = area_normal_and_center_get_normal_radius(ss, brush);
1494 const float normal_radius_sq = normal_radius * normal_radius;
1495 const float normal_radius_inv = math::rcp(normal_radius);
1496
1497 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
1499 const Span<float3> normals = subdiv_ccg.normals;
1500 const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
1501 const Span<int> grids = node.grids();
1502
1503 if (ss.cache && !ss.cache->accum) {
1504 if (const std::optional<OrigPositionData> orig_data = orig_position_data_lookup_grids(object,
1505 node))
1506 {
1507 const Span<float3> orig_positions = orig_data->positions;
1508 const Span<float3> orig_normals = orig_data->normals;
1509
1510 tls.distances.reinitialize(orig_positions.size());
1511 const MutableSpan<float> distances_sq = tls.distances;
1513 ss, orig_positions, eBrushFalloffShape(brush.falloff_shape), distances_sq);
1514
1515 for (const int i : grids.index_range()) {
1516 const IndexRange grid_range_node = bke::ccg::grid_range(key, i);
1517 const int grid = grids[i];
1518 for (const int offset : IndexRange(key.grid_area)) {
1519 if (!grid_hidden.is_empty() && grid_hidden[grid][offset]) {
1520 continue;
1521 }
1522 const int node_vert = grid_range_node[offset];
1523
1524 const bool normal_test_r = use_area_nos && distances_sq[node_vert] <= normal_radius_sq;
1525 const bool area_test_r = use_area_cos && distances_sq[node_vert] <= position_radius_sq;
1526 if (!normal_test_r && !area_test_r) {
1527 continue;
1528 }
1529 const float3 &normal = orig_normals[node_vert];
1530 const float distance = std::sqrt(distances_sq[node_vert]);
1531 const int flip_index = math::dot(view_normal, normal) <= 0.0f;
1532 if (area_test_r) {
1533 accumulate_area_center(location,
1534 orig_positions[node_vert],
1535 distance,
1536 position_radius_inv,
1537 flip_index,
1538 anctd);
1539 }
1540 if (normal_test_r) {
1541 accumulate_area_normal(normal, distance, normal_radius_inv, flip_index, anctd);
1542 }
1543 }
1544 }
1545 return;
1546 }
1547 }
1548
1549 const Span<float3> positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
1550 tls.distances.reinitialize(positions.size());
1551 const MutableSpan<float> distances_sq = tls.distances;
1553 ss, positions, eBrushFalloffShape(brush.falloff_shape), distances_sq);
1554
1555 for (const int i : grids.index_range()) {
1556 const IndexRange grid_range_node = bke::ccg::grid_range(key, i);
1557 const int grid = grids[i];
1558 const IndexRange grid_range = bke::ccg::grid_range(key, grid);
1559 for (const int offset : IndexRange(key.grid_area)) {
1560 if (!grid_hidden.is_empty() && grid_hidden[grid][offset]) {
1561 continue;
1562 }
1563 const int node_vert = grid_range_node[offset];
1564 const int vert = grid_range[offset];
1565
1566 const bool normal_test_r = use_area_nos && distances_sq[node_vert] <= normal_radius_sq;
1567 const bool area_test_r = use_area_cos && distances_sq[node_vert] <= position_radius_sq;
1568 if (!normal_test_r && !area_test_r) {
1569 continue;
1570 }
1571 const float3 &normal = normals[vert];
1572 const float distance = std::sqrt(distances_sq[node_vert]);
1573 const int flip_index = math::dot(view_normal, normal) <= 0.0f;
1574 if (area_test_r) {
1576 location, positions[node_vert], distance, position_radius_inv, flip_index, anctd);
1577 }
1578 if (normal_test_r) {
1579 accumulate_area_normal(normal, distance, normal_radius_inv, flip_index, anctd);
1580 }
1581 }
1582 }
1583}
1584
1586 const Brush &brush,
1587 const bool use_area_nos,
1588 const bool use_area_cos,
1589 const bool has_bm_orco,
1590 const bke::pbvh::BMeshNode &node,
1591 SampleLocalData &tls,
1592 AreaNormalCenterData &anctd)
1593{
1594 const SculptSession &ss = *object.sculpt;
1595 const float3 &location = ss.cache ? ss.cache->location_symm : ss.cursor_location;
1596 const float3 &view_normal = ss.cache ? ss.cache->view_normal_symm : ss.cursor_view_normal;
1597 const float position_radius = area_normal_and_center_get_position_radius(ss, brush);
1598 const float position_radius_sq = position_radius * position_radius;
1599 const float position_radius_inv = math::rcp(position_radius);
1600 const float normal_radius = area_normal_and_center_get_normal_radius(ss, brush);
1601 const float normal_radius_sq = normal_radius * normal_radius;
1602 const float normal_radius_inv = math::rcp(normal_radius);
1603
1604 bool use_original = false;
1605 if (ss.cache && !ss.cache->accum) {
1606 use_original = undo::get_bmesh_log_entry() != nullptr;
1607 }
1608
1609 /* When the mesh is edited we can't rely on original coords
1610 * (original mesh may not even have verts in brush radius). */
1611 if (use_original && has_bm_orco) {
1612 Span<float3> orig_positions;
1613 Span<int3> orig_tris;
1614 BKE_pbvh_node_get_bm_orco_data(node, orig_positions, orig_tris);
1615
1616 tls.positions.resize(orig_tris.size());
1617 const MutableSpan<float3> positions = tls.positions;
1618 for (const int i : orig_tris.index_range()) {
1619 const float *co_tri[3] = {
1620 orig_positions[orig_tris[i][0]],
1621 orig_positions[orig_tris[i][1]],
1622 orig_positions[orig_tris[i][2]],
1623 };
1624 closest_on_tri_to_point_v3(positions[i], location, UNPACK3(co_tri));
1625 }
1626
1627 tls.distances.reinitialize(positions.size());
1628 const MutableSpan<float> distances_sq = tls.distances;
1630 ss, positions, eBrushFalloffShape(brush.falloff_shape), distances_sq);
1631
1632 for (const int i : orig_tris.index_range()) {
1633 const bool normal_test_r = use_area_nos && distances_sq[i] <= normal_radius_sq;
1634 const bool area_test_r = use_area_cos && distances_sq[i] <= position_radius_sq;
1635 if (!normal_test_r && !area_test_r) {
1636 continue;
1637 }
1638 const float3 normal = math::normal_tri(float3(orig_positions[orig_tris[i][0]]),
1639 float3(orig_positions[orig_tris[i][1]]),
1640 float3(orig_positions[orig_tris[i][2]]));
1641
1642 const float distance = std::sqrt(distances_sq[i]);
1643 const int flip_index = math::dot(view_normal, normal) <= 0.0f;
1644 if (area_test_r) {
1646 location, positions[i], distance, position_radius_inv, flip_index, anctd);
1647 }
1648 if (normal_test_r) {
1649 accumulate_area_normal(normal, distance, normal_radius_inv, flip_index, anctd);
1650 }
1651 }
1652 return;
1653 }
1654
1656 &const_cast<bke::pbvh::BMeshNode &>(node));
1657 if (use_original) {
1658 tls.positions.resize(verts.size());
1659 const MutableSpan<float3> positions = tls.positions;
1660 Array<float3> normals(verts.size());
1662
1663 tls.distances.reinitialize(positions.size());
1664 const MutableSpan<float> distances_sq = tls.distances;
1666 ss, positions, eBrushFalloffShape(brush.falloff_shape), distances_sq);
1667
1668 int i = 0;
1669 for (BMVert *vert : verts) {
1670 if (BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
1671 i++;
1672 continue;
1673 }
1674 const bool normal_test_r = use_area_nos && distances_sq[i] <= normal_radius_sq;
1675 const bool area_test_r = use_area_cos && distances_sq[i] <= position_radius_sq;
1676 if (!normal_test_r && !area_test_r) {
1677 i++;
1678 continue;
1679 }
1680 const float3 &normal = normals[i];
1681 const float distance = std::sqrt(distances_sq[i]);
1682 const int flip_index = math::dot(view_normal, normal) <= 0.0f;
1683 if (area_test_r) {
1685 location, positions[i], distance, position_radius_inv, flip_index, anctd);
1686 }
1687 if (normal_test_r) {
1688 accumulate_area_normal(normal, distance, normal_radius_inv, flip_index, anctd);
1689 }
1690 i++;
1691 }
1692 return;
1693 }
1694
1695 const Span<float3> positions = gather_bmesh_positions(verts, tls.positions);
1696
1697 tls.distances.reinitialize(positions.size());
1698 const MutableSpan<float> distances_sq = tls.distances;
1700 ss, positions, eBrushFalloffShape(brush.falloff_shape), distances_sq);
1701
1702 int i = 0;
1703 for (BMVert *vert : verts) {
1704 if (BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
1705 i++;
1706 continue;
1707 }
1708 const bool normal_test_r = use_area_nos && distances_sq[i] <= normal_radius_sq;
1709 const bool area_test_r = use_area_cos && distances_sq[i] <= position_radius_sq;
1710 if (!normal_test_r && !area_test_r) {
1711 i++;
1712 continue;
1713 }
1714 const float3 &normal = vert->no;
1715 const float distance = std::sqrt(distances_sq[i]);
1716 const int flip_index = math::dot(view_normal, normal) <= 0.0f;
1717 if (area_test_r) {
1719 location, positions[i], distance, position_radius_inv, flip_index, anctd);
1720 }
1721 if (normal_test_r) {
1722 accumulate_area_normal(normal, distance, normal_radius_inv, flip_index, anctd);
1723 }
1724 i++;
1725 }
1726}
1727
1729 const AreaNormalCenterData &b)
1730{
1731 AreaNormalCenterData joined{};
1732
1733 joined.area_cos[0] = a.area_cos[0] + b.area_cos[0];
1734 joined.area_cos[1] = a.area_cos[1] + b.area_cos[1];
1735 joined.count_co[0] = a.count_co[0] + b.count_co[0];
1736 joined.count_co[1] = a.count_co[1] + b.count_co[1];
1737
1738 joined.area_nos[0] = a.area_nos[0] + b.area_nos[0];
1739 joined.area_nos[1] = a.area_nos[1] + b.area_nos[1];
1740 joined.count_no[0] = a.count_no[0] + b.count_no[0];
1741 joined.count_no[1] = a.count_no[1] + b.count_no[1];
1742
1743 return joined;
1744}
1745
1746void calc_area_center(const Depsgraph &depsgraph,
1747 const Brush &brush,
1748 const Object &ob,
1749 const IndexMask &node_mask,
1750 float r_area_co[3])
1751{
1752 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
1753 const SculptSession &ss = *ob.sculpt;
1754 int n;
1755
1758 switch (pbvh.type()) {
1759 case bke::pbvh::Type::Mesh: {
1760 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
1761 const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, ob);
1762 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, ob);
1763 const bke::AttributeAccessor attributes = mesh.attributes();
1764 const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
1765
1768 node_mask.index_range(),
1769 1,
1771 [&](const IndexRange range, AreaNormalCenterData anctd) {
1772 SampleLocalData &tls = all_tls.local();
1773 node_mask.slice(range).foreach_index([&](const int i) {
1774 calc_area_normal_and_center_node_mesh(ob,
1775 vert_positions,
1776 vert_normals,
1777 hide_vert,
1778 brush,
1779 false,
1780 true,
1781 nodes[i],
1782 tls,
1783 anctd);
1784 });
1785 return anctd;
1786 },
1788 break;
1789 }
1791 const bool has_bm_orco = ss.bm && dyntopo::stroke_is_dyntopo(ob, brush);
1792
1795 node_mask.index_range(),
1796 1,
1798 [&](const IndexRange range, AreaNormalCenterData anctd) {
1799 SampleLocalData &tls = all_tls.local();
1800 node_mask.slice(range).foreach_index([&](const int i) {
1801 calc_area_normal_and_center_node_bmesh(
1802 ob, brush, false, true, has_bm_orco, nodes[i], tls, anctd);
1803 });
1804 return anctd;
1805 },
1807 break;
1808 }
1812 node_mask.index_range(),
1813 1,
1815 [&](const IndexRange range, AreaNormalCenterData anctd) {
1816 SampleLocalData &tls = all_tls.local();
1817 node_mask.slice(range).foreach_index([&](const int i) {
1818 calc_area_normal_and_center_node_grids(ob, brush, false, true, nodes[i], tls, anctd);
1819 });
1820 return anctd;
1821 },
1823 break;
1824 }
1825 }
1826
1827 /* For flatten center. */
1828 for (n = 0; n < anctd.area_cos.size(); n++) {
1829 if (anctd.count_co[n] == 0) {
1830 continue;
1831 }
1832
1833 mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]);
1834 break;
1835 }
1836
1837 if (n == 2) {
1838 zero_v3(r_area_co);
1839 }
1840
1841 if (anctd.count_co[0] == 0 && anctd.count_co[1] == 0) {
1842 if (ss.cache) {
1843 copy_v3_v3(r_area_co, ss.cache->location_symm);
1844 }
1845 }
1846}
1847
1848std::optional<float3> calc_area_normal(const Depsgraph &depsgraph,
1849 const Brush &brush,
1850 const Object &ob,
1851 const IndexMask &node_mask)
1852{
1853 SculptSession &ss = *ob.sculpt;
1854 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
1855
1858 switch (pbvh.type()) {
1859 case bke::pbvh::Type::Mesh: {
1860 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
1861 const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, ob);
1862 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, ob);
1863 const bke::AttributeAccessor attributes = mesh.attributes();
1864 const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
1865
1868 node_mask.index_range(),
1869 1,
1871 [&](const IndexRange range, AreaNormalCenterData anctd) {
1872 SampleLocalData &tls = all_tls.local();
1873 node_mask.slice(range).foreach_index([&](const int i) {
1874 calc_area_normal_and_center_node_mesh(ob,
1875 vert_positions,
1876 vert_normals,
1877 hide_vert,
1878 brush,
1879 true,
1880 false,
1881 nodes[i],
1882 tls,
1883 anctd);
1884 });
1885 return anctd;
1886 },
1888 break;
1889 }
1891 const bool has_bm_orco = ss.bm && dyntopo::stroke_is_dyntopo(ob, brush);
1892
1895 node_mask.index_range(),
1896 1,
1898 [&](const IndexRange range, AreaNormalCenterData anctd) {
1899 SampleLocalData &tls = all_tls.local();
1900 node_mask.slice(range).foreach_index([&](const int i) {
1901 calc_area_normal_and_center_node_bmesh(
1902 ob,
1903 brush,
1904 true,
1905 false,
1906 has_bm_orco,
1907 static_cast<const blender::bke::pbvh::BMeshNode &>(nodes[i]),
1908 tls,
1909 anctd);
1910 });
1911 return anctd;
1912 },
1914 break;
1915 }
1919 node_mask.index_range(),
1920 1,
1922 [&](const IndexRange range, AreaNormalCenterData anctd) {
1923 SampleLocalData &tls = all_tls.local();
1924 node_mask.slice(range).foreach_index([&](const int i) {
1925 calc_area_normal_and_center_node_grids(ob, brush, true, false, nodes[i], tls, anctd);
1926 });
1927 return anctd;
1928 },
1930 break;
1931 }
1932 }
1933
1934 for (const int i : {0, 1}) {
1935 if (anctd.count_no[i] != 0) {
1936 if (!math::is_zero(anctd.area_nos[i])) {
1937 return math::normalize(anctd.area_nos[i]);
1938 }
1939 }
1940 }
1941 return std::nullopt;
1942}
1943
1945 const Brush &brush,
1946 const Object &ob,
1947 const IndexMask &node_mask,
1948 float r_area_no[3],
1949 float r_area_co[3])
1950{
1951 SculptSession &ss = *ob.sculpt;
1952 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
1953 int n;
1954
1957 switch (pbvh.type()) {
1958 case bke::pbvh::Type::Mesh: {
1959 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
1960 const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, ob);
1961 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, ob);
1962 const bke::AttributeAccessor attributes = mesh.attributes();
1963 const VArraySpan hide_vert = *attributes.lookup<bool>(".hide_vert", bke::AttrDomain::Point);
1964
1967 node_mask.index_range(),
1968 1,
1970 [&](const IndexRange range, AreaNormalCenterData anctd) {
1971 SampleLocalData &tls = all_tls.local();
1972 node_mask.slice(range).foreach_index([&](const int i) {
1973 calc_area_normal_and_center_node_mesh(ob,
1974 vert_positions,
1975 vert_normals,
1976 hide_vert,
1977 brush,
1978 true,
1979 true,
1980 nodes[i],
1981 tls,
1982 anctd);
1983 });
1984 return anctd;
1985 },
1987 break;
1988 }
1990 const bool has_bm_orco = ss.bm && dyntopo::stroke_is_dyntopo(ob, brush);
1991
1994 node_mask.index_range(),
1995 1,
1997 [&](const IndexRange range, AreaNormalCenterData anctd) {
1998 SampleLocalData &tls = all_tls.local();
1999 node_mask.slice(range).foreach_index([&](const int i) {
2000 calc_area_normal_and_center_node_bmesh(
2001 ob, brush, true, true, has_bm_orco, nodes[i], tls, anctd);
2002 });
2003 return anctd;
2004 },
2006 break;
2007 }
2011 node_mask.index_range(),
2012 1,
2014 [&](const IndexRange range, AreaNormalCenterData anctd) {
2015 SampleLocalData &tls = all_tls.local();
2016 node_mask.slice(range).foreach_index([&](const int i) {
2017 calc_area_normal_and_center_node_grids(ob, brush, true, true, nodes[i], tls, anctd);
2018 });
2019 return anctd;
2020 },
2022 break;
2023 }
2024 }
2025
2026 /* For flatten center. */
2027 for (n = 0; n < anctd.area_cos.size(); n++) {
2028 if (anctd.count_co[n] == 0) {
2029 continue;
2030 }
2031
2032 mul_v3_v3fl(r_area_co, anctd.area_cos[n], 1.0f / anctd.count_co[n]);
2033 break;
2034 }
2035
2036 if (n == 2) {
2037 zero_v3(r_area_co);
2038 }
2039
2040 if (anctd.count_co[0] == 0 && anctd.count_co[1] == 0) {
2041 if (ss.cache) {
2042 copy_v3_v3(r_area_co, ss.cache->location_symm);
2043 }
2044 }
2045
2046 /* For area normal. */
2047 for (n = 0; n < anctd.area_nos.size(); n++) {
2048 if (normalize_v3_v3(r_area_no, anctd.area_nos[n]) != 0.0f) {
2049 break;
2050 }
2051 }
2052}
2053
2054} // namespace blender::ed::sculpt_paint
2055
2057
2058/* -------------------------------------------------------------------- */
2061
2067static float brush_strength(const Sculpt &sd,
2069 const float feather,
2070 const UnifiedPaintSettings &ups,
2071 const PaintModeSettings & /*paint_mode_settings*/)
2072{
2073 const Scene *scene = cache.vc->scene;
2074 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
2075
2076 /* Primary strength input; square it to make lower values more sensitive. */
2077 const float root_alpha = BKE_brush_alpha_get(scene, &brush);
2078 const float alpha = root_alpha * root_alpha;
2079 const float dir = (brush.flag & BRUSH_DIR_IN) ? -1.0f : 1.0f;
2080 const float pressure = BKE_brush_use_alpha_pressure(&brush) ? cache.pressure : 1.0f;
2081 const float pen_flip = cache.pen_flip ? -1.0f : 1.0f;
2082 const float invert = cache.invert ? -1.0f : 1.0f;
2083 float overlap = ups.overlap_factor;
2084 /* Spacing is integer percentage of radius, divide by 50 to get
2085 * normalized diameter. */
2086
2087 float flip = dir * invert * pen_flip;
2088 if (brush.flag & BRUSH_INVERT_TO_SCRAPE_FILL) {
2089 flip = 1.0f;
2090 }
2091
2092 /* Pressure final value after being tweaked depending on the brush. */
2093 float final_pressure;
2094
2095 switch (brush.sculpt_brush_type) {
2097 final_pressure = pow4f(pressure);
2098 overlap = (1.0f + overlap) / 2.0f;
2099 return 0.25f * alpha * flip * final_pressure * overlap * feather;
2103 return alpha * flip * pressure * overlap * feather;
2105 return alpha * pressure * overlap * feather;
2108 /* Grab deform uses the same falloff as a regular grab brush. */
2109 return root_alpha * feather;
2110 }
2112 return root_alpha * feather * pressure * overlap;
2113 }
2114 else if (brush.cloth_deform_type == BRUSH_CLOTH_DEFORM_EXPAND) {
2115 /* Expand is more sensible to strength as it keeps expanding the cloth when sculpting over
2116 * the same vertices. */
2117 return 0.1f * alpha * flip * pressure * overlap * feather;
2118 }
2119 else {
2120 /* Multiply by 10 by default to get a larger range of strength depending on the size of the
2121 * brush and object. */
2122 return 10.0f * alpha * flip * pressure * overlap * feather;
2123 }
2125 return alpha * pressure * overlap * feather;
2127 return alpha * pressure * overlap * feather * 2.0f;
2129 final_pressure = pressure * pressure;
2130 return final_pressure * overlap * feather;
2133 return alpha * pressure * overlap * feather;
2135 /* Clay Strips needs less strength to compensate the curve. */
2136 final_pressure = powf(pressure, 1.5f);
2137 return alpha * flip * final_pressure * overlap * feather * 0.3f;
2139 final_pressure = pressure * pressure;
2140 return alpha * flip * final_pressure * overlap * feather * 1.3f;
2141
2143 overlap = (1.0f + overlap) / 2.0f;
2144 switch ((BrushMaskTool)brush.mask_tool) {
2145 case BRUSH_MASK_DRAW:
2146 return alpha * flip * pressure * overlap * feather;
2147 case BRUSH_MASK_SMOOTH:
2148 return alpha * pressure * feather;
2149 }
2150 break;
2153 return alpha * flip * pressure * overlap * feather;
2154
2156 if (flip > 0.0f) {
2157 return 0.250f * alpha * flip * pressure * overlap * feather;
2158 }
2159 else {
2160 return 0.125f * alpha * flip * pressure * overlap * feather;
2161 }
2162
2164 overlap = (1.0f + overlap) / 2.0f;
2165 return alpha * flip * pressure * overlap * feather;
2166
2170 if (flip > 0.0f) {
2171 overlap = (1.0f + overlap) / 2.0f;
2172 return alpha * flip * pressure * overlap * feather;
2173 }
2174 else {
2175 /* Reduce strength for DEEPEN, PEAKS, and CONTRAST. */
2176 return 0.5f * alpha * flip * pressure * overlap * feather;
2177 }
2178
2180 return flip * alpha * pressure * feather;
2181
2183 if (flip > 0.0f) {
2184 return alpha * flip * pressure * overlap * feather;
2185 }
2186 else {
2187 return 0.25f * alpha * flip * pressure * overlap * feather;
2188 }
2189
2191 overlap = (1.0f + overlap) / 2.0f;
2192 return alpha * pressure * overlap * feather;
2193
2195 return alpha * pressure * feather;
2196
2198 return root_alpha * feather;
2199
2201 return root_alpha * feather;
2202
2204 return alpha * pressure * feather;
2205
2209 return root_alpha * feather;
2211 /* The Dyntopo Density brush does not use a normal brush workflow to calculate the effect,
2212 * and this strength value is unused. */
2213 return 0.0f;
2214 }
2216 return 0.0f;
2217}
2218
2220 const Brush &brush,
2221 const float brush_point[3],
2222 const int thread_id,
2223 float *r_value,
2224 float r_rgba[4])
2225{
2227 const Scene *scene = cache.vc->scene;
2228 const MTex *mtex = BKE_brush_mask_texture_get(&brush, OB_MODE_SCULPT);
2229
2230 if (!mtex->tex) {
2231 *r_value = 1.0f;
2232 copy_v4_fl(r_rgba, 1.0f);
2233 return;
2234 }
2235
2236 float point[3];
2237 sub_v3_v3v3(point, brush_point, cache.plane_offset);
2238
2239 if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) {
2240 /* Get strength by feeding the vertex location directly into a texture. */
2241 *r_value = BKE_brush_sample_tex_3d(scene, &brush, mtex, point, r_rgba, 0, ss.tex_pool);
2242 }
2243 else {
2244 /* If the active area is being applied for symmetry, flip it
2245 * across the symmetry axis and rotate it back to the original
2246 * position in order to project it. This insures that the
2247 * brush texture will be oriented correctly. */
2248 if (cache.radial_symmetry_pass) {
2250 }
2252 cache.mirror_symmetry_pass);
2253
2254 /* Still no symmetry supported for other paint modes.
2255 * Sculpt does it DIY. */
2256 if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) {
2257 /* Similar to fixed mode, but projects from brush angle
2258 * rather than view direction. */
2259
2260 mul_m4_v3(cache.brush_local_mat.ptr(), symm_point);
2261
2262 float x = symm_point[0];
2263 float y = symm_point[1];
2264
2265 x *= mtex->size[0];
2266 y *= mtex->size[1];
2267
2268 x += mtex->ofs[0];
2269 y += mtex->ofs[1];
2270
2271 paint_get_tex_pixel(mtex, x, y, ss.tex_pool, thread_id, r_value, r_rgba);
2272
2273 add_v3_fl(r_rgba, brush.texture_sample_bias); // v3 -> Ignore alpha
2274 *r_value -= brush.texture_sample_bias;
2275 }
2276 else {
2278 cache.vc->region, symm_point, cache.projection_mat);
2279 const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f};
2280 *r_value = BKE_brush_sample_tex_3d(scene, &brush, mtex, point_3d, r_rgba, 0, ss.tex_pool);
2281 }
2282 }
2283}
2284
2286 const Brush &brush,
2287 float rgba[3],
2288 float r_offset[3])
2289{
2290 mul_v3_fl(rgba, ss.cache->bstrength);
2291 /* Handle brush inversion */
2292 if (ss.cache->bstrength < 0) {
2293 rgba[0] *= -1;
2294 rgba[1] *= -1;
2295 }
2296
2297 /* Apply texture size */
2298 for (int i = 0; i < 3; ++i) {
2299 rgba[i] *= blender::math::safe_divide(1.0f, pow2f(brush.mtex.size[i]));
2300 }
2301
2302 /* Transform vector to object space */
2304
2305 /* Handle symmetry */
2306 if (ss.cache->radial_symmetry_pass) {
2307 mul_m4_v3(ss.cache->symm_rot_mat.ptr(), rgba);
2308 }
2309 copy_v3_v3(r_offset,
2311}
2312
2313namespace blender::ed::sculpt_paint {
2314
2316{
2318 return true;
2319 }
2321 return true;
2322 }
2323 return false;
2324}
2325
2327 const float3 &location,
2328 const float radius_sq,
2329 const bool original)
2330{
2331 const Bounds<float3> bounds = original ? BKE_pbvh_node_get_original_BB(&node) :
2333 const float3 nearest = math::clamp(location, bounds.min, bounds.max);
2334 return math::distance_squared(location, nearest) < radius_sq;
2335}
2336
2337bool node_in_cylinder(const DistRayAABB_Precalc &ray_dist_precalc,
2338 const bke::pbvh::Node &node,
2339 const float radius_sq,
2340 const bool original)
2341{
2342 const Bounds<float3> bounds = (original) ? BKE_pbvh_node_get_original_BB(&node) :
2344
2345 float dummy_co[3], dummy_depth;
2346 const float dist_sq = dist_squared_ray_to_aabb_v3(
2347 &ray_dist_precalc, bounds.min, bounds.max, dummy_co, &dummy_depth);
2348
2349 /* TODO: Solve issues and enable distance check. */
2350 return dist_sq < radius_sq || true;
2351}
2352
2353static IndexMask pbvh_gather_cursor_update(Object &ob, bool use_original, IndexMaskMemory &memory)
2354{
2355 SculptSession &ss = *ob.sculpt;
2356 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
2357 const float3 center = ss.cache ? ss.cache->location_symm : ss.cursor_location;
2358 return bke::pbvh::search_nodes(pbvh, memory, [&](const bke::pbvh::Node &node) {
2359 return node_in_sphere(node, center, ss.cursor_radius, use_original);
2360 });
2361}
2362
2365 Object &ob, const Brush &brush, bool use_original, float radius_scale, IndexMaskMemory &memory)
2366{
2367 SculptSession &ss = *ob.sculpt;
2368 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
2369
2370 const float3 center = ss.cache->location_symm;
2371 const float radius_sq = math::square(ss.cache->radius * radius_scale);
2372 const bool ignore_ineffective = brush.sculpt_brush_type != SCULPT_BRUSH_TYPE_MASK;
2373 switch (brush.falloff_shape) {
2375 return bke::pbvh::search_nodes(pbvh, memory, [&](const bke::pbvh::Node &node) {
2376 if (ignore_ineffective && node_fully_masked_or_hidden(node)) {
2377 return false;
2378 }
2379 return node_in_sphere(node, center, radius_sq, use_original);
2380 });
2381 }
2382
2385 center, ss.cache->view_normal_symm);
2386 return bke::pbvh::search_nodes(pbvh, memory, [&](const bke::pbvh::Node &node) {
2387 if (ignore_ineffective && node_fully_masked_or_hidden(node)) {
2388 return false;
2389 }
2390 return node_in_cylinder(ray_dist_precalc, node, radius_sq, use_original);
2391 });
2392 }
2393 }
2394
2395 return {};
2396}
2397
2399 const Brush &brush,
2400 const bool use_original,
2401 const float radius_scale,
2402 IndexMaskMemory &memory)
2403{
2404 return pbvh_gather_generic(ob, brush, use_original, radius_scale, memory);
2405}
2406
2407/* Calculate primary direction of movement for many brushes. */
2408static float3 calc_sculpt_normal(const Depsgraph &depsgraph,
2409 const Sculpt &sd,
2410 Object &ob,
2411 const IndexMask &node_mask)
2412{
2413 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
2414 const SculptSession &ss = *ob.sculpt;
2415 switch (brush.sculpt_plane) {
2417 return calc_area_normal(depsgraph, brush, ob, node_mask).value_or(float3(0));
2419 return ss.cache->view_normal;
2420 case SCULPT_DISP_DIR_X:
2421 return float3(1, 0, 0);
2422 case SCULPT_DISP_DIR_Y:
2423 return float3(0, 1, 0);
2424 case SCULPT_DISP_DIR_Z:
2425 return float3(0, 0, 1);
2426 }
2428 return {};
2429}
2430
2431static void update_sculpt_normal(const Depsgraph &depsgraph,
2432 const Sculpt &sd,
2433 Object &ob,
2434 const IndexMask &node_mask)
2435{
2436 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
2437 StrokeCache &cache = *ob.sculpt->cache;
2438 /* Grab brush does not update the sculpt normal during a stroke. */
2439 const bool update_normal = !(brush.flag & BRUSH_ORIGINAL_NORMAL) &&
2442 !(brush.flag & BRUSH_ANCHORED)) &&
2445 cache.normal_weight > 0.0f);
2446
2447 if (cache.mirror_symmetry_pass == 0 && cache.radial_symmetry_pass == 0 &&
2449 {
2450 cache.sculpt_normal = calc_sculpt_normal(depsgraph, sd, ob, node_mask);
2454 }
2456 }
2457 else {
2460 }
2461}
2462
2464 const float center[3],
2465 const float screen_dir[2],
2466 float r_local_dir[3])
2467{
2468 Object &ob = *vc.obact;
2469 float loc[3];
2470
2471 mul_v3_m4v3(loc, ob.object_to_world().ptr(), center);
2472 const float zfac = ED_view3d_calc_zfac(vc.rv3d, loc);
2473
2474 ED_view3d_win_to_delta(vc.region, screen_dir, zfac, r_local_dir);
2475 normalize_v3(r_local_dir);
2476
2477 add_v3_v3(r_local_dir, ob.loc);
2478 mul_m4_v3(ob.world_to_object().ptr(), r_local_dir);
2479}
2480
2481static void calc_brush_local_mat(const float rotation,
2482 const Object &ob,
2483 float local_mat[4][4],
2484 float local_mat_inv[4][4])
2485{
2486 const StrokeCache *cache = ob.sculpt->cache;
2487 float tmat[4][4];
2488 float mat[4][4];
2489 float scale[4][4];
2490 float angle, v[3];
2491
2492 /* Ensure `ob.world_to_object` is up to date. */
2493 invert_m4_m4(ob.runtime->world_to_object.ptr(), ob.object_to_world().ptr());
2494
2495 /* Initialize last column of matrix. */
2496 mat[0][3] = 0.0f;
2497 mat[1][3] = 0.0f;
2498 mat[2][3] = 0.0f;
2499 mat[3][3] = 1.0f;
2500
2501 /* Read rotation (user angle, rake, etc.) to find the view's movement direction (negative X of
2502 * the brush). */
2503 angle = rotation + cache->special_rotation;
2504 /* By convention, motion direction points down the brush's Y axis, the angle represents the X
2505 * axis, normal is a 90 deg CCW rotation of the motion direction. */
2506 float motion_normal_screen[2];
2507 motion_normal_screen[0] = cosf(angle);
2508 motion_normal_screen[1] = sinf(angle);
2509 /* Convert view's brush transverse direction to object-space,
2510 * i.e. the normal of the plane described by the motion */
2511 float motion_normal_local[3];
2513 *cache->vc, cache->location_symm, motion_normal_screen, motion_normal_local);
2514
2515 /* Calculate the movement direction for the local matrix.
2516 * Note that there is a deliberate prioritization here: Our calculations are
2517 * designed such that the _motion vector_ gets projected into the tangent space;
2518 * in most cases this will be more intuitive than projecting the transverse
2519 * direction (which is orthogonal to the motion direction and therefore less
2520 * apparent to the user).
2521 * The Y-axis of the brush-local frame has to lie in the intersection of the tangent plane
2522 * and the motion plane. */
2523
2524 cross_v3_v3v3(v, cache->sculpt_normal, motion_normal_local);
2525 normalize_v3_v3(mat[1], v);
2526
2527 /* Get other axes. */
2528 cross_v3_v3v3(mat[0], mat[1], cache->sculpt_normal);
2529 copy_v3_v3(mat[2], cache->sculpt_normal);
2530
2531 /* Set location. */
2532 copy_v3_v3(mat[3], cache->location_symm);
2533
2534 /* Scale by brush radius. */
2535 float radius = cache->radius;
2536
2537 normalize_m4(mat);
2538 scale_m4_fl(scale, radius);
2539 mul_m4_m4m4(tmat, mat, scale);
2540
2541 /* Return tmat as is (for converting from local area coords to model-space coords). */
2542 copy_m4_m4(local_mat_inv, tmat);
2543 /* Return inverse (for converting from model-space coords to local area coords). */
2544 invert_m4_m4(local_mat, tmat);
2545}
2546
2547} // namespace blender::ed::sculpt_paint
2548
2549#define SCULPT_TILT_SENSITIVITY 0.7f
2550void SCULPT_tilt_apply_to_normal(float r_normal[3],
2552 const float tilt_strength)
2553{
2554 if (!U.experimental.use_sculpt_tools_tilt) {
2555 return;
2556 }
2557 const float rot_max = M_PI_2 * tilt_strength * SCULPT_TILT_SENSITIVITY;
2558 mul_v3_mat3_m4v3(r_normal, cache->vc->obact->object_to_world().ptr(), r_normal);
2559 float normal_tilt_y[3];
2560 rotate_v3_v3v3fl(normal_tilt_y, r_normal, cache->vc->rv3d->viewinv[0], cache->tilt.y * rot_max);
2561 float normal_tilt_xy[3];
2563 normal_tilt_xy, normal_tilt_y, cache->vc->rv3d->viewinv[1], cache->tilt.x * rot_max);
2564 mul_v3_mat3_m4v3(r_normal, cache->vc->obact->world_to_object().ptr(), normal_tilt_xy);
2565 normalize_v3(r_normal);
2566}
2567
2568void SCULPT_tilt_effective_normal_get(const SculptSession &ss, const Brush &brush, float r_no[3])
2569{
2572}
2573
2574static void update_brush_local_mat(const Sculpt &sd, Object &ob)
2575{
2576 using namespace blender::ed::sculpt_paint;
2577 StrokeCache *cache = ob.sculpt->cache;
2578
2579 if (cache->mirror_symmetry_pass == 0 && cache->radial_symmetry_pass == 0) {
2580 const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
2581 const MTex *mask_tex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
2583 mask_tex->rot, ob, cache->brush_local_mat.ptr(), cache->brush_local_mat_inv.ptr());
2584 }
2585}
2586
2588
2589/* -------------------------------------------------------------------- */
2592
2593static bool sculpt_needs_pbvh_pixels(PaintModeSettings &paint_mode_settings,
2594 const Brush &brush,
2595 Object &ob)
2596{
2598 U.experimental.use_sculpt_texture_paint)
2599 {
2600 Image *image;
2601 ImageUser *image_user;
2602 return SCULPT_paint_image_canvas_get(paint_mode_settings, ob, &image, &image_user);
2603 }
2604
2605 return false;
2606}
2607
2608static void sculpt_pbvh_update_pixels(const Depsgraph &depsgraph,
2609 PaintModeSettings &paint_mode_settings,
2610 Object &ob)
2611{
2612 using namespace blender;
2613 BLI_assert(ob.type == OB_MESH);
2614
2615 Image *image;
2616 ImageUser *image_user;
2617 if (!SCULPT_paint_image_canvas_get(paint_mode_settings, ob, &image, &image_user)) {
2618 return;
2619 }
2620
2621 bke::pbvh::build_pixels(depsgraph, ob, *image, *image_user);
2622}
2623
2625
2626/* -------------------------------------------------------------------- */
2629
2653
2670
2672{
2674 if (co[0] < 0.0f) {
2675 symm_area |= PAINT_SYMM_AREA_X;
2676 }
2677 if (co[1] < 0.0f) {
2678 symm_area |= PAINT_SYMM_AREA_Y;
2679 }
2680 if (co[2] < 0.0f) {
2681 symm_area |= PAINT_SYMM_AREA_Z;
2682 }
2683 return symm_area;
2684}
2685
2686static void flip_qt_qt(float out[4], const float in[4], const ePaintSymmetryFlags symm)
2687{
2688 float axis[3], angle;
2689
2690 quat_to_axis_angle(axis, &angle, in);
2691 normalize_v3(axis);
2692
2693 if (symm & PAINT_SYMM_X) {
2694 axis[0] *= -1.0f;
2695 angle *= -1.0f;
2696 }
2697 if (symm & PAINT_SYMM_Y) {
2698 axis[1] *= -1.0f;
2699 angle *= -1.0f;
2700 }
2701 if (symm & PAINT_SYMM_Z) {
2702 axis[2] *= -1.0f;
2703 angle *= -1.0f;
2704 }
2705
2707}
2708
2709static void flip_qt(float quat[4], const ePaintSymmetryFlags symm)
2710{
2711 flip_qt_qt(quat, quat, symm);
2712}
2713
2715 const ePaintSymmetryFlags symm,
2716 const ePaintSymmetryAreas symmarea,
2717 const float3 &pivot)
2718{
2720 for (int i = 0; i < 3; i++) {
2721 ePaintSymmetryFlags symm_it = ePaintSymmetryFlags(1 << i);
2722 if (!(symm & symm_it)) {
2723 continue;
2724 }
2725 if (symmarea & symm_it) {
2727 }
2728 if (pivot[i] < 0.0f) {
2730 }
2731 }
2732 return result;
2733}
2734
2736 const ePaintSymmetryFlags symm,
2737 const ePaintSymmetryAreas symmarea,
2738 const float pivot[3])
2739{
2740 for (int i = 0; i < 3; i++) {
2741 ePaintSymmetryFlags symm_it = ePaintSymmetryFlags(1 << i);
2742 if (!(symm & symm_it)) {
2743 continue;
2744 }
2745 if (symmarea & symm_it) {
2746 flip_qt(quat, symm_it);
2747 }
2748 if (pivot[i] < 0.0f) {
2749 flip_qt(quat, symm_it);
2750 }
2751 }
2752}
2753
2755{
2757 /* Elastic deformations in any brush need all nodes to avoid artifacts as the effect
2758 * of the Kelvinlet is not constrained by the radius. */
2759 return true;
2760 }
2761
2763 /* Pose needs all nodes because it applies all symmetry iterations at the same time
2764 * and the IK chain can grow to any area of the model. */
2765 /* TODO: This can be optimized by filtering the nodes after calculating the chain. */
2766 return true;
2767 }
2768
2770 /* Boundary needs all nodes because it is not possible to know where the boundary
2771 * deformation is going to be propagated before calculating it. */
2772 /* TODO: after calculating the boundary info in the first iteration, it should be
2773 * possible to get the nodes that have vertices included in any boundary deformation
2774 * and cache them. */
2775 return true;
2776 }
2777
2780 {
2781 /* Snake hook in elastic deform type has same requirements as the elastic deform brush. */
2782 return true;
2783 }
2784 return false;
2785}
2786
2787namespace blender::ed::sculpt_paint {
2788
2789void calc_brush_plane(const Depsgraph &depsgraph,
2790 const Brush &brush,
2791 Object &ob,
2792 const IndexMask &node_mask,
2793 float3 &r_area_no,
2794 float3 &r_area_co)
2795{
2796 const SculptSession &ss = *ob.sculpt;
2797
2798 zero_v3(r_area_co);
2799 zero_v3(r_area_no);
2800
2803 !(brush.flag & BRUSH_ORIGINAL_PLANE) || !(brush.flag & BRUSH_ORIGINAL_NORMAL)))
2804 {
2805 switch (brush.sculpt_plane) {
2807 copy_v3_v3(r_area_no, ss.cache->view_normal);
2808 break;
2809
2810 case SCULPT_DISP_DIR_X:
2811 ARRAY_SET_ITEMS(r_area_no, 1.0f, 0.0f, 0.0f);
2812 break;
2813
2814 case SCULPT_DISP_DIR_Y:
2815 ARRAY_SET_ITEMS(r_area_no, 0.0f, 1.0f, 0.0f);
2816 break;
2817
2818 case SCULPT_DISP_DIR_Z:
2819 ARRAY_SET_ITEMS(r_area_no, 0.0f, 0.0f, 1.0f);
2820 break;
2821
2823 calc_area_normal_and_center(depsgraph, brush, ob, node_mask, r_area_no, r_area_co);
2825 project_plane_v3_v3v3(r_area_no, r_area_no, ss.cache->view_normal_symm);
2826 normalize_v3(r_area_no);
2827 }
2828 break;
2829 }
2830
2831 /* For flatten center. */
2832 /* Flatten center has not been calculated yet if we are not using the area normal. */
2833 if (brush.sculpt_plane != SCULPT_DISP_DIR_AREA) {
2834 calc_area_center(depsgraph, brush, ob, node_mask, r_area_co);
2835 }
2836
2837 /* For area normal. */
2839 (brush.flag & BRUSH_ORIGINAL_NORMAL))
2840 {
2841 copy_v3_v3(r_area_no, ss.cache->sculpt_normal);
2842 }
2843 else {
2844 copy_v3_v3(ss.cache->sculpt_normal, r_area_no);
2845 }
2846
2847 /* For flatten center. */
2849 (brush.flag & BRUSH_ORIGINAL_PLANE))
2850 {
2851 copy_v3_v3(r_area_co, ss.cache->last_center);
2852 }
2853 else {
2854 copy_v3_v3(ss.cache->last_center, r_area_co);
2855 }
2856 }
2857 else {
2858 /* For area normal. */
2859 copy_v3_v3(r_area_no, ss.cache->sculpt_normal);
2860
2861 /* For flatten center. */
2862 copy_v3_v3(r_area_co, ss.cache->last_center);
2863
2864 /* For area normal. */
2865 r_area_no = symmetry_flip(r_area_no, ss.cache->mirror_symmetry_pass);
2866
2867 /* For flatten center. */
2868 r_area_co = symmetry_flip(r_area_co, ss.cache->mirror_symmetry_pass);
2869
2870 /* For area normal. */
2871 mul_m4_v3(ss.cache->symm_rot_mat.ptr(), r_area_no);
2872
2873 /* For flatten center. */
2874 mul_m4_v3(ss.cache->symm_rot_mat.ptr(), r_area_co);
2875
2876 /* Shift the plane for the current tile. */
2877 add_v3_v3(r_area_co, ss.cache->plane_offset);
2878 }
2879}
2880
2881} // namespace blender::ed::sculpt_paint
2882
2884{
2885 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
2886
2887 float rv = brush.plane_offset;
2888
2889 if (brush.flag & BRUSH_OFFSET_PRESSURE) {
2890 rv *= ss.cache->pressure;
2891 }
2892
2893 return rv;
2894}
2895
2897
2898/* -------------------------------------------------------------------- */
2901
2902namespace blender::ed::sculpt_paint {
2903
2904static void dynamic_topology_update(const Depsgraph &depsgraph,
2905 const Scene & /*scene*/,
2906 const Sculpt &sd,
2907 Object &ob,
2908 const Brush &brush,
2909 UnifiedPaintSettings & /*ups*/,
2910 PaintModeSettings & /*paint_mode_settings*/)
2911{
2912 SculptSession &ss = *ob.sculpt;
2914
2915 /* Build a list of all nodes that are potentially within the brush's area of influence. */
2916 const bool use_original = brush_type_needs_original(brush.sculpt_brush_type) ? true :
2917 !ss.cache->accum;
2918 const float radius_scale = 1.25f;
2919
2920 IndexMaskMemory memory;
2921 const IndexMask node_mask = pbvh_gather_generic(ob, brush, use_original, radius_scale, memory);
2922 if (node_mask.is_empty()) {
2923 return;
2924 }
2925
2927
2928 /* Free index based vertex info as it will become invalid after modifying the topology during the
2929 * stroke. */
2931
2933 float location[3];
2934
2935 if (!(sd.flags & SCULPT_DYNTOPO_DETAIL_MANUAL)) {
2937 mode |= PBVH_Subdivide;
2938 }
2939
2940 if ((sd.flags & SCULPT_DYNTOPO_COLLAPSE) ||
2942 {
2943 mode |= PBVH_Collapse;
2944 }
2945 }
2946
2949 }
2950 else {
2952 }
2953 pbvh.tag_positions_changed(node_mask);
2954 pbvh.tag_topology_changed(node_mask);
2955 node_mask.foreach_index([&](const int i) { BKE_pbvh_node_mark_topology_update(nodes[i]); });
2956 node_mask.foreach_index(GrainSize(1), [&](const int i) {
2957 BKE_pbvh_bmesh_node_save_orig(ss.bm, ss.bm_log, &nodes[i], false);
2958 });
2959
2960 float max_edge_len;
2963 }
2964 else if (sd.flags & SCULPT_DYNTOPO_DETAIL_BRUSH) {
2966 }
2967 else {
2969 sd.detail_size, ss.cache->radius, ss.cache->dyntopo_pixel_radius, U.pixelsize);
2970 }
2971 const float min_edge_len = max_edge_len * dyntopo::detail_size::EDGE_LENGTH_MIN_FACTOR;
2972
2974 pbvh,
2975 *ss.bm_log,
2976 mode,
2977 min_edge_len,
2978 max_edge_len,
2979 ss.cache->location_symm,
2981 ss.cache->radius,
2982 (brush.flag & BRUSH_FRONTFACE) != 0,
2984
2985 /* Update average stroke position. */
2986 copy_v3_v3(location, ss.cache->location);
2987 mul_m4_v3(ob.object_to_world().ptr(), location);
2988}
2989
2990static void push_undo_nodes(const Depsgraph &depsgraph,
2991 Object &ob,
2992 const Brush &brush,
2993 const IndexMask &node_mask)
2994{
2995 SculptSession &ss = *ob.sculpt;
2996 bool need_coords = ss.cache->supports_gravity;
2997
2999 /* Draw face sets in smooth mode moves the vertices. */
3000 if (ss.cache->alt_smooth) {
3001 need_coords = true;
3002 }
3003 else {
3005 }
3006 }
3007 else if (brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_MASK) {
3009 }
3012 }
3013 else {
3014 need_coords = true;
3015 }
3016
3017 if (need_coords) {
3019 }
3020}
3021
3022static void do_brush_action(const Depsgraph &depsgraph,
3023 const Scene &scene,
3024 const Sculpt &sd,
3025 Object &ob,
3026 const Brush &brush,
3028 PaintModeSettings &paint_mode_settings)
3029{
3030 SculptSession &ss = *ob.sculpt;
3032 IndexMaskMemory memory;
3033 IndexMask node_mask, texnode_mask;
3034
3035 const bool use_original = brush_type_needs_original(brush.sculpt_brush_type) ? true :
3036 !ss.cache->accum;
3037 const bool use_pixels = sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob);
3038
3039 if (sculpt_needs_pbvh_pixels(paint_mode_settings, brush, ob)) {
3040 sculpt_pbvh_update_pixels(depsgraph, paint_mode_settings, ob);
3041
3042 texnode_mask = pbvh_gather_texpaint(ob, brush, use_original, 1.0f, memory);
3043
3044 if (texnode_mask.is_empty()) {
3045 return;
3046 }
3047 }
3048
3049 /* Build a list of all nodes that are potentially within the brush's area of influence */
3050
3052 /* These brushes need to update all nodes as they are not constrained by the brush radius */
3053 node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
3054 }
3055 else if (brush.sculpt_brush_type == SCULPT_BRUSH_TYPE_CLOTH) {
3056 node_mask = cloth::brush_affected_nodes_gather(ob, brush, memory);
3057 }
3058 else {
3059 float radius_scale = 1.0f;
3060
3061 /* Corners of square brushes can go outside the brush radius. */
3063 radius_scale = M_SQRT2;
3064 }
3065
3066 /* With these options enabled not all required nodes are inside the original brush radius, so
3067 * the brush can produce artifacts in some situations. */
3069 radius_scale = 2.0f;
3070 }
3071 node_mask = pbvh_gather_generic(ob, brush, use_original, radius_scale, memory);
3072 }
3073
3074 /* Draw Face Sets in draw mode makes a single undo push, in alt-smooth mode deforms the
3075 * vertices and uses regular coords undo. */
3076 /* It also assigns the paint_face_set here as it needs to be done regardless of the stroke type
3077 * and the number of nodes under the brush influence. */
3080 {
3081 if (ss.cache->invert) {
3082 /* When inverting the brush, pick the paint face mask ID from the mesh. */
3084 }
3085 else {
3086 /* By default create a new Face Sets. */
3088 }
3089 }
3090
3091 /* For anchored brushes with spherical falloff, we start off with zero radius, thus we have no
3092 * bke::pbvh::Tree nodes on the first brush step. */
3093 if (!node_mask.is_empty() ||
3095 {
3097 /* Initialize auto-masking cache. */
3098 if (auto_mask::is_enabled(sd, ob, &brush)) {
3099 ss.cache->automasking = auto_mask::cache_init(depsgraph, sd, &brush, ob);
3100 }
3101 /* Initialize surface smooth cache. */
3104 {
3107 float3(0));
3108 }
3109 }
3110 }
3111
3112 /* Only act if some verts are inside the brush area. */
3113 if (node_mask.is_empty()) {
3114 return;
3115 }
3116 float location[3];
3117
3118 if (!use_pixels) {
3119 push_undo_nodes(depsgraph, ob, brush, node_mask);
3120 }
3121
3122 if (sculpt_brush_needs_normal(ss, sd, brush)) {
3123 update_sculpt_normal(depsgraph, sd, ob, node_mask);
3124 }
3125
3126 update_brush_local_mat(sd, ob);
3127
3130 {
3131 pose::pose_brush_init(depsgraph, ob, ss, brush);
3132 }
3133
3135 if (!ss.cache->cloth_sim) {
3137 depsgraph, ob, 1.0f, 0.0f, 0.0f, false, true);
3138 }
3141 ob,
3142 node_mask,
3143 *ss.cache->cloth_sim,
3144 ss.cache->location_symm,
3145 std::numeric_limits<float>::max());
3146 }
3147
3148 bool invert = ss.cache->pen_flip || ss.cache->invert;
3149 if (brush.flag & BRUSH_DIR_IN) {
3150 invert = !invert;
3151 }
3152
3153 /* Apply one type of brush action. */
3154 switch (brush.sculpt_brush_type) {
3156 const bool use_vector_displacement = (brush.flag2 & BRUSH_USE_COLOR_AS_DISPLACEMENT &&
3158 if (use_vector_displacement) {
3159 do_draw_vector_displacement_brush(depsgraph, sd, ob, node_mask);
3160 }
3161 else {
3162 do_draw_brush(depsgraph, sd, ob, node_mask);
3163 }
3164 break;
3165 }
3168 /* NOTE: The enhance brush needs to initialize its state on the first brush step. The
3169 * stroke strength can become 0 during the stroke, but it can not change sign (the sign is
3170 * determined in the beginning of the stroke. So here it is important to not switch to
3171 * enhance brush in the middle of the stroke. */
3172 if (ss.cache->bstrength < 0.0f) {
3173 /* Invert mode, intensify details. */
3174 do_enhance_details_brush(depsgraph, sd, ob, node_mask);
3175 }
3176 else {
3178 depsgraph, sd, ob, node_mask, std::clamp(ss.cache->bstrength, 0.0f, 1.0f));
3179 }
3180 }
3182 do_surface_smooth_brush(depsgraph, sd, ob, node_mask);
3183 }
3184 break;
3186 do_crease_brush(depsgraph, scene, sd, ob, node_mask);
3187 break;
3189 do_blob_brush(depsgraph, scene, sd, ob, node_mask);
3190 break;
3192 do_pinch_brush(depsgraph, sd, ob, node_mask);
3193 break;
3195 do_inflate_brush(depsgraph, sd, ob, node_mask);
3196 break;
3198 do_grab_brush(depsgraph, sd, ob, node_mask);
3199 break;
3201 do_rotate_brush(depsgraph, sd, ob, node_mask);
3202 break;
3204 do_snake_hook_brush(depsgraph, sd, ob, node_mask);
3205 break;
3207 do_nudge_brush(depsgraph, sd, ob, node_mask);
3208 break;
3210 do_thumb_brush(depsgraph, sd, ob, node_mask);
3211 break;
3213 do_layer_brush(depsgraph, sd, ob, node_mask);
3214 break;
3216 do_flatten_brush(depsgraph, sd, ob, node_mask);
3217 break;
3219 do_clay_brush(depsgraph, sd, ob, node_mask);
3220 break;
3222 do_clay_strips_brush(depsgraph, sd, ob, node_mask);
3223 break;
3225 do_multiplane_scrape_brush(depsgraph, sd, ob, node_mask);
3226 break;
3228 do_clay_thumb_brush(depsgraph, sd, ob, node_mask);
3229 break;
3231 if (invert && brush.flag & BRUSH_INVERT_TO_SCRAPE_FILL) {
3232 do_scrape_brush(depsgraph, sd, ob, node_mask);
3233 }
3234 else {
3235 do_fill_brush(depsgraph, sd, ob, node_mask);
3236 }
3237 break;
3239 if (invert && brush.flag & BRUSH_INVERT_TO_SCRAPE_FILL) {
3240 do_fill_brush(depsgraph, sd, ob, node_mask);
3241 }
3242 else {
3243 do_scrape_brush(depsgraph, sd, ob, node_mask);
3244 }
3245 break;
3247 switch ((BrushMaskTool)brush.mask_tool) {
3248 case BRUSH_MASK_DRAW:
3249 do_mask_brush(depsgraph, sd, ob, node_mask);
3250 break;
3251 case BRUSH_MASK_SMOOTH:
3252 do_smooth_mask_brush(depsgraph, sd, ob, node_mask, ss.cache->bstrength);
3253 break;
3254 }
3255 break;
3257 pose::do_pose_brush(depsgraph, sd, ob, node_mask);
3258 break;
3260 do_draw_sharp_brush(depsgraph, sd, ob, node_mask);
3261 break;
3263 do_elastic_deform_brush(depsgraph, sd, ob, node_mask);
3264 break;
3266 if (ss.cache->alt_smooth) {
3267 do_topology_relax_brush(depsgraph, sd, ob, node_mask);
3268 }
3269 else {
3270 do_topology_slide_brush(depsgraph, sd, ob, node_mask);
3271 }
3272 break;
3274 boundary::do_boundary_brush(depsgraph, sd, ob, node_mask);
3275 break;
3277 cloth::do_cloth_brush(depsgraph, sd, ob, node_mask);
3278 break;
3280 if (!ss.cache->alt_smooth) {
3281 do_draw_face_sets_brush(depsgraph, sd, ob, node_mask);
3282 }
3283 else {
3284 do_relax_face_sets_brush(depsgraph, sd, ob, node_mask);
3285 }
3286 break;
3288 do_displacement_eraser_brush(depsgraph, sd, ob, node_mask);
3289 break;
3291 do_displacement_smear_brush(depsgraph, sd, ob, node_mask);
3292 break;
3295 scene, depsgraph, paint_mode_settings, sd, ob, node_mask, texnode_mask);
3296 break;
3298 color::do_smear_brush(depsgraph, sd, ob, node_mask);
3299 break;
3300 }
3301
3303 brush.autosmooth_factor > 0)
3304 {
3305 if (brush.flag & BRUSH_INVERSE_SMOOTH_PRESSURE) {
3307 depsgraph, sd, ob, node_mask, brush.autosmooth_factor * (1.0f - ss.cache->pressure));
3308 }
3309 else {
3310 do_smooth_brush(depsgraph, sd, ob, node_mask, brush.autosmooth_factor);
3311 }
3312 }
3313
3314 if (brush_uses_topology_rake(ss, brush)) {
3316 }
3317
3318 /* The cloth brush adds the gravity as a regular force and it is processed in the solver. */
3319 if (ss.cache->supports_gravity && !ELEM(brush.sculpt_brush_type,
3323 {
3324 do_gravity_brush(depsgraph, sd, ob, node_mask);
3325 }
3326
3329 cloth::sim_activate_nodes(ob, *ss.cache->cloth_sim, node_mask);
3330 cloth::do_simulation_step(depsgraph, sd, ob, *ss.cache->cloth_sim, node_mask);
3331 }
3332 }
3333
3334 /* Update average stroke position. */
3335 copy_v3_v3(location, ss.cache->location);
3336 mul_m4_v3(ob.object_to_world().ptr(), location);
3337
3338 add_v3_v3(ups.average_stroke_accum, location);
3340 /* Update last stroke position. */
3341 ups.last_stroke_valid = true;
3342}
3343
3344} // namespace blender::ed::sculpt_paint
3345
3347 const ePaintSymmetryFlags symm,
3348 const char axis,
3349 const float angle)
3350{
3351 using namespace blender;
3356
3359
3360 /* XXX This reduces the length of the grab delta if it approaches the line of symmetry
3361 * XXX However, a different approach appears to be needed. */
3362#if 0
3363 if (sd->paint.symmetry_flags & PAINT_SYMMETRY_FEATHER) {
3364 float frac = 1.0f / max_overlap_count(sd);
3365 float reduce = (feather - frac) / (1.0f - frac);
3366
3367 printf("feather: %f frac: %f reduce: %f\n", feather, frac, reduce);
3368
3369 if (frac < 1.0f) {
3370 mul_v3_fl(cache.grab_delta_symmetry, reduce);
3371 }
3372 }
3373#endif
3374
3377 zero_v3(cache.plane_offset);
3378
3379 /* Expects XYZ. */
3380 if (axis) {
3381 rotate_m4(cache.symm_rot_mat.ptr(), axis, angle);
3382 rotate_m4(cache.symm_rot_mat_inv.ptr(), axis, -angle);
3383 }
3384
3385 mul_m4_v3(cache.symm_rot_mat.ptr(), cache.location_symm);
3386 mul_m4_v3(cache.symm_rot_mat.ptr(), cache.grab_delta_symm);
3387
3388 if (cache.supports_gravity) {
3391 }
3392
3393 if (cache.rake_rotation) {
3394 float4 new_quat;
3395 float4 existing(cache.rake_rotation->w,
3396 cache.rake_rotation->x,
3397 cache.rake_rotation->y,
3398 cache.rake_rotation->z);
3399 flip_qt_qt(new_quat, existing, symm);
3400 cache.rake_rotation_symm = math::Quaternion(new_quat);
3401 }
3402}
3403
3404namespace blender::ed::sculpt_paint {
3405
3406using BrushActionFunc = void (*)(const Depsgraph &depsgraph,
3407 const Scene &scene,
3408 const Sculpt &sd,
3409 Object &ob,
3410 const Brush &brush,
3412 PaintModeSettings &paint_mode_settings);
3413
3414static void do_tiled(const Depsgraph &depsgraph,
3415 const Scene &scene,
3416 const Sculpt &sd,
3417 Object &ob,
3418 const Brush &brush,
3420 PaintModeSettings &paint_mode_settings,
3421 const BrushActionFunc action)
3422{
3423 SculptSession &ss = *ob.sculpt;
3424 StrokeCache *cache = ss.cache;
3425 const float radius = cache->radius;
3426 const Bounds<float3> bb = *BKE_object_boundbox_get(&ob);
3427 const float *bbMin = bb.min;
3428 const float *bbMax = bb.max;
3429 const float *step = sd.paint.tile_offset;
3430
3431 /* These are integer locations, for real location: multiply with step and add orgLoc.
3432 * So 0,0,0 is at orgLoc. */
3433 int start[3];
3434 int end[3];
3435 int cur[3];
3436
3437 /* Position of the "prototype" stroke for tiling. */
3438 float orgLoc[3];
3439 float original_initial_location[3];
3440 copy_v3_v3(orgLoc, cache->location_symm);
3441 copy_v3_v3(original_initial_location, cache->initial_location_symm);
3442
3443 for (int dim = 0; dim < 3; dim++) {
3444 if ((sd.paint.symmetry_flags & (PAINT_TILE_X << dim)) && step[dim] > 0) {
3445 start[dim] = (bbMin[dim] - orgLoc[dim] - radius) / step[dim];
3446 end[dim] = (bbMax[dim] - orgLoc[dim] + radius) / step[dim];
3447 }
3448 else {
3449 start[dim] = end[dim] = 0;
3450 }
3451 }
3452
3453 /* First do the "un-tiled" position to initialize the stroke for this location. */
3454 cache->tile_pass = 0;
3455 action(depsgraph, scene, sd, ob, brush, ups, paint_mode_settings);
3456
3457 /* Now do it for all the tiles. */
3458 copy_v3_v3_int(cur, start);
3459 for (cur[0] = start[0]; cur[0] <= end[0]; cur[0]++) {
3460 for (cur[1] = start[1]; cur[1] <= end[1]; cur[1]++) {
3461 for (cur[2] = start[2]; cur[2] <= end[2]; cur[2]++) {
3462 if (!cur[0] && !cur[1] && !cur[2]) {
3463 /* Skip tile at orgLoc, this was already handled before all others. */
3464 continue;
3465 }
3466
3467 ++cache->tile_pass;
3468
3469 for (int dim = 0; dim < 3; dim++) {
3470 cache->location_symm[dim] = cur[dim] * step[dim] + orgLoc[dim];
3471 cache->plane_offset[dim] = cur[dim] * step[dim];
3472 cache->initial_location_symm[dim] = cur[dim] * step[dim] +
3473 original_initial_location[dim];
3474 }
3475 action(depsgraph, scene, sd, ob, brush, ups, paint_mode_settings);
3476 }
3477 }
3478 }
3479}
3480
3481static void do_radial_symmetry(const Depsgraph &depsgraph,
3482 const Scene &scene,
3483 const Sculpt &sd,
3484 Object &ob,
3485 const Brush &brush,
3487 PaintModeSettings &paint_mode_settings,
3488 const BrushActionFunc action,
3489 const ePaintSymmetryFlags symm,
3490 const int axis,
3491 const float /*feather*/)
3492{
3493 SculptSession &ss = *ob.sculpt;
3494
3495 for (int i = 1; i < sd.radial_symm[axis - 'X']; i++) {
3496 const float angle = 2.0f * M_PI * i / sd.radial_symm[axis - 'X'];
3499 do_tiled(depsgraph, scene, sd, ob, brush, ups, paint_mode_settings, action);
3500 }
3501}
3502
3507static void sculpt_fix_noise_tear(const Sculpt &sd, Object &ob)
3508{
3509 SculptSession &ss = *ob.sculpt;
3510 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
3511 const MTex *mtex = BKE_brush_mask_texture_get(&brush, OB_MODE_SCULPT);
3512
3513 if (ss.multires.active && mtex->tex && mtex->tex->type == TEX_NOISE) {
3515 }
3516}
3517
3518static void do_symmetrical_brush_actions(const Depsgraph &depsgraph,
3519 const Scene &scene,
3520 const Sculpt &sd,
3521 Object &ob,
3522 const BrushActionFunc action,
3524 PaintModeSettings &paint_mode_settings)
3525{
3526 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
3527 SculptSession &ss = *ob.sculpt;
3528 StrokeCache &cache = *ss.cache;
3529 const char symm = SCULPT_mesh_symmetry_xyz_get(ob);
3530
3531 float feather = calc_symmetry_feather(sd, *ss.cache);
3532
3533 cache.bstrength = brush_strength(sd, cache, feather, ups, paint_mode_settings);
3534 cache.symmetry = symm;
3535
3536 /* `symm` is a bit combination of XYZ -
3537 * 1 is mirror X; 2 is Y; 3 is XY; 4 is Z; 5 is XZ; 6 is YZ; 7 is XYZ */
3538 for (int i = 0; i <= symm; i++) {
3539 if (!SCULPT_is_symmetry_iteration_valid(i, symm)) {
3540 continue;
3541 }
3543 cache.mirror_symmetry_pass = symm;
3544 cache.radial_symmetry_pass = 0;
3545
3546 SCULPT_cache_calc_brushdata_symm(cache, symm, 0, 0);
3547 do_tiled(depsgraph, scene, sd, ob, brush, ups, paint_mode_settings, action);
3548
3550 depsgraph, scene, sd, ob, brush, ups, paint_mode_settings, action, symm, 'X', feather);
3552 depsgraph, scene, sd, ob, brush, ups, paint_mode_settings, action, symm, 'Y', feather);
3554 depsgraph, scene, sd, ob, brush, ups, paint_mode_settings, action, symm, 'Z', feather);
3555 }
3556}
3557
3558} // namespace blender::ed::sculpt_paint
3559
3561{
3563 return ob && ob->mode & OB_MODE_SCULPT;
3564}
3565
3571
3577
3586{
3589 ScrArea *area = CTX_wm_area(C);
3590 ARegion *region = CTX_wm_region(C);
3591
3592 if (paint && ob && BKE_paint_brush(paint) &&
3593 (area && ELEM(area->spacetype, SPACE_VIEW3D, SPACE_IMAGE)) &&
3594 (region && region->regiontype == RGN_TYPE_WINDOW))
3595 {
3596 bToolRef *tref = area->runtime.tool;
3597 if (tref && tref->runtime && tref->runtime->keymap[0]) {
3598 std::array<wmOperatorType *, 7> trim_operators = {
3599 WM_operatortype_find("SCULPT_OT_trim_box_gesture", false),
3600 WM_operatortype_find("SCULPT_OT_trim_lasso_gesture", false),
3601 WM_operatortype_find("SCULPT_OT_trim_line_gesture", false),
3602 WM_operatortype_find("SCULPT_OT_trim_polyline_gesture", false),
3603 WM_operatortype_find("SCULPT_OT_mesh_filter", false),
3604 WM_operatortype_find("SCULPT_OT_cloth_filter", false),
3605 WM_operatortype_find("SCULPT_OT_color_filter", false),
3606 };
3607
3608 return std::any_of(trim_operators.begin(), trim_operators.end(), [tref](wmOperatorType *ot) {
3609 PointerRNA ptr;
3610 return WM_toolsystem_ref_properties_get_from_operator(tref, ot, &ptr);
3611 });
3612 }
3613 }
3614 return false;
3615}
3616
3622
3623static const char *sculpt_brush_type_name(const Sculpt &sd)
3624{
3625 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
3626
3627 switch (eBrushSculptType(brush.sculpt_brush_type)) {
3629 return "Draw Brush";
3631 return "Smooth Brush";
3633 return "Crease Brush";
3635 return "Blob Brush";
3637 return "Pinch Brush";
3639 return "Inflate Brush";
3641 return "Grab Brush";
3643 return "Nudge Brush";
3645 return "Thumb Brush";
3647 return "Layer Brush";
3649 return "Flatten Brush";
3651 return "Clay Brush";
3653 return "Clay Strips Brush";
3655 return "Clay Thumb Brush";
3657 return "Fill Brush";
3659 return "Scrape Brush";
3661 return "Snake Hook Brush";
3663 return "Rotate Brush";
3665 return "Mask Brush";
3667 return "Simplify Brush";
3669 return "Draw Sharp Brush";
3671 return "Elastic Deform Brush";
3673 return "Pose Brush";
3675 return "Multi-plane Scrape Brush";
3677 return "Slide/Relax Brush";
3679 return "Boundary Brush";
3681 return "Cloth Brush";
3683 return "Draw Face Sets";
3685 return "Multires Displacement Eraser";
3687 return "Multires Displacement Smear";
3689 return "Paint Brush";
3691 return "Smear Brush";
3692 }
3693
3694 return "Sculpting";
3695}
3696
3697namespace blender::ed::sculpt_paint {
3698
3703
3704} // namespace blender::ed::sculpt_paint
3705
3706enum class StrokeFlags : uint8_t {
3710};
3711
3712namespace blender::ed::sculpt_paint {
3713
3714/* Initialize mirror modifier clipping. */
3715static void sculpt_init_mirror_clipping(const Object &ob, const SculptSession &ss)
3716{
3718
3720 if (!(md->type == eModifierType_Mirror && (md->mode & eModifierMode_Realtime))) {
3721 continue;
3722 }
3724
3725 if (!(mmd->flag & MOD_MIR_CLIPPING)) {
3726 continue;
3727 }
3728 /* Check each axis for mirroring. */
3729 for (int i = 0; i < 3; i++) {
3730 if (!(mmd->flag & (MOD_MIR_AXIS_X << i))) {
3731 continue;
3732 }
3733 /* Enable sculpt clipping. */
3735
3736 /* Update the clip tolerance. */
3737 ss.cache->mirror_modifier_clip.tolerance[i] = std::max(
3739
3740 /* Store matrix for mirror object clipping. */
3741 if (mmd->mirror_ob) {
3742 const float4x4 mirror_ob_inv = math::invert(mmd->mirror_ob->object_to_world());
3744 mirror_ob_inv.ptr(),
3745 ob.object_to_world().ptr());
3746 }
3747 }
3748 }
3750}
3751
3753{
3754 Main *bmain = CTX_data_main(C);
3755 Scene *scene = CTX_data_scene(C);
3756 Brush *cur_brush = BKE_paint_brush(paint);
3757
3758 if (cur_brush->sculpt_brush_type == SCULPT_BRUSH_TYPE_MASK) {
3759 cache->saved_mask_brush_tool = cur_brush->mask_tool;
3760 cur_brush->mask_tool = BRUSH_MASK_SMOOTH;
3761 return;
3762 }
3763
3764 if (ELEM(cur_brush->sculpt_brush_type,
3769 {
3770 /* Do nothing, this brush has its own smooth mode. */
3771 return;
3772 }
3773
3774 /* Switch to the smooth brush if possible. */
3775 BKE_paint_brush_set_essentials(bmain, paint, "Smooth");
3776 Brush *smooth_brush = BKE_paint_brush(paint);
3777
3778 if (!smooth_brush) {
3779 BKE_paint_brush_set(paint, cur_brush);
3780 CLOG_WARN(&LOG, "Switching to the smooth brush not possible, corresponding brush not");
3781 cache->saved_active_brush = nullptr;
3782 return;
3783 }
3784
3785 int cur_brush_size = BKE_brush_size_get(scene, cur_brush);
3786
3787 cache->saved_active_brush = cur_brush;
3788
3789 cache->saved_smooth_size = BKE_brush_size_get(scene, smooth_brush);
3790 BKE_brush_size_set(scene, smooth_brush, cur_brush_size);
3791 BKE_curvemapping_init(smooth_brush->curve);
3792}
3793
3795{
3796 Brush &brush = *BKE_paint_brush(paint);
3797
3799 brush.mask_tool = cache->saved_mask_brush_tool;
3800 return;
3801 }
3802
3803 if (ELEM(brush.sculpt_brush_type,
3808 {
3809 /* Do nothing. */
3810 return;
3811 }
3812
3813 /* If saved_active_brush is not set, brush was not switched/affected in
3814 * smooth_brush_toggle_on(). */
3815 if (cache->saved_active_brush) {
3816 Scene *scene = CTX_data_scene(C);
3817 BKE_brush_size_set(scene, &brush, cache->saved_smooth_size);
3819 cache->saved_active_brush = nullptr;
3820 }
3821}
3822
3823/* Initialize the stroke cache invariants from operator properties. */
3825 bContext *C, Sculpt &sd, SculptSession &ss, wmOperator *op, const float mval[2])
3826{
3827 StrokeCache *cache = MEM_new<StrokeCache>(__func__);
3828 ToolSettings *tool_settings = CTX_data_tool_settings(C);
3829 UnifiedPaintSettings *ups = &tool_settings->unified_paint_settings;
3830 const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
3833 float mat[3][3];
3834 float viewDir[3] = {0.0f, 0.0f, 1.0f};
3835 float max_scale;
3836 int mode;
3837
3838 ss.cache = cache;
3839
3840 /* Set scaling adjustment. */
3841 max_scale = 0.0f;
3842 for (int i = 0; i < 3; i++) {
3843 max_scale = max_ff(max_scale, fabsf(ob.scale[i]));
3844 }
3845 cache->scale[0] = max_scale / ob.scale[0];
3846 cache->scale[1] = max_scale / ob.scale[1];
3847 cache->scale[2] = max_scale / ob.scale[2];
3848
3849 cache->plane_trim_squared = brush->plane_trim * brush->plane_trim;
3850
3851 cache->mirror_modifier_clip.flag = 0;
3852
3854
3855 /* Initial mouse location. */
3856 if (mval) {
3857 copy_v2_v2(cache->initial_mouse, mval);
3858 }
3859 else {
3860 zero_v2(cache->initial_mouse);
3861 }
3862
3865
3868
3869 mode = RNA_enum_get(op->ptr, "mode");
3870 cache->invert = mode == BRUSH_STROKE_INVERT;
3871 cache->alt_smooth = mode == BRUSH_STROKE_SMOOTH;
3872 cache->normal_weight = brush->normal_weight;
3873
3874 /* Interpret invert as following normal, for grab brushes. */
3876 if (cache->invert) {
3877 cache->invert = false;
3878 cache->normal_weight = (cache->normal_weight == 0.0f);
3879 }
3880 }
3881
3882 /* Not very nice, but with current events system implementation
3883 * we can't handle brush appearance inversion hotkey separately (sergey). */
3884 if (cache->invert) {
3885 ups->draw_inverted = true;
3886 }
3887 else {
3888 ups->draw_inverted = false;
3889 }
3890
3891 /* Alt-Smooth. */
3892 if (cache->alt_smooth) {
3893 smooth_brush_toggle_on(C, &sd.paint, cache);
3894 /* Refresh the brush pointer in case we switched brush in the toggle function. */
3895 brush = BKE_paint_brush(&sd.paint);
3896 }
3897
3898 copy_v2_v2(cache->mouse, cache->initial_mouse);
3899 copy_v2_v2(cache->mouse_event, cache->initial_mouse);
3900 copy_v2_v2(ups->tex_mouse, cache->initial_mouse);
3901
3902 /* Truly temporary data that isn't stored in properties. */
3903 cache->vc = vc;
3904 cache->brush = brush;
3905
3906 /* Cache projection matrix. */
3907 cache->projection_mat = ED_view3d_ob_project_mat_get(cache->vc->rv3d, &ob);
3908
3909 invert_m4_m4(ob.runtime->world_to_object.ptr(), ob.object_to_world().ptr());
3910 copy_m3_m4(mat, cache->vc->rv3d->viewinv);
3911 mul_m3_v3(mat, viewDir);
3912 copy_m3_m4(mat, ob.world_to_object().ptr());
3913 mul_m3_v3(mat, viewDir);
3914 normalize_v3_v3(cache->view_normal, viewDir);
3915
3916 cache->supports_gravity = (!ELEM(brush->sculpt_brush_type,
3922 (sd.gravity_factor > 0.0f));
3923 /* Get gravity vector in world space. */
3924 if (cache->supports_gravity) {
3925 if (sd.gravity_object) {
3926 Object *gravity_object = sd.gravity_object;
3927
3928 copy_v3_v3(cache->gravity_direction, gravity_object->object_to_world().ptr()[2]);
3929 }
3930 else {
3931 cache->gravity_direction[0] = cache->gravity_direction[1] = 0.0f;
3932 cache->gravity_direction[2] = 1.0f;
3933 }
3934
3935 /* Transform to sculpted object space. */
3936 mul_m3_v3(mat, cache->gravity_direction);
3938 }
3939
3940 cache->accum = true;
3941
3942 /* Make copies of the mesh vertex locations and normals for some brushes. */
3943 if (brush->flag & BRUSH_ANCHORED) {
3944 cache->accum = false;
3945 }
3946
3947 /* Draw sharp does not need the original coordinates to produce the accumulate effect, so it
3948 * should work the opposite way. */
3950 cache->accum = false;
3951 }
3952
3954 if (!(brush->flag & BRUSH_ACCUMULATE)) {
3955 cache->accum = false;
3957 cache->accum = true;
3958 }
3959 }
3960 }
3961
3962 /* Original coordinates require the sculpt undo system, which isn't used
3963 * for image brushes. It's also not necessary, just disable it. */
3964 if (brush && brush->sculpt_brush_type == SCULPT_BRUSH_TYPE_PAINT &&
3965 SCULPT_use_image_paint_brush(tool_settings->paint_mode, ob))
3966 {
3967 cache->accum = true;
3968 }
3969
3970 cache->first_time = true;
3971
3972#define PIXEL_INPUT_THRESHHOLD 5
3975 }
3976
3977#undef PIXEL_INPUT_THRESHHOLD
3978}
3979
3980static float brush_dynamic_size_get(const Brush &brush,
3981 const StrokeCache &cache,
3982 float initial_size)
3983{
3984 switch (brush.sculpt_brush_type) {
3986 return max_ff(initial_size * 0.20f, initial_size * pow3f(cache.pressure));
3988 return max_ff(initial_size * 0.30f, initial_size * powf(cache.pressure, 1.5f));
3990 float clay_stabilized_pressure = clay_thumb_get_stabilized_pressure(cache);
3991 return initial_size * clay_stabilized_pressure;
3992 }
3993 default:
3994 return initial_size * cache.pressure;
3995 }
3996}
3997
3998/* In these brushes the grab delta is calculated always from the initial stroke location, which is
3999 * generally used to create grab deformations. */
4001{
4003 return true;
4004 }
4005
4006 if (ELEM(brush.sculpt_brush_type,
4012 {
4013 return true;
4014 }
4017 {
4018 return true;
4019 }
4020 return false;
4021}
4022
4023/* In these brushes the grab delta is calculated from the previous stroke location, which is used
4024 * to calculate to orientate the brush tip and deformation towards the stroke direction. */
4038
4039static void brush_delta_update(const Depsgraph &depsgraph,
4041 const Object &ob,
4042 const Brush &brush)
4043{
4044 SculptSession &ss = *ob.sculpt;
4045 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
4046 StrokeCache *cache = ss.cache;
4047 const float mval[2] = {
4048 cache->mouse_event[0],
4049 cache->mouse_event[1],
4050 };
4051 int brush_type = brush.sculpt_brush_type;
4052
4053 if (!ELEM(brush_type,
4068 !brush_uses_topology_rake(ss, brush))
4069 {
4070 return;
4071 }
4072 float grab_location[3], imat[4][4], delta[3], loc[3];
4073
4075 if (brush_type == SCULPT_BRUSH_TYPE_GRAB && brush.flag & BRUSH_GRAB_ACTIVE_VERTEX) {
4076 if (pbvh.type() == bke::pbvh::Type::Mesh) {
4078 cache->orig_grab_location = positions[std::get<int>(ss.active_vert())];
4079 }
4080 else {
4082 }
4083 }
4084 else {
4085 copy_v3_v3(cache->orig_grab_location, cache->location);
4086 }
4087 }
4088 else if (brush_type == SCULPT_BRUSH_TYPE_SNAKE_HOOK ||
4089 (brush_type == SCULPT_BRUSH_TYPE_CLOTH &&
4091 {
4092 add_v3_v3(cache->location, cache->grab_delta);
4093 }
4094
4095 /* Compute 3d coordinate at same z from original location + mval. */
4096 mul_v3_m4v3(loc, ob.object_to_world().ptr(), cache->orig_grab_location);
4097 ED_view3d_win_to_3d(cache->vc->v3d, cache->vc->region, loc, mval, grab_location);
4098
4099 /* Compute delta to move verts by. */
4102 sub_v3_v3v3(delta, grab_location, cache->old_grab_location);
4103 invert_m4_m4(imat, ob.object_to_world().ptr());
4104 mul_mat3_m4_v3(imat, delta);
4105 add_v3_v3(cache->grab_delta, delta);
4106 }
4107 else if (need_delta_for_tip_orientation(brush)) {
4108 if (brush.flag & BRUSH_ANCHORED) {
4109 float orig[3];
4110 mul_v3_m4v3(orig, ob.object_to_world().ptr(), cache->orig_grab_location);
4111 sub_v3_v3v3(cache->grab_delta, grab_location, orig);
4112 }
4113 else {
4114 sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
4115 }
4116 invert_m4_m4(imat, ob.object_to_world().ptr());
4117 mul_mat3_m4_v3(imat, cache->grab_delta);
4118 }
4119 else {
4120 /* Use for 'Brush.topology_rake_factor'. */
4121 sub_v3_v3v3(cache->grab_delta, grab_location, cache->old_grab_location);
4122 }
4123 }
4124 else {
4125 zero_v3(cache->grab_delta);
4126 }
4127
4130 }
4131
4132 copy_v3_v3(cache->old_grab_location, grab_location);
4133
4135 /* Location stays the same for finding vertices in brush radius. */
4136 copy_v3_v3(cache->location, cache->orig_grab_location);
4137
4138 ups.draw_anchored = true;
4140 ups.anchored_size = ups.pixel_radius;
4141 }
4142
4143 /* Handle 'rake' */
4144 cache->rake_rotation = std::nullopt;
4145 cache->rake_rotation_symm = std::nullopt;
4146 invert_m4_m4(imat, ob.object_to_world().ptr());
4147 mul_mat3_m4_v3(imat, grab_location);
4148
4150 copy_v3_v3(cache->rake_data.follow_co, grab_location);
4151 }
4152
4153 if (!brush_needs_rake_rotation(brush)) {
4154 return;
4155 }
4157
4158 if (!is_zero_v3(cache->grab_delta)) {
4159 const float eps = 0.00001f;
4160
4161 float v1[3], v2[3];
4162
4163 copy_v3_v3(v1, cache->rake_data.follow_co);
4165 sub_v3_v3(v2, cache->grab_delta);
4166
4167 sub_v3_v3(v1, grab_location);
4168 sub_v3_v3(v2, grab_location);
4169
4170 if ((normalize_v3(v2) > eps) && (normalize_v3(v1) > eps) && (len_squared_v3v3(v1, v2) > eps)) {
4171 const float rake_dist_sq = len_squared_v3v3(cache->rake_data.follow_co, grab_location);
4172 const float rake_fade = (rake_dist_sq > square_f(cache->rake_data.follow_dist)) ?
4173 1.0f :
4174 sqrtf(rake_dist_sq) / cache->rake_data.follow_dist;
4175
4176 const math::AxisAngle between_vecs(v1, v2);
4177 const math::AxisAngle rotated(between_vecs.axis(),
4178 between_vecs.angle() * brush.rake_factor * rake_fade);
4179 cache->rake_rotation = math::to_quaternion(rotated);
4180 }
4181 }
4182 rake_data_update(&cache->rake_data, grab_location);
4183}
4184
4185static void cache_paint_invariants_update(StrokeCache &cache, const Brush &brush)
4186{
4187 cache.hardness = brush.hardness;
4190 1.0f - cache.pressure :
4191 cache.pressure;
4192 }
4193
4194 cache.paint_brush.flow = brush.flow;
4197 1.0f - cache.pressure :
4198 cache.pressure;
4199 }
4200
4201 cache.paint_brush.wet_mix = brush.wet_mix;
4204 1.0f - cache.pressure :
4205 cache.pressure;
4206
4207 /* This makes wet mix more sensible in higher values, which allows to create brushes that have
4208 * a wider pressure range were they only blend colors without applying too much of the brush
4209 * color. */
4210 cache.paint_brush.wet_mix = 1.0f - pow2f(1.0f - cache.paint_brush.wet_mix);
4211 }
4212
4217 1.0f - cache.pressure :
4218 cache.pressure;
4219 }
4220
4221 cache.paint_brush.density = brush.density;
4224 1.0f - cache.pressure :
4225 cache.pressure;
4226 }
4227}
4228
4229/* Initialize the stroke cache variants from operator properties. */
4231{
4232 Scene &scene = *CTX_data_scene(C);
4233 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
4235 SculptSession &ss = *ob.sculpt;
4236 StrokeCache &cache = *ss.cache;
4237 Brush &brush = *BKE_paint_brush(&sd.paint);
4238
4240 !((brush.flag & BRUSH_ANCHORED) ||
4244 {
4245 RNA_float_get_array(ptr, "location", cache.location);
4246 }
4247
4248 cache.pen_flip = RNA_boolean_get(ptr, "pen_flip");
4249 RNA_float_get_array(ptr, "mouse", cache.mouse);
4250 RNA_float_get_array(ptr, "mouse_event", cache.mouse_event);
4251
4252 /* XXX: Use pressure value from first brush step for brushes which don't support strokes (grab,
4253 * thumb). They depends on initial state and brush coord/pressure/etc.
4254 * It's more an events design issue, which doesn't split coordinate/pressure/angle changing
4255 * events. We should avoid this after events system re-design. */
4257 cache.pressure = RNA_float_get(ptr, "pressure");
4258 }
4259
4260 cache.tilt = {RNA_float_get(ptr, "x_tilt"), RNA_float_get(ptr, "y_tilt")};
4261
4262 /* Truly temporary data that isn't stored in properties. */
4264 cache.initial_radius = sculpt_calc_radius(*cache.vc, brush, scene, cache.location);
4265
4266 if (!BKE_brush_use_locked_size(&scene, &brush)) {
4267 BKE_brush_unprojected_radius_set(&scene, &brush, cache.initial_radius);
4268 }
4269 }
4270
4271 /* Clay stabilized pressure. */
4276 }
4277 else {
4279 cache.pressure;
4283 {
4285 }
4286 }
4287 }
4288
4290 {
4291 cache.radius = brush_dynamic_size_get(brush, cache, cache.initial_radius);
4293 }
4294 else {
4295 cache.radius = cache.initial_radius;
4297 }
4298
4299 cache_paint_invariants_update(cache, brush);
4300
4301 cache.radius_squared = cache.radius * cache.radius;
4302
4303 if (brush.flag & BRUSH_ANCHORED) {
4304 /* True location has been calculated as part of the stroke system already here. */
4305 if (brush.flag & BRUSH_EDGE_TO_EDGE) {
4306 RNA_float_get_array(ptr, "location", cache.location);
4307 }
4308
4309 cache.radius = paint_calc_object_space_radius(*cache.vc, cache.location, ups.pixel_radius);
4310 cache.radius_squared = cache.radius * cache.radius;
4311 }
4312
4313 brush_delta_update(depsgraph, ups, ob, brush);
4314
4316 cache.vertex_rotation = -BLI_dial_angle(cache.dial, cache.mouse) * cache.bstrength;
4317
4318 ups.draw_anchored = true;
4320 ups.anchored_size = ups.pixel_radius;
4321 }
4322
4323 cache.special_rotation = ups.brush_rotation;
4324
4325 cache.iteration_count++;
4326}
4327
4328/* Returns true if any of the smoothing modes are active (currently
4329 * one of smooth brush, autosmooth, mask smooth, or shift-key
4330 * smooth). */
4332 const Brush &brush,
4333 const Object &object,
4334 int stroke_mode)
4335{
4336 SculptSession &ss = *object.sculpt;
4337 const bke::pbvh::Tree *pbvh = bke::object::pbvh_get(object);
4338 if (pbvh && auto_mask::is_enabled(sd, object, &brush)) {
4339 return true;
4340 }
4341 return ((stroke_mode == BRUSH_STROKE_SMOOTH) || (ss.cache && ss.cache->alt_smooth) ||
4344 (brush.mask_tool == BRUSH_MASK_SMOOTH)) ||
4354}
4355
4356} // namespace blender::ed::sculpt_paint
4357
4358void SCULPT_stroke_modifiers_check(const bContext *C, Object &ob, const Brush &brush)
4359{
4360 using namespace blender::ed::sculpt_paint;
4361 SculptSession &ss = *ob.sculpt;
4363 const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
4364
4365 bool need_pmap = sculpt_needs_connectivity_info(sd, brush, ob, 0);
4367 (!BKE_sculptsession_use_pbvh_draw(&ob, rv3d) && need_pmap))
4368 {
4372 }
4373}
4374
4376{
4377 using namespace blender;
4378 using namespace blender::ed::sculpt_paint;
4379 if (BKE_pbvh_node_get_tmin(&node) >= *tmin) {
4380 return;
4381 }
4382
4384 bool use_origco = false;
4385 Span<float3> origco;
4386 if (srd.original && srd.ss->cache) {
4387 switch (pbvh.type()) {
4389 if (const std::optional<OrigPositionData> orig_data =
4391 *srd.object, static_cast<const bke::pbvh::MeshNode &>(node)))
4392 {
4393 use_origco = true;
4394 origco = orig_data->positions;
4395 }
4396 break;
4398 if (const std::optional<OrigPositionData> orig_data = orig_position_data_lookup_grids(
4399 *srd.object, static_cast<const bke::pbvh::GridsNode &>(node)))
4400 {
4401 use_origco = true;
4402 origco = orig_data->positions;
4403 }
4404 break;
4406 use_origco = true;
4407 break;
4408 }
4409 }
4410
4411 if (node.flag_ & PBVH_FullyHidden) {
4412 return;
4413 }
4414
4415 bool hit = false;
4416 switch (pbvh.type()) {
4417 case bke::pbvh::Type::Mesh: {
4418 int mesh_active_vert;
4419 hit = bke::pbvh::node_raycast_mesh(static_cast<bke::pbvh::MeshNode &>(node),
4420 origco,
4421 srd.vert_positions,
4422 srd.faces,
4423 srd.corner_verts,
4424 srd.corner_tris,
4425 srd.hide_poly,
4426 srd.ray_start,
4427 srd.ray_normal,
4428 &srd.isect_precalc,
4429 &srd.depth,
4430 mesh_active_vert,
4432 srd.face_normal);
4433 if (hit) {
4434 srd.active_vertex = mesh_active_vert;
4435 }
4436 break;
4437 }
4439 SubdivCCGCoord grids_active_vert;
4441 static_cast<bke::pbvh::GridsNode &>(node),
4442 origco,
4443 srd.ray_start,
4444 srd.ray_normal,
4445 &srd.isect_precalc,
4446 &srd.depth,
4447 grids_active_vert,
4449 srd.face_normal);
4450 if (hit) {
4451 srd.active_vertex = grids_active_vert;
4452 }
4453 break;
4454 }
4456 BMVert *bmesh_active_vert;
4457 hit = bke::pbvh::node_raycast_bmesh(static_cast<bke::pbvh::BMeshNode &>(node),
4458 srd.ray_start,
4459 srd.ray_normal,
4460 &srd.isect_precalc,
4461 &srd.depth,
4462 use_origco,
4463 &bmesh_active_vert,
4464 srd.face_normal);
4465 if (hit) {
4466 srd.active_vertex = bmesh_active_vert;
4467 }
4468 break;
4469 }
4470 }
4471
4472 if (hit) {
4473 srd.hit = true;
4474 *tmin = srd.depth;
4475 }
4476}
4477
4480 float *tmin)
4481{
4482 using namespace blender;
4483 using namespace blender::ed::sculpt_paint;
4484 if (BKE_pbvh_node_get_tmin(&node) >= *tmin) {
4485 return;
4486 }
4488 bool use_origco = false;
4489 Span<float3> origco;
4490 if (srd.original && srd.ss->cache) {
4491 switch (pbvh.type()) {
4493 if (const std::optional<OrigPositionData> orig_data =
4495 *srd.object, static_cast<const bke::pbvh::MeshNode &>(node)))
4496 {
4497 use_origco = true;
4498 origco = orig_data->positions;
4499 }
4500 break;
4502 if (const std::optional<OrigPositionData> orig_data = orig_position_data_lookup_grids(
4503 *srd.object, static_cast<const bke::pbvh::GridsNode &>(node)))
4504 {
4505 use_origco = true;
4506 origco = orig_data->positions;
4507 }
4508
4509 break;
4511 use_origco = true;
4512 break;
4513 }
4514 }
4515
4517 node,
4518 origco,
4519 use_origco,
4520 srd.vert_positions,
4521 srd.faces,
4522 srd.corner_verts,
4523 srd.corner_tris,
4524 srd.hide_poly,
4525 srd.subdiv_ccg,
4526 srd.ray_start,
4527 srd.ray_normal,
4528 &srd.depth,
4529 &srd.dist_sq_to_ray))
4530 {
4531 srd.hit = true;
4532 *tmin = srd.dist_sq_to_ray;
4533 }
4534}
4535
4537 const float mval[2],
4538 float ray_start[3],
4539 float ray_end[3],
4540 float ray_normal[3],
4541 bool original)
4542{
4543 using namespace blender;
4544 float obimat[4][4];
4545 float dist;
4546 Object &ob = *vc->obact;
4547 RegionView3D *rv3d = vc->rv3d;
4548 View3D *v3d = vc->v3d;
4549
4550 /* TODO: what if the segment is totally clipped? (return == 0). */
4552 vc->depsgraph, vc->region, vc->v3d, mval, ray_start, ray_end, true);
4553
4554 invert_m4_m4(obimat, ob.object_to_world().ptr());
4555 mul_m4_v3(obimat, ray_start);
4556 mul_m4_v3(obimat, ray_end);
4557
4558 sub_v3_v3v3(ray_normal, ray_end, ray_start);
4559 dist = normalize_v3(ray_normal);
4560
4561 /* If the ray is clipped, don't adjust its start/end. */
4562 if ((rv3d->is_persp == false) && !RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
4563 /* Get the view origin without the addition
4564 * of -ray_normal * clip_start that
4565 * ED_view3d_win_to_segment_clipped gave us.
4566 * This is necessary to avoid floating point overflow.
4567 */
4568 ED_view3d_win_to_origin(vc->region, mval, ray_start);
4569 mul_m4_v3(obimat, ray_start);
4570
4572 bke::pbvh::clip_ray_ortho(pbvh, original, ray_start, ray_end, ray_normal);
4573
4574 dist = len_v3v3(ray_start, ray_end);
4575 }
4576
4577 return dist;
4578}
4579
4582 const float mval[2],
4583 bool use_sampled_normal)
4584{
4585 using namespace blender;
4586 using namespace blender::ed::sculpt_paint;
4588 Scene *scene = CTX_data_scene(C);
4590 float ray_start[3], ray_end[3], ray_normal[3], depth, mat[3][3];
4591 float viewDir[3] = {0.0f, 0.0f, 1.0f};
4592 bool original = false;
4593
4595
4596 Object &ob = *vc.obact;
4597 SculptSession &ss = *ob.sculpt;
4598
4599 const View3D *v3d = CTX_wm_view3d(C);
4600 const Base *base = CTX_data_active_base(C);
4601
4603
4604 if (!pbvh || !vc.rv3d || !BKE_base_is_visible(v3d, base)) {
4605 zero_v3(out->location);
4606 zero_v3(out->normal);
4608 ss.clear_active_vert(false);
4609 return false;
4610 }
4611
4612 /* bke::pbvh::Tree raycast to get active vertex and face normal. */
4613 depth = SCULPT_raycast_init(&vc, mval, ray_start, ray_end, ray_normal, original);
4614 SCULPT_stroke_modifiers_check(C, ob, brush);
4615
4616 SculptRaycastData srd{};
4617 srd.original = original;
4618 srd.object = &ob;
4619 srd.ss = ob.sculpt;
4620 srd.hit = false;
4621 if (pbvh->type() == bke::pbvh::Type::Mesh) {
4622 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
4624 srd.faces = mesh.faces();
4625 srd.corner_verts = mesh.corner_verts();
4626 srd.corner_tris = mesh.corner_tris();
4627 const bke::AttributeAccessor attributes = mesh.attributes();
4628 srd.hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
4629 }
4630 else if (pbvh->type() == bke::pbvh::Type::Grids) {
4631 srd.subdiv_ccg = ss.subdiv_ccg;
4632 }
4634 srd.ray_start = ray_start;
4635 srd.ray_normal = ray_normal;
4636 srd.depth = depth;
4637
4640 *pbvh,
4641 [&](bke::pbvh::Node &node, float *tmin) { sculpt_raycast_cb(node, srd, tmin); },
4642 ray_start,
4643 ray_normal,
4644 srd.original);
4645
4646 /* Cursor is not over the mesh, return default values. */
4647 if (!srd.hit) {
4648 zero_v3(out->location);
4649 zero_v3(out->normal);
4651 ss.clear_active_vert(true);
4652 return false;
4653 }
4654
4655 /* Update the active vertex of the SculptSession. */
4658
4659 switch (pbvh->type()) {
4662 ss.active_grid_index = std::nullopt;
4663 break;
4665 ss.active_face_index = std::nullopt;
4667 break;
4669 ss.active_face_index = std::nullopt;
4670 ss.active_grid_index = std::nullopt;
4671 break;
4672 }
4673
4674 copy_v3_v3(out->location, ray_normal);
4675 mul_v3_fl(out->location, srd.depth);
4676 add_v3_v3(out->location, ray_start);
4677
4678 /* Option to return the face normal directly for performance o accuracy reasons. */
4679 if (!use_sampled_normal) {
4680 copy_v3_v3(out->normal, srd.face_normal);
4681 return srd.hit;
4682 }
4683
4684 /* Sampled normal calculation. */
4685 float radius;
4686
4687 /* Update cursor data in SculptSession. */
4688 invert_m4_m4(ob.runtime->world_to_object.ptr(), ob.object_to_world().ptr());
4689 copy_m3_m4(mat, vc.rv3d->viewinv);
4690 mul_m3_v3(mat, viewDir);
4691 copy_m3_m4(mat, ob.world_to_object().ptr());
4692 mul_m3_v3(mat, viewDir);
4696 ss.rv3d = vc.rv3d;
4697 ss.v3d = vc.v3d;
4698
4699 if (!BKE_brush_use_locked_size(scene, &brush)) {
4700 radius = paint_calc_object_space_radius(vc, out->location, BKE_brush_size_get(scene, &brush));
4701 }
4702 else {
4703 radius = BKE_brush_unprojected_radius_get(scene, &brush);
4704 }
4705 ss.cursor_radius = radius;
4706
4707 IndexMaskMemory memory;
4708 const IndexMask node_mask = pbvh_gather_cursor_update(ob, original, memory);
4709
4710 /* In case there are no nodes under the cursor, return the face normal. */
4711 if (node_mask.is_empty()) {
4712 copy_v3_v3(out->normal, srd.face_normal);
4713 return true;
4714 }
4715
4717
4718 /* Calculate the sampled normal. */
4719 if (const std::optional<float3> sampled_normal = calc_area_normal(
4720 *depsgraph, brush, ob, node_mask))
4721 {
4722 copy_v3_v3(out->normal, *sampled_normal);
4723 copy_v3_v3(ss.cursor_sampled_normal, *sampled_normal);
4724 }
4725 else {
4726 /* Use face normal when there are no vertices to sample inside the cursor radius. */
4727 copy_v3_v3(out->normal, srd.face_normal);
4728 }
4729 return true;
4730}
4731
4733 float out[3],
4734 const float mval[2],
4735 bool force_original)
4736{
4738 bool check_closest = brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE;
4739
4740 return SCULPT_stroke_get_location_ex(C, out, mval, force_original, check_closest, true);
4741}
4742
4744 float out[3],
4745 const float mval[2],
4746 bool force_original,
4747 bool check_closest,
4748 bool limit_closest_radius)
4749{
4750 using namespace blender;
4751 using namespace blender::ed::sculpt_paint;
4753 float ray_start[3], ray_end[3], ray_normal[3], depth;
4754
4756
4757 Object &ob = *vc.obact;
4758
4759 SculptSession &ss = *ob.sculpt;
4760 StrokeCache *cache = ss.cache;
4761 bool original = force_original || ((cache) ? !cache->accum : false);
4762
4764
4765 SCULPT_stroke_modifiers_check(C, ob, brush);
4766
4767 depth = SCULPT_raycast_init(&vc, mval, ray_start, ray_end, ray_normal, original);
4768
4770 if (pbvh.type() == bke::pbvh::Type::BMesh) {
4773 }
4774
4775 bool hit = false;
4776 {
4778 srd.object = &ob;
4779 srd.ss = ob.sculpt;
4780 srd.ray_start = ray_start;
4781 srd.ray_normal = ray_normal;
4782 srd.hit = false;
4783 if (pbvh.type() == bke::pbvh::Type::Mesh) {
4784 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
4786 srd.faces = mesh.faces();
4787 srd.corner_verts = mesh.corner_verts();
4788 srd.corner_tris = mesh.corner_tris();
4789 const bke::AttributeAccessor attributes = mesh.attributes();
4790 srd.hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
4791 }
4792 else if (pbvh.type() == bke::pbvh::Type::Grids) {
4793 srd.subdiv_ccg = ss.subdiv_ccg;
4794 }
4796 srd.depth = depth;
4797 srd.original = original;
4799
4801 pbvh,
4802 [&](bke::pbvh::Node &node, float *tmin) { sculpt_raycast_cb(node, srd, tmin); },
4803 ray_start,
4804 ray_normal,
4805 srd.original);
4806 if (srd.hit) {
4807 hit = true;
4808 copy_v3_v3(out, ray_normal);
4809 mul_v3_fl(out, srd.depth);
4810 add_v3_v3(out, ray_start);
4811 }
4812 }
4813
4814 if (hit || !check_closest) {
4815 return hit;
4816 }
4817
4819 srd.original = original;
4820 srd.object = &ob;
4821 srd.ss = ob.sculpt;
4822 srd.hit = false;
4823 if (pbvh.type() == bke::pbvh::Type::Mesh) {
4824 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
4826 srd.faces = mesh.faces();
4827 srd.corner_verts = mesh.corner_verts();
4828 srd.corner_tris = mesh.corner_tris();
4829 const bke::AttributeAccessor attributes = mesh.attributes();
4830 srd.hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
4831 }
4832 else if (pbvh.type() == bke::pbvh::Type::Grids) {
4833 srd.subdiv_ccg = ss.subdiv_ccg;
4834 }
4835 srd.ray_start = ray_start;
4836 srd.ray_normal = ray_normal;
4837 srd.depth = std::numeric_limits<float>::max();
4838 srd.dist_sq_to_ray = std::numeric_limits<float>::max();
4839
4841 pbvh,
4842 [&](bke::pbvh::Node &node, float *tmin) { sculpt_find_nearest_to_ray_cb(node, srd, tmin); },
4843 ray_start,
4844 ray_normal,
4845 srd.original);
4846 if (srd.hit && srd.dist_sq_to_ray) {
4847 hit = true;
4848 copy_v3_v3(out, ray_normal);
4849 mul_v3_fl(out, srd.depth);
4850 add_v3_v3(out, ray_start);
4851 }
4852
4853 float closest_radius_sq = std::numeric_limits<float>::max();
4854 if (limit_closest_radius) {
4855 closest_radius_sq = sculpt_calc_radius(vc, brush, *CTX_data_scene(C), out);
4856 closest_radius_sq *= closest_radius_sq;
4857 }
4858
4859 return hit && srd.dist_sq_to_ray < closest_radius_sq;
4860}
4861
4862static void brush_init_tex(const Sculpt &sd, SculptSession &ss)
4863{
4864 const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
4865 const MTex *mask_tex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
4866
4867 /* Init mtex nodes. */
4868 if (mask_tex->tex && mask_tex->tex->nodetree) {
4869 /* Has internal flag to detect it only does it once. */
4871 }
4872
4873 if (ss.tex_pool == nullptr) {
4875 }
4876}
4877
4879{
4881 ToolSettings *tool_settings = CTX_data_tool_settings(C);
4882 const Sculpt &sd = *tool_settings->sculpt;
4884 const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
4885
4886 if (!G.background) {
4888 }
4889 brush_init_tex(sd, ss);
4890
4891 const bool needs_colors = SCULPT_brush_type_is_paint(brush->sculpt_brush_type) &&
4892 !SCULPT_use_image_paint_brush(tool_settings->paint_mode, ob);
4893
4894 if (needs_colors) {
4896 }
4897
4898 /* CTX_data_ensure_evaluated_depsgraph should be used at the end to include the updates of
4899 * earlier steps modifying the data. */
4903
4905}
4906
4908 const Sculpt &sd,
4909 Object &ob)
4910{
4911 using namespace blender::ed::sculpt_paint;
4912 SculptSession &ss = *ob.sculpt;
4913 const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
4914
4915 /* Brushes that use original coordinates and need a "restore" step. This has to happen separately
4916 * rather than in the brush deformation calculation because that is called once for each symmetry
4917 * pass, potentially within the same BVH node.
4918 *
4919 * NOTE: Despite the Cloth and Boundary brush using original coordinates, the brushes do not
4920 * expect this restoration to happen on every stroke step. Performing this restoration causes
4921 * issues with the cloth simulation mode for those brushes.
4922 */
4923 if (ELEM(brush->sculpt_brush_type,
4928 {
4930 return;
4931 }
4932
4933 /* For the cloth brush it makes more sense to not restore the mesh state to keep running the
4934 * simulation from the previous state. */
4936 return;
4937 }
4938
4939 /* Restore the mesh before continuing with anchored stroke. */
4940 if ((brush->flag & BRUSH_ANCHORED) ||
4943 (brush->flag & BRUSH_DRAG_DOT))
4944 {
4945
4947
4948 if (ss.cache) {
4949 /* Temporary data within the StrokeCache that is usually cleared at the end of the stroke
4950 * needs to be invalidated here so that the brushes do not accumulate and apply extra data.
4951 * See #129069. */
4953 ss.cache->paint_brush.mix_colors = {};
4954 }
4955 }
4956}
4957
4958namespace blender::ed::sculpt_paint {
4959
4961{
4962 Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
4964 SculptSession &ss = *ob.sculpt;
4965 ARegion &region = *CTX_wm_region(C);
4968 Mesh *mesh = static_cast<Mesh *>(ob.data);
4969
4971
4972 const bool use_pbvh_draw = BKE_sculptsession_use_pbvh_draw(&ob, rv3d);
4973
4974 if (rv3d) {
4975 /* Mark for faster 3D viewport redraws. */
4976 rv3d->rflag |= RV3D_PAINTING;
4977 }
4978
4979 if (mmd != nullptr) {
4981 }
4982
4983 if ((update_type == UpdateType::Image) != 0) {
4984 ED_region_tag_redraw(&region);
4985 if (update_type == UpdateType::Image) {
4986 /* Early exit when only need to update the images. We don't want to tag any geometry updates
4987 * that would rebuild the bke::pbvh::Tree. */
4988 return;
4989 }
4990 }
4991
4993
4994 /* Only current viewport matters, slower update for all viewports will
4995 * be done in sculpt_flush_update_done. */
4996 if (!use_pbvh_draw) {
4997 /* Slow update with full dependency graph update and all that comes with it.
4998 * Needed when there are modifiers or full shading in the 3D viewport. */
5000 ED_region_tag_redraw(&region);
5001 }
5002 else {
5003 /* Fast path where we just update the BVH nodes that changed, and redraw
5004 * only the part of the 3D viewport where changes happened. */
5005 rcti r;
5006
5008 if (rv3d && SCULPT_get_redraw_rect(region, *rv3d, ob, r)) {
5009 if (ss.cache) {
5010 ss.cache->current_r = r;
5011 }
5012
5013 /* previous is not set in the current cache else
5014 * the partial rect will always grow */
5016
5017 r.xmin += region.winrct.xmin - 2;
5018 r.xmax += region.winrct.xmin + 2;
5019 r.ymin += region.winrct.ymin - 2;
5020 r.ymax += region.winrct.ymin + 2;
5021 ED_region_tag_redraw_partial(&region, &r, true);
5022 }
5023 }
5024
5025 if (update_type == UpdateType::Position && !ss.shapekey_active) {
5026 if (pbvh.type() == bke::pbvh::Type::Mesh) {
5027 /* Various operations inside sculpt mode can cause either the MeshRuntimeData or the entire
5028 * Mesh to be changed (e.g. Undoing the very first operation after opening a file, performing
5029 * remesh, etc).
5030 *
5031 * This is an unideal fix for the core issue here, but to mitigate the drastic performance
5032 * falloff, we refreeze the cache before we do any operation that would tag this runtime
5033 * cache as dirty.
5034 *
5035 * See #130636.
5036 */
5037 if (!mesh->runtime->corner_tris_cache.frozen) {
5038 mesh->runtime->corner_tris_cache.freeze();
5039 }
5040
5041 /* Updating mesh positions without marking caches dirty is generally not good, but since
5042 * sculpt mode has special requirements and is expected to have sole ownership of the mesh it
5043 * modifies, it's generally okay. */
5044 if (use_pbvh_draw) {
5045 /* When drawing from bke::pbvh::Tree is used, vertex and face normals are updated
5046 * later in #bke::pbvh::update_normals. However, we update the mesh's bounds eagerly here
5047 * since they are trivial to access from the bke::pbvh::Tree. Updating the
5048 * object's evaluated geometry bounding box is necessary because sculpt strokes don't cause
5049 * an object reevaluation. */
5050 mesh->tag_positions_changed_no_normals();
5051 /* Sculpt mode does not use or recalculate face corner normals, so they are cleared. */
5052 mesh->runtime->corner_normals_cache.tag_dirty();
5053 }
5054 else {
5055 /* Drawing happens from the modifier stack evaluation result.
5056 * Tag both coordinates and normals as modified, as both needed for proper drawing and the
5057 * modifier stack is not guaranteed to tag normals for update. */
5058 mesh->tag_positions_changed();
5059 }
5060
5061 mesh->bounds_set_eager(bke::pbvh::bounds_get(pbvh));
5062 if (ob.runtime->bounds_eval) {
5063 ob.runtime->bounds_eval = mesh->bounds_min_max();
5064 }
5065 }
5066 }
5067}
5068
5069void flush_update_done(const bContext *C, Object &ob, UpdateType update_type)
5070{
5071 /* After we are done drawing the stroke, check if we need to do a more
5072 * expensive depsgraph tag to update geometry. */
5074 RegionView3D *current_rv3d = CTX_wm_region_view3d(C);
5075 SculptSession &ss = *ob.sculpt;
5076 Mesh *mesh = static_cast<Mesh *>(ob.data);
5077
5078 /* Always needed for linked duplicates. */
5079 bool need_tag = (ID_REAL_USERS(&mesh->id) > 1);
5080
5081 if (current_rv3d) {
5082 current_rv3d->rflag &= ~RV3D_PAINTING;
5083 }
5084
5085 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
5086 bScreen *screen = WM_window_get_active_screen(win);
5087 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
5088 SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
5089 if (sl->spacetype != SPACE_VIEW3D) {
5090 continue;
5091 }
5092
5093 /* Tag all 3D viewports for redraw now that we are done. Others
5094 * viewports did not get a full redraw, and anti-aliasing for the
5095 * current viewport was deactivated. */
5096 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
5097 if (region->regiontype == RGN_TYPE_WINDOW) {
5098 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
5099 if (rv3d != current_rv3d) {
5100 need_tag |= !BKE_sculptsession_use_pbvh_draw(&ob, rv3d);
5101 }
5102
5103 ED_region_tag_redraw(region);
5104 }
5105 }
5106 }
5107
5108 if (update_type == UpdateType::Image) {
5109 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
5110 SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
5111 if (sl->spacetype != SPACE_IMAGE) {
5112 continue;
5113 }
5115 }
5116 }
5117 }
5118
5120
5121 if (update_type == UpdateType::Position) {
5123
5124 /* Coordinates were modified, so fake neighbors are not longer valid. */
5126 }
5127
5128 if (update_type == UpdateType::Position) {
5129 if (pbvh.type() == bke::pbvh::Type::BMesh) {
5131 }
5132 }
5133
5134 if (need_tag) {
5136 }
5137}
5138
5139} // namespace blender::ed::sculpt_paint
5140
5141/* Returns whether the mouse/stylus is over the mesh (1)
5142 * or over the background (0). */
5143static bool over_mesh(bContext *C, wmOperator * /*op*/, const float mval[2])
5144{
5145 float co_dummy[3];
5147 Brush *brush = BKE_paint_brush(&sd->paint);
5148
5149 bool check_closest = brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE;
5150
5151 return SCULPT_stroke_get_location_ex(C, co_dummy, mval, false, check_closest, true);
5152}
5153
5154static void stroke_undo_begin(const bContext *C, wmOperator *op)
5155{
5156 using namespace blender::ed::sculpt_paint;
5157 const Scene &scene = *CTX_data_scene(C);
5159 const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
5160 const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
5161 ToolSettings *tool_settings = CTX_data_tool_settings(C);
5162
5163 /* Setup the correct undo system. Image painting and sculpting are mutual exclusive.
5164 * Color attributes are part of the sculpting undo system. */
5165 if (brush && brush->sculpt_brush_type == SCULPT_BRUSH_TYPE_PAINT &&
5166 SCULPT_use_image_paint_brush(tool_settings->paint_mode, ob))
5167 {
5169 }
5170 else {
5172 }
5173}
5174
5175static void stroke_undo_end(const bContext *C, Brush *brush)
5176{
5177 using namespace blender::ed::sculpt_paint;
5179 ToolSettings *tool_settings = CTX_data_tool_settings(C);
5180
5181 if (brush && brush->sculpt_brush_type == SCULPT_BRUSH_TYPE_PAINT &&
5182 SCULPT_use_image_paint_brush(tool_settings->paint_mode, ob))
5183 {
5185 }
5186 else {
5187 undo::push_end(ob);
5188 }
5189}
5190
5192{
5193 switch (blender::bke::object::pbvh_get(object)->type()) {
5195 return true;
5197 BKE_report(reports, RPT_ERROR, "Not supported in dynamic topology mode");
5198 return false;
5200 BKE_report(reports, RPT_ERROR, "Not supported in multiresolution mode");
5201 return false;
5202 }
5204 return false;
5205}
5206
5207namespace blender::ed::sculpt_paint {
5208
5209static bool stroke_test_start(bContext *C, wmOperator *op, const float mval[2])
5210{
5211 /* Don't start the stroke until `mval` goes over the mesh.
5212 * NOTE: `mval` will only be null when re-executing the saved stroke.
5213 * We have exception for 'exec' strokes since they may not set `mval`,
5214 * only 'location', see: #52195. */
5215 if (((op->flag & OP_IS_INVOKE) == 0) || (mval == nullptr) || over_mesh(C, op, mval)) {
5217 SculptSession &ss = *ob.sculpt;
5219 Brush *brush = BKE_paint_brush(&sd.paint);
5220 ToolSettings *tool_settings = CTX_data_tool_settings(C);
5221
5222 /* NOTE: This should be removed when paint mode is available. Paint mode can force based on the
5223 * canvas it is painting on. (ref. use_sculpt_texture_paint). */
5224 if (brush && SCULPT_brush_type_is_paint(brush->sculpt_brush_type) &&
5225 !SCULPT_use_image_paint_brush(tool_settings->paint_mode, ob))
5226 {
5227 View3D *v3d = CTX_wm_view3d(C);
5228 if (v3d->shading.type == OB_SOLID) {
5230 }
5231 }
5232
5234
5235 sculpt_update_cache_invariants(C, sd, ss, op, mval);
5236
5238 SCULPT_cursor_geometry_info_update(C, &sgi, mval, false);
5239
5240 stroke_undo_begin(C, op);
5241
5242 return true;
5243 }
5244 return false;
5245}
5246
5248 wmOperator * /*op*/,
5249 PaintStroke *stroke,
5250 PointerRNA *itemptr)
5251{
5253 const Scene &scene = *CTX_data_scene(C);
5254 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
5257 SculptSession &ss = *ob.sculpt;
5258 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
5259 ToolSettings &tool_settings = *CTX_data_tool_settings(C);
5260 StrokeCache *cache = ss.cache;
5262
5263 SCULPT_stroke_modifiers_check(C, ob, brush);
5264 sculpt_update_cache_variants(C, sd, ob, itemptr);
5266
5267 if (dyntopo::stroke_is_dyntopo(ob, brush)) {
5269 depsgraph, scene, sd, ob, dynamic_topology_update, ups, tool_settings.paint_mode);
5270 }
5271
5273 depsgraph, scene, sd, ob, do_brush_action, ups, tool_settings.paint_mode);
5274
5275 /* Hack to fix noise texture tearing mesh. */
5276 sculpt_fix_noise_tear(sd, ob);
5277
5278 ss.cache->first_time = false;
5280
5281 /* Cleanup. */
5284 }
5286 if (SCULPT_use_image_paint_brush(tool_settings.paint_mode, ob)) {
5288 }
5289 else {
5291 }
5292 }
5293 else {
5295 }
5296}
5297
5298static void brush_exit_tex(Sculpt &sd)
5299{
5300 Brush *brush = BKE_paint_brush(&sd.paint);
5301 const MTex *mask_tex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
5302
5303 if (mask_tex->tex && mask_tex->tex->nodetree) {
5304 ntreeTexEndExecTree(mask_tex->tex->nodetree->runtime->execdata);
5305 }
5306}
5307
5308static void stroke_done(const bContext *C, PaintStroke * /*stroke*/)
5309{
5311 SculptSession &ss = *ob.sculpt;
5313 ToolSettings *tool_settings = CTX_data_tool_settings(C);
5314
5315 /* Finished. */
5316 if (!ss.cache) {
5317 brush_exit_tex(sd);
5318 return;
5319 }
5321 Brush *brush = BKE_paint_brush(&sd.paint);
5322 BLI_assert(brush == ss.cache->brush); /* const, so we shouldn't change. */
5323 ups->draw_inverted = false;
5324
5325 SCULPT_stroke_modifiers_check(C, ob, *brush);
5326
5327 /* Alt-Smooth. */
5328 if (ss.cache->alt_smooth) {
5330 /* Refresh the brush pointer in case we switched brush in the toggle function. */
5331 brush = BKE_paint_brush(&sd.paint);
5332 }
5333
5334 MEM_delete(ss.cache);
5335 ss.cache = nullptr;
5336
5337 stroke_undo_end(C, brush);
5338
5341 }
5342 else if (brush->sculpt_brush_type == SCULPT_BRUSH_TYPE_PAINT) {
5343 if (SCULPT_use_image_paint_brush(tool_settings->paint_mode, ob)) {
5345 }
5346 else {
5348 }
5349 }
5350 else {
5352 }
5353
5355 brush_exit_tex(sd);
5356}
5357
5359{
5360 PaintStroke *stroke;
5361 int ignore_background_click;
5362 int retval;
5364 Scene &scene = *CTX_data_scene(C);
5365 const View3D *v3d = CTX_wm_view3d(C);
5366 const Base *base = CTX_data_active_base(C);
5367 /* Test that ob is visible; otherwise we won't be able to get evaluated data
5368 * from the depsgraph. We do this here instead of SCULPT_mode_poll
5369 * to avoid falling through to the translate operator in the
5370 * global view3d keymap. */
5371 if (!BKE_base_is_visible(v3d, base)) {
5372 return OPERATOR_CANCELLED;
5373 }
5374
5376
5378 Brush &brush = *BKE_paint_brush(&sd.paint);
5379
5382 {
5383 return OPERATOR_CANCELLED;
5384 }
5388 }
5391 {
5392 return OPERATOR_CANCELLED;
5393 }
5394 if (ELEM(brush.sculpt_brush_type,
5397 {
5399 if (!pbvh || pbvh->type() != bke::pbvh::Type::Grids) {
5400 BKE_report(op->reports, RPT_ERROR, "Only supported in multiresolution mode");
5401 return OPERATOR_CANCELLED;
5402 }
5403 }
5404
5405 stroke = paint_stroke_new(C,
5406 op,
5410 nullptr,
5412 event->type);
5413
5414 op->customdata = stroke;
5415
5416 /* For tablet rotation. */
5417 ignore_background_click = RNA_boolean_get(op->ptr, "ignore_background_click");
5418 const float mval[2] = {float(event->mval[0]), float(event->mval[1])};
5419 if (ignore_background_click && !over_mesh(C, op, mval)) {
5420 paint_stroke_free(C, op, static_cast<PaintStroke *>(op->customdata));
5421 return OPERATOR_PASS_THROUGH;
5422 }
5423
5424 retval = op->type->modal(C, op, event);
5426 paint_stroke_free(C, op, static_cast<PaintStroke *>(op->customdata));
5427 return retval;
5428 }
5429 /* Add modal handler. */
5431
5432 OPERATOR_RETVAL_CHECK(retval);
5434
5436}
5437
5439{
5441
5443 op,
5447 nullptr,
5449 0);
5450
5451 /* Frees op->customdata. */
5452 paint_stroke_exec(C, op, static_cast<PaintStroke *>(op->customdata));
5453
5454 return OPERATOR_FINISHED;
5455}
5456
5458{
5459 using namespace blender::ed::sculpt_paint;
5460 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
5462 SculptSession &ss = *ob.sculpt;
5464 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
5465
5466 /* XXX Canceling strokes that way does not work with dynamic topology,
5467 * user will have to do real undo for now. See #46456. */
5468 if (ss.cache && !dyntopo::stroke_is_dyntopo(ob, brush)) {
5470 }
5471
5472 paint_stroke_cancel(C, op, static_cast<PaintStroke *>(op->customdata));
5473
5474 MEM_delete(ss.cache);
5475 ss.cache = nullptr;
5476
5477 brush_exit_tex(sd);
5478}
5479
5480static int brush_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
5481{
5482 return paint_stroke_modal(C, op, event, (PaintStroke **)&op->customdata);
5483}
5484
5485static void redo_empty_ui(bContext * /*C*/, wmOperator * /*op*/) {}
5486
5488{
5489 /* Identifiers. */
5490 ot->name = "Sculpt";
5491 ot->idname = "SCULPT_OT_brush_stroke";
5492 ot->description = "Sculpt a stroke into the geometry";
5493
5494 /* API callbacks. */
5496 ot->modal = brush_stroke_modal;
5498 ot->poll = SCULPT_poll;
5500 ot->ui = redo_empty_ui;
5501
5502 /* Flags (sculpt does its own undo? (ton)). */
5503 ot->flag = OPTYPE_BLOCKING;
5504
5505 /* Properties. */
5506
5508
5509 RNA_def_boolean(ot->srna,
5510 "ignore_background_click",
5511 false,
5512 "Ignore Background Click",
5513 "Clicks on the background do not start the stroke");
5514}
5515
5516/* Fake Neighbors. */
5517
5518static void fake_neighbor_init(Object &object, const float max_dist)
5519{
5520 SculptSession &ss = *object.sculpt;
5521 const int totvert = SCULPT_vertex_count_get(object);
5524}
5525
5530
5532 int vert = -1;
5533 float distance_sq = std::numeric_limits<float>::max();
5534
5536 {
5537 NearestVertData joined = a;
5538 if (joined.vert == -1) {
5539 joined.vert = b.vert;
5540 joined.distance_sq = b.distance_sq;
5541 }
5542 else if (b.distance_sq < joined.distance_sq) {
5543 joined.vert = b.vert;
5544 joined.distance_sq = b.distance_sq;
5545 }
5546 return joined;
5547 }
5548};
5549
5551 const Span<float3> vert_positions,
5552 const Span<bool> hide_vert,
5553 const float3 &location,
5554 const float max_distance_sq,
5555 const int island_id,
5556 const bke::pbvh::MeshNode &node,
5557 NearestVertData &nvtd)
5558{
5559 for (const int vert : node.verts()) {
5560 if (!hide_vert.is_empty() && hide_vert[vert]) {
5561 continue;
5562 }
5564 continue;
5565 }
5566 if (islands::vert_id_get(ss, vert) == island_id) {
5567 continue;
5568 }
5569 const float distance_sq = math::distance_squared(vert_positions[vert], location);
5570 if (distance_sq < max_distance_sq && distance_sq < nvtd.distance_sq) {
5571 nvtd.vert = vert;
5572 nvtd.distance_sq = distance_sq;
5573 }
5574 }
5575}
5576
5578 const CCGKey &key,
5579 const Span<float3> positions,
5580 const BitGroupVector<> &grid_hidden,
5581 const float3 &location,
5582 const float max_distance_sq,
5583 const int island_id,
5584 const bke::pbvh::GridsNode &node,
5585 NearestVertData &nvtd)
5586{
5587 for (const int grid : node.grids()) {
5588 const IndexRange grid_range = bke::ccg::grid_range(key, grid);
5589 BKE_subdiv_ccg_foreach_visible_grid_vert(key, grid_hidden, grid, [&](const int offset) {
5590 const int vert = grid_range[offset];
5592 return;
5593 }
5594 if (islands::vert_id_get(ss, vert) == island_id) {
5595 return;
5596 }
5597 const float distance_sq = math::distance_squared(positions[vert], location);
5598 if (distance_sq < max_distance_sq && distance_sq < nvtd.distance_sq) {
5599 nvtd.vert = vert;
5600 nvtd.distance_sq = distance_sq;
5601 }
5602 });
5603 }
5604}
5605
5607 const float3 &location,
5608 const float max_distance_sq,
5609 const int island_id,
5610 const bke::pbvh::BMeshNode &node,
5611 NearestVertData &nvtd)
5612{
5613 for (const BMVert *bm_vert :
5615 {
5616 if (BM_elem_flag_test(bm_vert, BM_ELEM_HIDDEN)) {
5617 continue;
5618 }
5619 const int vert = BM_elem_index_get(bm_vert);
5621 continue;
5622 }
5623 if (islands::vert_id_get(ss, vert) == island_id) {
5624 continue;
5625 }
5626 const float distance_sq = math::distance_squared(float3(bm_vert->co), location);
5627 if (distance_sq < max_distance_sq && distance_sq < nvtd.distance_sq) {
5628 nvtd.vert = vert;
5629 nvtd.distance_sq = distance_sq;
5630 }
5631 }
5632}
5633
5634static void fake_neighbor_search(const Depsgraph &depsgraph,
5635 const Object &ob,
5636 const float max_distance_sq,
5637 MutableSpan<int> fake_neighbors)
5638{
5639 /* NOTE: This algorithm is extremely slow, it has O(n^2) runtime for the entire mesh. This looks
5640 * like the "closest pair of points" problem which should have far better solutions. */
5641 SculptSession &ss = *ob.sculpt;
5642 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
5643
5644 switch (pbvh.type()) {
5645 case bke::pbvh::Type::Mesh: {
5646 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
5647 const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, ob);
5648 const bke::AttributeAccessor attributes = mesh.attributes();
5649 const VArraySpan<bool> hide_vert = *attributes.lookup<bool>(".hide_vert",
5651 for (const int vert : vert_positions.index_range()) {
5652 if (fake_neighbors[vert] != FAKE_NEIGHBOR_NONE) {
5653 continue;
5654 }
5655 const int island_id = islands::vert_id_get(ss, vert);
5656 const float3 &location = vert_positions[vert];
5657
5658 IndexMaskMemory memory;
5659 const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
5660 pbvh, memory, [&](const bke::pbvh::Node &node) {
5661 return node_in_sphere(node, location, max_distance_sq, false);
5662 });
5663 if (nodes_in_sphere.is_empty()) {
5664 continue;
5665 }
5668 nodes_in_sphere.index_range(),
5669 1,
5671 [&](const IndexRange range, NearestVertData nvtd) {
5672 nodes_in_sphere.slice(range).foreach_index([&](const int i) {
5674 vert_positions,
5675 hide_vert,
5676 location,
5677 max_distance_sq,
5678 island_id,
5679 nodes[i],
5680 nvtd);
5681 });
5682 return nvtd;
5683 },
5685 if (nvtd.vert == -1) {
5686 continue;
5687 }
5688 fake_neighbors[vert] = nvtd.vert;
5689 fake_neighbors[nvtd.vert] = vert;
5690 }
5691 break;
5692 }
5694 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
5695 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
5696 const Span<float3> positions = subdiv_ccg.positions;
5697 const BitGroupVector<> grid_hidden = subdiv_ccg.grid_hidden;
5698 for (const int vert : positions.index_range()) {
5699 if (fake_neighbors[vert] != FAKE_NEIGHBOR_NONE) {
5700 continue;
5701 }
5702 const int island_id = islands::vert_id_get(ss, vert);
5703 const float3 &location = positions[vert];
5704 IndexMaskMemory memory;
5705 const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
5706 pbvh, memory, [&](const bke::pbvh::Node &node) {
5707 return node_in_sphere(node, location, max_distance_sq, false);
5708 });
5709 if (nodes_in_sphere.is_empty()) {
5710 continue;
5711 }
5714 nodes_in_sphere.index_range(),
5715 1,
5717 [&](const IndexRange range, NearestVertData nvtd) {
5718 nodes_in_sphere.slice(range).foreach_index([&](const int i) {
5720 key,
5721 positions,
5722 grid_hidden,
5723 location,
5724 max_distance_sq,
5725 island_id,
5726 nodes[i],
5727 nvtd);
5728 });
5729 return nvtd;
5730 },
5732 if (nvtd.vert == -1) {
5733 continue;
5734 }
5735 fake_neighbors[vert] = nvtd.vert;
5736 fake_neighbors[nvtd.vert] = vert;
5737 }
5738 break;
5739 }
5741 const BMesh &bm = *ss.bm;
5742 for (const int vert : IndexRange(bm.totvert)) {
5743 if (fake_neighbors[vert] != FAKE_NEIGHBOR_NONE) {
5744 continue;
5745 }
5746 const int island_id = islands::vert_id_get(ss, vert);
5747 const float3 &location = BM_vert_at_index(&const_cast<BMesh &>(bm), vert)->co;
5748 IndexMaskMemory memory;
5749 const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
5750 pbvh, memory, [&](const bke::pbvh::Node &node) {
5751 return node_in_sphere(node, location, max_distance_sq, false);
5752 });
5753 if (nodes_in_sphere.is_empty()) {
5754 continue;
5755 }
5758 nodes_in_sphere.index_range(),
5759 1,
5761 [&](const IndexRange range, NearestVertData nvtd) {
5762 nodes_in_sphere.slice(range).foreach_index([&](const int i) {
5764 ss, location, max_distance_sq, island_id, nodes[i], nvtd);
5765 });
5766 return nvtd;
5767 },
5769 if (nvtd.vert == -1) {
5770 continue;
5771 }
5772 fake_neighbors[vert] = nvtd.vert;
5773 fake_neighbors[nvtd.vert] = vert;
5774 }
5775 break;
5776 }
5777 }
5778}
5779
5780} // namespace blender::ed::sculpt_paint
5781
5783
5785{
5786 SculptSession &ss = *object.sculpt;
5787 if (!ss.vertex_info.boundary.is_empty()) {
5788 return;
5789 }
5790
5791 Mesh *base_mesh = BKE_mesh_from_object(&object);
5792
5793 ss.vertex_info.boundary.resize(base_mesh->verts_num);
5794 Array<int> adjacent_faces_edge_count(base_mesh->edges_num, 0);
5795 array_utils::count_indices(base_mesh->corner_edges(), adjacent_faces_edge_count);
5796
5797 const Span<int2> edges = base_mesh->edges();
5798 for (const int e : edges.index_range()) {
5799 if (adjacent_faces_edge_count[e] < 2) {
5800 const int2 &edge = edges[e];
5801 ss.vertex_info.boundary[edge[0]].set();
5802 ss.vertex_info.boundary[edge[1]].set();
5803 }
5804 }
5805}
5806
5807} // namespace blender::ed::sculpt_paint::boundary
5808
5810 Object &ob,
5811 const float max_dist)
5812{
5813 using namespace blender::ed::sculpt_paint;
5814 SculptSession &ss = *ob.sculpt;
5815
5816 /* Fake neighbors were already initialized with the same distance, so no need to be
5817 * recalculated. */
5819 ss.fake_neighbors.current_max_distance == max_dist)
5820 {
5822 }
5823
5825 fake_neighbor_init(ob, max_dist);
5827
5829}
5830
5832{
5833 using namespace blender::ed::sculpt_paint;
5834 SculptSession &ss = *ob.sculpt;
5836}
5837
5839 const Object &object,
5840 const float3 &position,
5841 bool original)
5842{
5843 using namespace blender;
5844 SculptSession &ss = *object.sculpt;
5845 float ray_start[3], ray_end[3], ray_normal[3];
5846
5847 ViewContext *vc = ss.cache ? ss.cache->vc : &ss.filter_cache->vc;
5848
5850 vc->region, position, ss.cache ? ss.cache->projection_mat : ss.filter_cache->viewmat);
5851
5852 int depth = SCULPT_raycast_init(vc, mouse, ray_end, ray_start, ray_normal, original);
5853
5854 negate_v3(ray_normal);
5855
5856 copy_v3_v3(ray_start, position);
5857 madd_v3_v3fl(ray_start, ray_normal, 0.002);
5858
5859 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(const_cast<Object &>(object));
5860
5861 SculptRaycastData srd = {nullptr};
5862 srd.original = original;
5863 srd.object = &const_cast<Object &>(object);
5864 srd.ss = &ss;
5865 srd.hit = false;
5866 srd.ray_start = ray_start;
5867 srd.ray_normal = ray_normal;
5868 srd.depth = depth;
5869 if (pbvh.type() == bke::pbvh::Type::Mesh) {
5870 const Mesh &mesh = *static_cast<const Mesh *>(object.data);
5872 srd.faces = mesh.faces();
5873 srd.corner_verts = mesh.corner_verts();
5874 srd.corner_tris = mesh.corner_tris();
5875 }
5876 else if (pbvh.type() == bke::pbvh::Type::Grids) {
5877 srd.subdiv_ccg = ss.subdiv_ccg;
5878 }
5879 SCULPT_vertex_random_access_ensure(const_cast<Object &>(object));
5880
5883 pbvh,
5884 [&](bke::pbvh::Node &node, float *tmin) { sculpt_raycast_cb(node, srd, tmin); },
5885 ray_start,
5886 ray_normal,
5887 srd.original);
5888
5889 return srd.hit;
5890}
5891
5893
5894int vert_id_get(const SculptSession &ss, const int vert)
5895{
5897 if (!ss.topology_island_cache) {
5898 /* The cache should be calculated whenever it's necessary.
5899 * Still avoid crashing in release builds though. */
5900 return 0;
5901 }
5903 if (!cache.vert_island_ids.is_empty()) {
5904 return cache.vert_island_ids[vert];
5905 }
5906 return 0;
5907}
5908
5910{
5911 ss.topology_island_cache.reset();
5912}
5913
5915 const int verts_num)
5916{
5917 Array<int> island_indices(verts_num);
5918 const int islands_num = vert_sets.calc_reduced_ids(island_indices);
5919 if (islands_num == 1) {
5920 return {};
5921 }
5922
5923 Array<uint8_t> island_ids(island_indices.size());
5924 threading::parallel_for(island_ids.index_range(), 4096, [&](const IndexRange range) {
5925 for (const int i : range) {
5926 island_ids[i] = uint8_t(island_indices[i]);
5927 }
5928 });
5929
5931 cache.vert_island_ids = std::move(island_ids);
5932 return cache;
5933}
5934
5936{
5937 const OffsetIndices<int> faces = mesh.faces();
5938 const Span<int> corner_verts = mesh.corner_verts();
5939 const bke::AttributeAccessor attributes = mesh.attributes();
5940 const VArraySpan<bool> hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
5941 IndexMaskMemory memory;
5942 const IndexMask visible_faces = hide_poly.is_empty() ?
5943 IndexMask(faces.size()) :
5945 faces.index_range(), hide_poly, memory);
5946
5947 AtomicDisjointSet disjoint_set(mesh.verts_num);
5948 visible_faces.foreach_index(GrainSize(1024), [&](const int face) {
5949 const Span<int> face_verts = corner_verts.slice(faces[face]);
5950 for (const int i : face_verts.index_range().drop_front(1)) {
5951 disjoint_set.join(face_verts.first(), face_verts[i]);
5952 }
5953 });
5954 return vert_disjoint_set_to_islands(disjoint_set, mesh.verts_num);
5955}
5956
5961{
5962 const SculptSession &ss = *object.sculpt;
5963 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
5964 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
5965 AtomicDisjointSet disjoint_set(subdiv_ccg.positions.size());
5966 threading::parallel_for(IndexRange(subdiv_ccg.grids_num), 512, [&](const IndexRange range) {
5967 for (const int grid : range) {
5968 SubdivCCGNeighbors neighbors;
5969 for (const short y : IndexRange(key.grid_size)) {
5970 for (const short x : IndexRange(key.grid_size)) {
5971 const SubdivCCGCoord coord{grid, x, y};
5972 SubdivCCGNeighbors neighbors;
5973 BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, true, neighbors);
5974 for (const SubdivCCGCoord neighbor : neighbors.coords) {
5975 disjoint_set.join(coord.to_index(key), neighbor.to_index(key));
5976 }
5977 }
5978 }
5979 }
5980 });
5981
5982 return vert_disjoint_set_to_islands(disjoint_set, subdiv_ccg.positions.size());
5983}
5984
5986{
5987 const SculptSession &ss = *object.sculpt;
5988 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
5990 BMesh &bm = *ss.bm;
5992
5993 IndexMaskMemory memory;
5994 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
5995 AtomicDisjointSet disjoint_set(bm.totvert);
5996 node_mask.foreach_index(GrainSize(1), [&](const int i) {
5997 for (const BMFace *face :
5999 {
6000 if (BM_elem_flag_test(face, BM_ELEM_HIDDEN)) {
6001 continue;
6002 }
6003 disjoint_set.join(BM_elem_index_get(face->l_first->v),
6004 BM_elem_index_get(face->l_first->next->v));
6005 disjoint_set.join(BM_elem_index_get(face->l_first->v),
6006 BM_elem_index_get(face->l_first->next->next->v));
6007 }
6008 });
6009
6010 return vert_disjoint_set_to_islands(disjoint_set, bm.totvert);
6011}
6012
6014{
6015 switch (bke::object::pbvh_get(object)->type()) {
6017 return calc_topology_islands_mesh(*static_cast<const Mesh *>(object.data));
6019 return calc_topology_islands_grids(object);
6021 return calc_topology_islands_bmesh(object);
6022 }
6024 return {};
6025}
6026
6028{
6029 SculptSession &ss = *object.sculpt;
6030 if (ss.topology_island_cache) {
6031 return;
6032 }
6033 ss.topology_island_cache = std::make_unique<SculptTopologyIslandCache>(calculate_cache(object));
6034}
6035
6036} // namespace blender::ed::sculpt_paint::islands
6037
6038void SCULPT_cube_tip_init(const Sculpt & /*sd*/,
6039 const Object &ob,
6040 const Brush &brush,
6041 float mat[4][4])
6042{
6043 using namespace blender::ed::sculpt_paint;
6044 SculptSession &ss = *ob.sculpt;
6045 float scale[4][4];
6046 float tmat[4][4];
6047 float unused[4][4];
6048
6049 zero_m4(mat);
6050 calc_brush_local_mat(0.0, ob, unused, mat);
6051
6052 /* NOTE: we ignore the radius scaling done inside of calc_brush_local_mat to
6053 * duplicate prior behavior.
6054 *
6055 * TODO: try disabling this and check that all edge cases work properly.
6056 */
6057 normalize_m4(mat);
6058
6059 scale_m4_fl(scale, ss.cache->radius);
6060 mul_m4_m4m4(tmat, mat, scale);
6061 mul_v3_fl(tmat[1], brush.tip_scale_x);
6062 invert_m4_m4(mat, tmat);
6063}
6064
6065
6066namespace blender::ed::sculpt_paint {
6067
6069{
6070 BLI_assert(verts.size() == positions.size());
6071
6072 int i = 0;
6073 for (const BMVert *vert : verts) {
6074 positions[i] = vert->co;
6075 i++;
6076 }
6077}
6078
6079void gather_grids_normals(const SubdivCCG &subdiv_ccg,
6080 const Span<int> grids,
6082{
6083 gather_data_grids(subdiv_ccg, subdiv_ccg.normals.as_span(), grids, normals);
6084}
6085
6087{
6088 int i = 0;
6089 for (const BMVert *vert : verts) {
6090 normals[i] = vert->no;
6091 i++;
6092 }
6093}
6094
6095template<typename T>
6097{
6098 BLI_assert(indices.size() == dst.size());
6099
6100 for (const int i : indices.index_range()) {
6101 dst[i] = src[indices[i]];
6102 }
6103}
6104
6105template<typename T>
6106void gather_data_grids(const SubdivCCG &subdiv_ccg,
6107 const Span<T> src,
6108 const Span<int> grids,
6109 const MutableSpan<T> node_data)
6110{
6111 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
6112 BLI_assert(grids.size() * key.grid_area == node_data.size());
6113
6114 for (const int i : grids.index_range()) {
6115 const IndexRange grids_range = bke::ccg::grid_range(key, grids[i]);
6116 const IndexRange node_range = bke::ccg::grid_range(key, i);
6117 node_data.slice(node_range).copy_from(src.slice(grids_range));
6118 }
6119}
6120
6121template<typename T>
6123 const Set<BMVert *, 0> &verts,
6124 const MutableSpan<T> node_data)
6125{
6126 BLI_assert(verts.size() == node_data.size());
6127
6128 int i = 0;
6129 for (const BMVert *vert : verts) {
6130 node_data[i] = src[BM_elem_index_get(vert)];
6131 i++;
6132 }
6133}
6134
6135template<typename T>
6137{
6138 BLI_assert(indices.size() == src.size());
6139
6140 for (const int i : indices.index_range()) {
6141 dst[indices[i]] = src[i];
6142 }
6143}
6144
6145template<typename T>
6146void scatter_data_grids(const SubdivCCG &subdiv_ccg,
6147 const Span<T> node_data,
6148 const Span<int> grids,
6149 const MutableSpan<T> dst)
6150{
6151 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
6152 BLI_assert(grids.size() * key.grid_area == node_data.size());
6153
6154 for (const int i : grids.index_range()) {
6155 const IndexRange grids_range = bke::ccg::grid_range(key, grids[i]);
6156 const IndexRange node_range = bke::ccg::grid_range(key, i);
6157 dst.slice(grids_range).copy_from(node_data.slice(node_range));
6158 }
6159}
6160
6161template<typename T>
6162void scatter_data_bmesh(const Span<T> node_data,
6163 const Set<BMVert *, 0> &verts,
6164 const MutableSpan<T> dst)
6165{
6166 BLI_assert(verts.size() == node_data.size());
6167
6168 int i = 0;
6169 for (const BMVert *vert : verts) {
6170 dst[BM_elem_index_get(vert)] = node_data[i];
6171 i++;
6172 }
6173}
6174
6183 Span<int>,
6187 Span<int>,
6192 const Set<BMVert *, 0> &,
6194
6202 Span<int>,
6206 Span<int>,
6210 const Set<BMVert *, 0> &,
6212
6214 const Brush &brush,
6215 const Object &object,
6216 const MeshAttributeData &attribute_data,
6217 const Span<float3> vert_positions,
6218 const Span<float3> vert_normals,
6219 const bke::pbvh::MeshNode &node,
6220 Vector<float> &r_factors,
6221 Vector<float> &r_distances)
6222{
6223 const SculptSession &ss = *object.sculpt;
6224 const StrokeCache &cache = *ss.cache;
6225
6226 const Span<int> verts = node.verts();
6227
6228 r_factors.resize(verts.size());
6229 const MutableSpan<float> factors = r_factors;
6230 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
6231 filter_region_clip_factors(ss, vert_positions, verts, factors);
6232 if (brush.flag & BRUSH_FRONTFACE) {
6233 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
6234 }
6235
6236 r_distances.resize(verts.size());
6237 const MutableSpan<float> distances = r_distances;
6239 ss, vert_positions, verts, eBrushFalloffShape(brush.falloff_shape), distances);
6240 filter_distances_with_radius(cache.radius, distances, factors);
6241 apply_hardness_to_distances(cache, distances);
6242 calc_brush_strength_factors(cache, brush, distances, factors);
6243
6244 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
6245
6246 calc_brush_texture_factors(ss, brush, vert_positions, verts, factors);
6247}
6248
6250 const Brush &brush,
6251 const Object &object,
6252 const MeshAttributeData &attribute_data,
6253 const Span<float3> positions,
6254 const Span<float3> vert_normals,
6255 const bke::pbvh::MeshNode &node,
6256 Vector<float> &r_factors,
6257 Vector<float> &r_distances)
6258{
6259 const SculptSession &ss = *object.sculpt;
6260 const StrokeCache &cache = *ss.cache;
6261
6262 const Span<int> verts = node.verts();
6263
6264 r_factors.resize(verts.size());
6265 const MutableSpan<float> factors = r_factors;
6266 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
6267 filter_region_clip_factors(ss, positions, factors);
6268 if (brush.flag & BRUSH_FRONTFACE) {
6269 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
6270 }
6271
6272 r_distances.resize(verts.size());
6273 const MutableSpan<float> distances = r_distances;
6274 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
6275 filter_distances_with_radius(cache.radius, distances, factors);
6276 apply_hardness_to_distances(cache, distances);
6277 calc_brush_strength_factors(cache, brush, distances, factors);
6278
6279 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
6280
6281 calc_brush_texture_factors(ss, brush, positions, factors);
6282}
6283
6285 const Brush &brush,
6286 const Object &object,
6287 const Span<float3> positions,
6288 const bke::pbvh::GridsNode &node,
6289 Vector<float> &r_factors,
6290 Vector<float> &r_distances)
6291{
6292 const SculptSession &ss = *object.sculpt;
6293 const StrokeCache &cache = *ss.cache;
6294 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
6295
6296 const Span<int> grids = node.grids();
6297
6298 r_factors.resize(positions.size());
6299 const MutableSpan<float> factors = r_factors;
6300 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
6301 filter_region_clip_factors(ss, positions, factors);
6302 if (brush.flag & BRUSH_FRONTFACE) {
6303 calc_front_face(cache.view_normal_symm, subdiv_ccg, grids, factors);
6304 }
6305
6306 r_distances.resize(positions.size());
6307 const MutableSpan<float> distances = r_distances;
6308 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
6309 filter_distances_with_radius(cache.radius, distances, factors);
6310 apply_hardness_to_distances(cache, distances);
6311 calc_brush_strength_factors(cache, brush, distances, factors);
6312
6313 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
6314
6315 calc_brush_texture_factors(ss, brush, positions, factors);
6316}
6317
6319 const Brush &brush,
6320 const Object &object,
6321 const Span<float3> positions,
6323 Vector<float> &r_factors,
6324 Vector<float> &r_distances)
6325{
6326 const SculptSession &ss = *object.sculpt;
6327 const StrokeCache &cache = *ss.cache;
6328
6330
6331 r_factors.resize(verts.size());
6332 const MutableSpan<float> factors = r_factors;
6334 filter_region_clip_factors(ss, positions, factors);
6335 if (brush.flag & BRUSH_FRONTFACE) {
6336 calc_front_face(cache.view_normal_symm, verts, factors);
6337 }
6338
6339 r_distances.resize(verts.size());
6340 const MutableSpan<float> distances = r_distances;
6341 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
6342 filter_distances_with_radius(cache.radius, distances, factors);
6343 apply_hardness_to_distances(cache, distances);
6344 calc_brush_strength_factors(cache, brush, distances, factors);
6345
6346 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
6347
6348 calc_brush_texture_factors(ss, brush, positions, factors);
6349}
6350
6352 const Brush &brush,
6353 const Object &object,
6354 const MeshAttributeData &attribute_data,
6355 const Span<float3> positions,
6356 const Span<float3> normals,
6357 const bke::pbvh::MeshNode &node,
6358 Vector<float> &r_factors,
6359 Vector<float> &r_distances)
6360{
6361 const SculptSession &ss = *object.sculpt;
6362 const StrokeCache &cache = *ss.cache;
6363
6364 const Span<int> verts = node.verts();
6365
6366 r_factors.resize(verts.size());
6367 const MutableSpan<float> factors = r_factors;
6368 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
6369 filter_region_clip_factors(ss, positions, factors);
6370
6371 if (brush.flag & BRUSH_FRONTFACE) {
6372 calc_front_face(cache.view_normal_symm, normals, factors);
6373 }
6374
6375 r_distances.resize(verts.size());
6376 const MutableSpan<float> distances = r_distances;
6377 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
6378 filter_distances_with_radius(cache.radius, distances, factors);
6379 apply_hardness_to_distances(cache, distances);
6380 calc_brush_strength_factors(cache, brush, distances, factors);
6381
6382 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
6383
6384 calc_brush_texture_factors(ss, brush, positions, factors);
6385}
6386
6388 const Brush &brush,
6389 const Object &object,
6390 const Span<float3> positions,
6391 const Span<float3> normals,
6392 const bke::pbvh::GridsNode &node,
6393 Vector<float> &r_factors,
6394 Vector<float> &r_distances)
6395{
6396 SculptSession &ss = *object.sculpt;
6397 const StrokeCache &cache = *ss.cache;
6398 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
6399
6400 const Span<int> grids = node.grids();
6401
6402 r_factors.resize(positions.size());
6403 const MutableSpan<float> factors = r_factors;
6404 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
6405 filter_region_clip_factors(ss, positions, factors);
6406 if (brush.flag & BRUSH_FRONTFACE) {
6407 calc_front_face(cache.view_normal_symm, normals, factors);
6408 }
6409
6410 r_distances.resize(positions.size());
6411 const MutableSpan<float> distances = r_distances;
6412 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
6413 filter_distances_with_radius(cache.radius, distances, factors);
6414 apply_hardness_to_distances(cache, distances);
6415 calc_brush_strength_factors(cache, brush, distances, factors);
6416
6417 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
6418
6419 calc_brush_texture_factors(ss, brush, positions, factors);
6420}
6421
6423 const Brush &brush,
6424 const Object &object,
6425 const Span<float3> positions,
6426 const Span<float3> normals,
6428 Vector<float> &r_factors,
6429 Vector<float> &r_distances)
6430{
6431 SculptSession &ss = *object.sculpt;
6432 const StrokeCache &cache = *ss.cache;
6433
6435
6436 r_factors.resize(verts.size());
6437 const MutableSpan<float> factors = r_factors;
6439 filter_region_clip_factors(ss, positions, factors);
6440 if (brush.flag & BRUSH_FRONTFACE) {
6441 calc_front_face(cache.view_normal_symm, normals, factors);
6442 }
6443
6444 r_distances.resize(verts.size());
6445 const MutableSpan<float> distances = r_distances;
6446 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
6447 filter_distances_with_radius(cache.radius, distances, factors);
6448 apply_hardness_to_distances(cache, distances);
6449 calc_brush_strength_factors(cache, brush, distances, factors);
6450
6451 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
6452
6453 calc_brush_texture_factors(ss, brush, positions, factors);
6454}
6455
6457 const Span<int> verts,
6458 const MutableSpan<float> r_factors)
6459{
6460 BLI_assert(verts.size() == r_factors.size());
6461
6462 if (!hide_vert.is_empty()) {
6463 for (const int i : verts.index_range()) {
6464 r_factors[i] = hide_vert[verts[i]] ? 0.0f : 1.0f;
6465 }
6466 }
6467 else {
6468 r_factors.fill(1.0f);
6469 }
6470}
6471
6472void fill_factor_from_hide(const SubdivCCG &subdiv_ccg,
6473 const Span<int> grids,
6474 const MutableSpan<float> r_factors)
6475{
6476 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
6477 BLI_assert(grids.size() * key.grid_area == r_factors.size());
6478
6479 const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
6480 if (grid_hidden.is_empty()) {
6481 r_factors.fill(1.0f);
6482 return;
6483 }
6484 for (const int i : grids.index_range()) {
6485 const BitSpan hidden = grid_hidden[grids[i]];
6486 const int start = i * key.grid_area;
6487 for (const int offset : IndexRange(key.grid_area)) {
6488 r_factors[start + offset] = hidden[offset] ? 0.0f : 1.0f;
6489 }
6490 }
6491}
6492
6494{
6495 BLI_assert(verts.size() == r_factors.size());
6496
6497 int i = 0;
6498 for (const BMVert *vert : verts) {
6499 r_factors[i] = BM_elem_flag_test_bool(vert, BM_ELEM_HIDDEN) ? 0.0f : 1.0f;
6500 i++;
6501 }
6502}
6503
6505 const Span<float> mask,
6506 const Span<int> verts,
6507 const MutableSpan<float> r_factors)
6508{
6509 BLI_assert(verts.size() == r_factors.size());
6510
6511 if (!mask.is_empty()) {
6512 for (const int i : verts.index_range()) {
6513 r_factors[i] = 1.0f - mask[verts[i]];
6514 }
6515 }
6516 else {
6517 r_factors.fill(1.0f);
6518 }
6519
6520 if (!hide_vert.is_empty()) {
6521 for (const int i : verts.index_range()) {
6522 if (hide_vert[verts[i]]) {
6523 r_factors[i] = 0.0f;
6524 }
6525 }
6526 }
6527}
6528
6530 const Set<BMVert *, 0> &verts,
6531 const MutableSpan<float> r_factors)
6532{
6533 BLI_assert(verts.size() == r_factors.size());
6534
6535 /* TODO: Avoid overhead of accessing attributes for every bke::pbvh::Tree node. */
6536 const int mask_offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask");
6537 int i = 0;
6538 for (const BMVert *vert : verts) {
6539 r_factors[i] = (mask_offset == -1) ? 1.0f : 1.0f - BM_ELEM_CD_GET_FLOAT(vert, mask_offset);
6540 if (BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
6541 r_factors[i] = 0.0f;
6542 }
6543 i++;
6544 }
6545}
6546
6548 const Span<int> grids,
6549 const MutableSpan<float> r_factors)
6550{
6551 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
6552 BLI_assert(grids.size() * key.grid_area == r_factors.size());
6553
6554 if (!subdiv_ccg.masks.is_empty()) {
6555 const Span<float> masks = subdiv_ccg.masks;
6556 for (const int i : grids.index_range()) {
6557 const Span src = masks.slice(bke::ccg::grid_range(key, grids[i]));
6558 MutableSpan dst = r_factors.slice(bke::ccg::grid_range(key, i));
6559 for (const int offset : dst.index_range()) {
6560 dst[offset] = 1.0f - src[offset];
6561 }
6562 }
6563 }
6564 else {
6565 r_factors.fill(1.0f);
6566 }
6567
6568 const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
6569 if (!grid_hidden.is_empty()) {
6570 for (const int i : grids.index_range()) {
6571 const BitSpan hidden = grid_hidden[grids[i]];
6572 const int start = i * key.grid_area;
6573 for (const int offset : IndexRange(key.grid_area)) {
6574 if (hidden[offset]) {
6575 r_factors[start + offset] = 0.0f;
6576 }
6577 }
6578 }
6579 }
6580}
6581
6582void calc_front_face(const float3 &view_normal,
6583 const Span<float3> vert_normals,
6584 const Span<int> verts,
6585 const MutableSpan<float> factors)
6586{
6587 BLI_assert(verts.size() == factors.size());
6588
6589 for (const int i : verts.index_range()) {
6590 const float dot = math::dot(view_normal, vert_normals[verts[i]]);
6591 factors[i] *= std::max(dot, 0.0f);
6592 }
6593}
6594
6595void calc_front_face(const float3 &view_normal,
6596 const Span<float3> normals,
6597 const MutableSpan<float> factors)
6598{
6599 BLI_assert(normals.size() == factors.size());
6600
6601 for (const int i : normals.index_range()) {
6602 const float dot = math::dot(view_normal, normals[i]);
6603 factors[i] *= std::max(dot, 0.0f);
6604 }
6605}
6606void calc_front_face(const float3 &view_normal,
6607 const SubdivCCG &subdiv_ccg,
6608 const Span<int> grids,
6609 const MutableSpan<float> factors)
6610{
6611 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
6612 const Span<float3> normals = subdiv_ccg.normals;
6613 BLI_assert(grids.size() * key.grid_area == factors.size());
6614
6615 for (const int i : grids.index_range()) {
6616 const Span<float3> grid_normals = normals.slice(bke::ccg::grid_range(key, grids[i]));
6617 MutableSpan<float> grid_factors = factors.slice(bke::ccg::grid_range(key, i));
6618 for (const int offset : grid_factors.index_range()) {
6619 const float dot = math::dot(view_normal, grid_normals[offset]);
6620 grid_factors[offset] *= std::max(dot, 0.0f);
6621 }
6622 }
6623}
6624
6625void calc_front_face(const float3 &view_normal,
6626 const Set<BMVert *, 0> &verts,
6627 const MutableSpan<float> factors)
6628{
6629 BLI_assert(verts.size() == factors.size());
6630
6631 int i = 0;
6632 for (const BMVert *vert : verts) {
6633 const float dot = math::dot(view_normal, float3(vert->no));
6634 factors[i] *= std::max(dot, 0.0f);
6635 i++;
6636 }
6637}
6638
6639void calc_front_face(const float3 &view_normal,
6640 const Set<BMFace *, 0> &faces,
6641 const MutableSpan<float> factors)
6642{
6643 BLI_assert(faces.size() == factors.size());
6644
6645 int i = 0;
6646 for (const BMFace *face : faces) {
6647 const float dot = math::dot(view_normal, float3(face->no));
6648 factors[i] *= std::max(dot, 0.0f);
6649 i++;
6650 }
6651}
6652
6654 const Span<float3> positions,
6655 const Span<int> verts,
6656 const MutableSpan<float> factors)
6657{
6658 BLI_assert(verts.size() == factors.size());
6659
6660 const RegionView3D *rv3d = ss.cache ? ss.cache->vc->rv3d : ss.rv3d;
6661 const View3D *v3d = ss.cache ? ss.cache->vc->v3d : ss.v3d;
6662 if (!RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
6663 return;
6664 }
6665
6666 const ePaintSymmetryFlags mirror_symmetry_pass = ss.cache ? ss.cache->mirror_symmetry_pass :
6668 const int radial_symmetry_pass = ss.cache ? ss.cache->radial_symmetry_pass : 0;
6669 const float4x4 symm_rot_mat_inv = ss.cache ? ss.cache->symm_rot_mat_inv : float4x4::identity();
6670 for (const int i : verts.index_range()) {
6671 float3 symm_co = symmetry_flip(positions[verts[i]], mirror_symmetry_pass);
6672 if (radial_symmetry_pass) {
6673 symm_co = math::transform_point(symm_rot_mat_inv, symm_co);
6674 }
6675 if (ED_view3d_clipping_test(rv3d, symm_co, true)) {
6676 factors[i] = 0.0f;
6677 }
6678 }
6679}
6680
6682 const Span<float3> positions,
6683 const MutableSpan<float> factors)
6684{
6685 BLI_assert(positions.size() == factors.size());
6686
6687 const RegionView3D *rv3d = ss.cache ? ss.cache->vc->rv3d : ss.rv3d;
6688 const View3D *v3d = ss.cache ? ss.cache->vc->v3d : ss.v3d;
6689 if (!RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
6690 return;
6691 }
6692
6693 const ePaintSymmetryFlags mirror_symmetry_pass = ss.cache ? ss.cache->mirror_symmetry_pass :
6695 const int radial_symmetry_pass = ss.cache ? ss.cache->radial_symmetry_pass : 0;
6696 const float4x4 symm_rot_mat_inv = ss.cache ? ss.cache->symm_rot_mat_inv : float4x4::identity();
6697 for (const int i : positions.index_range()) {
6698 float3 symm_co = symmetry_flip(positions[i], mirror_symmetry_pass);
6699 if (radial_symmetry_pass) {
6700 symm_co = math::transform_point(symm_rot_mat_inv, symm_co);
6701 }
6702 if (ED_view3d_clipping_test(rv3d, symm_co, true)) {
6703 factors[i] = 0.0f;
6704 }
6705 }
6706}
6707
6709 const Span<float3> positions,
6710 const Span<int> verts,
6711 const eBrushFalloffShape falloff_shape,
6712 const MutableSpan<float> r_distances)
6713{
6714 BLI_assert(verts.size() == r_distances.size());
6715
6716 const float3 &test_location = ss.cache ? ss.cache->location_symm : ss.cursor_location;
6717 if (falloff_shape == PAINT_FALLOFF_SHAPE_TUBE && (ss.cache || ss.filter_cache)) {
6718 /* The tube falloff shape requires the cached view normal. */
6719 const float3 &view_normal = ss.cache ? ss.cache->view_normal_symm :
6721 float4 test_plane;
6722 plane_from_point_normal_v3(test_plane, test_location, view_normal);
6723 for (const int i : verts.index_range()) {
6724 float3 projected;
6725 closest_to_plane_normalized_v3(projected, test_plane, positions[verts[i]]);
6726 r_distances[i] = math::distance_squared(projected, test_location);
6727 }
6728 }
6729 else {
6730 for (const int i : verts.index_range()) {
6731 r_distances[i] = math::distance_squared(test_location, positions[verts[i]]);
6732 }
6733 }
6734}
6735
6737 const Span<float3> positions,
6738 const Span<int> verts,
6739 const eBrushFalloffShape falloff_shape,
6740 const MutableSpan<float> r_distances)
6741{
6742 calc_brush_distances_squared(ss, positions, verts, falloff_shape, r_distances);
6743 for (float &value : r_distances) {
6744 value = std::sqrt(value);
6745 }
6746}
6747
6749 const Span<float3> positions,
6750 const eBrushFalloffShape falloff_shape,
6751 const MutableSpan<float> r_distances)
6752{
6753 BLI_assert(positions.size() == r_distances.size());
6754
6755 const float3 &test_location = ss.cache ? ss.cache->location_symm : ss.cursor_location;
6756 if (falloff_shape == PAINT_FALLOFF_SHAPE_TUBE && (ss.cache || ss.filter_cache)) {
6757 /* The tube falloff shape requires the cached view normal. */
6758 const float3 &view_normal = ss.cache ? ss.cache->view_normal_symm :
6760 float4 test_plane;
6761 plane_from_point_normal_v3(test_plane, test_location, view_normal);
6762 for (const int i : positions.index_range()) {
6763 float3 projected;
6764 closest_to_plane_normalized_v3(projected, test_plane, positions[i]);
6765 r_distances[i] = math::distance_squared(projected, test_location);
6766 }
6767 }
6768 else {
6769 for (const int i : positions.index_range()) {
6770 r_distances[i] = math::distance_squared(test_location, positions[i]);
6771 }
6772 }
6773}
6774
6776 const Span<float3> positions,
6777 const eBrushFalloffShape falloff_shape,
6778 const MutableSpan<float> r_distances)
6779{
6780 calc_brush_distances_squared(ss, positions, falloff_shape, r_distances);
6781 for (float &value : r_distances) {
6782 value = std::sqrt(value);
6783 }
6784}
6785
6786void filter_distances_with_radius(const float radius,
6787 const Span<float> distances,
6788 const MutableSpan<float> factors)
6789{
6790 for (const int i : distances.index_range()) {
6791 if (distances[i] >= radius) {
6792 factors[i] = 0.0f;
6793 }
6794 }
6795}
6796
6798 const float4x4 &mat,
6799 const Span<float3> positions,
6800 const Span<int> verts,
6801 const MutableSpan<float> r_distances,
6802 const MutableSpan<float> factors)
6803{
6804 BLI_assert(verts.size() == factors.size());
6805 BLI_assert(verts.size() == r_distances.size());
6806
6807 const float roundness = brush.tip_roundness;
6808 const float hardness = 1.0f - roundness;
6809 for (const int i : verts.index_range()) {
6810 if (factors[i] == 0.0f) {
6811 r_distances[i] = std::numeric_limits<float>::max();
6812 continue;
6813 }
6814 const float3 local = math::abs(math::transform_point(mat, positions[verts[i]]));
6815
6816 if (!(local.x <= 1.0f && local.y <= 1.0f && local.z <= 1.0f)) {
6817 factors[i] = 0.0f;
6818 r_distances[i] = std::numeric_limits<float>::max();
6819 continue;
6820 }
6821 if (std::min(local.x, local.y) > hardness) {
6822 /* Corner, distance to the center of the corner circle. */
6823 r_distances[i] = math::distance(float2(hardness), float2(local)) / roundness;
6824 continue;
6825 }
6826 if (std::max(local.x, local.y) > hardness) {
6827 /* Side, distance to the square XY axis. */
6828 r_distances[i] = (std::max(local.x, local.y) - hardness) / roundness;
6829 continue;
6830 }
6831
6832 /* Inside the square, constant distance. */
6833 r_distances[i] = 0.0f;
6834 }
6835}
6836
6838 const float4x4 &mat,
6839 const Span<float3> positions,
6840 const MutableSpan<float> r_distances,
6841 const MutableSpan<float> factors)
6842{
6843 BLI_assert(positions.size() == factors.size());
6844 BLI_assert(positions.size() == r_distances.size());
6845
6846 const float roundness = brush.tip_roundness;
6847 const float hardness = 1.0f - roundness;
6848 for (const int i : positions.index_range()) {
6849 if (factors[i] == 0.0f) {
6850 r_distances[i] = std::numeric_limits<float>::max();
6851 continue;
6852 }
6853 const float3 local = math::abs(math::transform_point(mat, positions[i]));
6854
6855 if (!(local.x <= 1.0f && local.y <= 1.0f && local.z <= 1.0f)) {
6856 factors[i] = 0.0f;
6857 r_distances[i] = std::numeric_limits<float>::max();
6858 continue;
6859 }
6860 if (std::min(local.x, local.y) > hardness) {
6861 /* Corner, distance to the center of the corner circle. */
6862 r_distances[i] = math::distance(float2(hardness), float2(local)) / roundness;
6863 continue;
6864 }
6865 if (std::max(local.x, local.y) > hardness) {
6866 /* Side, distance to the square XY axis. */
6867 r_distances[i] = (std::max(local.x, local.y) - hardness) / roundness;
6868 continue;
6869 }
6870
6871 /* Inside the square, constant distance. */
6872 r_distances[i] = 0.0f;
6873 }
6874}
6875
6876void apply_hardness_to_distances(const float radius,
6877 const float hardness,
6878 const MutableSpan<float> distances)
6879{
6880 if (hardness == 0.0f) {
6881 return;
6882 }
6883 const float threshold = hardness * radius;
6884 if (hardness == 1.0f) {
6885 for (const int i : distances.index_range()) {
6886 distances[i] = distances[i] < threshold ? 0.0f : radius;
6887 }
6888 return;
6889 }
6890 const float radius_inv = math::rcp(radius);
6891 const float hardness_inv_rcp = math::rcp(1.0f - hardness);
6892 for (const int i : distances.index_range()) {
6893 if (distances[i] < threshold) {
6894 distances[i] = 0.0f;
6895 }
6896 else {
6897 const float radius_factor = (distances[i] * radius_inv - hardness) * hardness_inv_rcp;
6898 distances[i] = radius_factor * radius;
6899 }
6900 }
6901}
6902
6904 const Brush &brush,
6905 const Span<float> distances,
6906 const MutableSpan<float> factors)
6907{
6909 eBrushCurvePreset(brush.curve_preset), brush.curve, distances, cache.radius, factors);
6910}
6911
6913 const Brush &brush,
6914 const Span<float3> vert_positions,
6915 const Span<int> verts,
6916 const MutableSpan<float> factors)
6917{
6918 BLI_assert(verts.size() == factors.size());
6919
6920 const int thread_id = BLI_task_parallel_thread_id(nullptr);
6921 const MTex *mtex = BKE_brush_mask_texture_get(&brush, OB_MODE_SCULPT);
6922 if (!mtex->tex) {
6923 return;
6924 }
6925
6926 for (const int i : verts.index_range()) {
6927 if (factors[i] == 0.0f) {
6928 continue;
6929 }
6930 float texture_value;
6931 float4 texture_rgba;
6932 /* NOTE: This is not a thread-safe call. */
6934 ss, brush, vert_positions[verts[i]], thread_id, &texture_value, texture_rgba);
6935
6936 factors[i] *= texture_value;
6937 }
6938}
6939
6941 const Brush &brush,
6942 const Span<float3> positions,
6943 const MutableSpan<float> factors)
6944{
6945 BLI_assert(positions.size() == factors.size());
6946
6947 const int thread_id = BLI_task_parallel_thread_id(nullptr);
6948 const MTex *mtex = BKE_brush_mask_texture_get(&brush, OB_MODE_SCULPT);
6949 if (!mtex->tex) {
6950 return;
6951 }
6952
6953 for (const int i : positions.index_range()) {
6954 if (factors[i] == 0.0f) {
6955 continue;
6956 }
6957 float texture_value;
6958 float4 texture_rgba;
6959 /* NOTE: This is not a thread-safe call. */
6960 sculpt_apply_texture(ss, brush, positions[i], thread_id, &texture_value, texture_rgba);
6961
6962 factors[i] *= texture_value;
6963 }
6964}
6965
6967 const Span<float3> positions,
6968 const Span<float3> orig_positions)
6969{
6970 BLI_assert(translations.size() == orig_positions.size());
6971 BLI_assert(translations.size() == positions.size());
6972 for (const int i : translations.index_range()) {
6973 const float3 prev_translation = positions[i] - orig_positions[i];
6974 translations[i] -= prev_translation;
6975 }
6976}
6977
6978void apply_translations(const Span<float3> translations,
6979 const Span<int> verts,
6980 const MutableSpan<float3> positions)
6981{
6982 BLI_assert(verts.size() == translations.size());
6983
6984 for (const int i : verts.index_range()) {
6985 const int vert = verts[i];
6986 positions[vert] += translations[i];
6987 }
6988}
6989
6990void apply_translations(const Span<float3> translations,
6991 const Span<int> grids,
6992 SubdivCCG &subdiv_ccg)
6993{
6994 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
6995 MutableSpan<float3> positions = subdiv_ccg.positions;
6996 BLI_assert(grids.size() * key.grid_area == translations.size());
6997
6998 for (const int i : grids.index_range()) {
6999 const Span<float3> grid_translations = translations.slice(bke::ccg::grid_range(key, i));
7000 MutableSpan<float3> grid_positions = positions.slice(bke::ccg::grid_range(key, grids[i]));
7001 for (const int offset : grid_positions.index_range()) {
7002 grid_positions[offset] += grid_translations[offset];
7003 }
7004 }
7005}
7006
7008{
7009 BLI_assert(verts.size() == translations.size());
7010
7011 int i = 0;
7012 for (BMVert *vert : verts) {
7013 add_v3_v3(vert->co, translations[i]);
7014 i++;
7015 }
7016}
7017
7018void project_translations(const MutableSpan<float3> translations, const float3 &plane)
7019{
7020 /* Equivalent to #project_plane_v3_v3v3. */
7021 const float len_sq = math::length_squared(plane);
7022 if (len_sq < std::numeric_limits<float>::epsilon()) {
7023 return;
7024 }
7025 const float dot_factor = -math::rcp(len_sq);
7026 for (const int i : translations.index_range()) {
7027 translations[i] += plane * math::dot(translations[i], plane) * dot_factor;
7028 }
7029}
7030
7032 const Span<int> verts,
7033 const MutableSpan<float3> translations)
7034{
7035 BLI_assert(verts.size() == translations.size());
7036
7037 for (const int i : verts.index_range()) {
7038 translations[i] = math::transform_point(deform_imats[verts[i]], translations[i]);
7039 }
7040}
7041
7043 const SculptSession &ss,
7044 const Span<float3> positions,
7045 const Span<int> verts,
7046 const MutableSpan<float3> translations)
7047{
7048 BLI_assert(verts.size() == translations.size());
7049
7050 const StrokeCache *cache = ss.cache;
7051 if (!cache) {
7052 return;
7053 }
7054 for (const int axis : IndexRange(3)) {
7055 if (sd.flags & (SCULPT_LOCK_X << axis)) {
7056 for (float3 &translation : translations) {
7057 translation[axis] = 0.0f;
7058 }
7059 continue;
7060 }
7061
7062 if (!(cache->mirror_modifier_clip.flag & (uint8_t(StrokeFlags::ClipX) << axis))) {
7063 continue;
7064 }
7065
7066 const float4x4 mirror(cache->mirror_modifier_clip.mat);
7067 const float4x4 mirror_inverse(cache->mirror_modifier_clip.mat_inv);
7068 for (const int i : verts.index_range()) {
7069 const int vert = verts[i];
7070
7071 /* Transform into the space of the mirror plane, check translations, then transform back. */
7072 float3 co_mirror = math::transform_point(mirror, positions[vert]);
7073 if (math::abs(co_mirror[axis]) > cache->mirror_modifier_clip.tolerance[axis]) {
7074 continue;
7075 }
7076 /* Clear the translation in the local space of the mirror object. */
7077 co_mirror[axis] = 0.0f;
7078 const float3 co_local = math::transform_point(mirror_inverse, co_mirror);
7079 translations[i][axis] = co_local[axis] - positions[vert][axis];
7080 }
7081 }
7082}
7083
7085 const SculptSession &ss,
7086 const Span<float3> positions,
7087 const MutableSpan<float3> translations)
7088{
7089 BLI_assert(positions.size() == translations.size());
7090
7091 const StrokeCache *cache = ss.cache;
7092 if (!cache) {
7093 return;
7094 }
7095 for (const int axis : IndexRange(3)) {
7096 if (sd.flags & (SCULPT_LOCK_X << axis)) {
7097 for (float3 &translation : translations) {
7098 translation[axis] = 0.0f;
7099 }
7100 continue;
7101 }
7102
7103 if (!(cache->mirror_modifier_clip.flag & (uint8_t(StrokeFlags::ClipX) << axis))) {
7104 continue;
7105 }
7106
7107 const float4x4 mirror(cache->mirror_modifier_clip.mat);
7108 const float4x4 mirror_inverse(cache->mirror_modifier_clip.mat_inv);
7109 for (const int i : positions.index_range()) {
7110 /* Transform into the space of the mirror plane, check translations, then transform back. */
7111 float3 co_mirror = math::transform_point(mirror, positions[i]);
7112 if (math::abs(co_mirror[axis]) > cache->mirror_modifier_clip.tolerance[axis]) {
7113 continue;
7114 }
7115 /* Clear the translation in the local space of the mirror object. */
7116 co_mirror[axis] = 0.0f;
7117 const float3 co_local = math::transform_point(mirror_inverse, co_mirror);
7118 translations[i][axis] = co_local[axis] - positions[i][axis];
7119 }
7120 }
7121}
7122
7124{
7125 Mesh &mesh = *static_cast<Mesh *>(object_orig.data);
7126 this->eval = bke::pbvh::vert_positions_eval(depsgraph, object_orig);
7127
7128 if (!object_orig.sculpt->deform_imats.is_empty()) {
7129 deform_imats_ = object_orig.sculpt->deform_imats;
7130 }
7131 orig_ = mesh.vert_positions_for_write();
7132
7134 if (eval_mut.data() != orig_.data()) {
7135 eval_mut_ = eval_mut;
7136 }
7137
7138 if (Key *keys = mesh.key) {
7139 keys_ = keys;
7140 const int active_index = object_orig.shapenr - 1;
7141 active_key_ = BKE_keyblock_find_by_index(keys, active_index);
7142 basis_active_ = active_key_ == keys->refkey;
7143 dependent_keys_ = BKE_keyblock_get_dependent_keys(keys_, active_index);
7144 }
7145 else {
7146 keys_ = nullptr;
7147 active_key_ = nullptr;
7148 basis_active_ = false;
7149 }
7150}
7151
7153{
7154 for (const int i : indices) {
7155 dst[i] = src[i];
7156 }
7157}
7158
7160{
7161 if (eval_mut_) {
7162 /* Apply translations to the evaluated mesh. This is necessary because multiple brush
7163 * evaluations can happen in between object reevaluations (otherwise just deforming the
7164 * original positions would be enough). */
7165 apply_translations(translations, verts, *eval_mut_);
7166 }
7167
7168 if (deform_imats_) {
7169 /* Apply the reverse procedural deformation, since subsequent translation happens to the state
7170 * from "before" deforming modifiers. */
7171 apply_crazyspace_to_translations(*deform_imats_, verts, translations);
7172 }
7173
7174 if (KeyBlock *key = active_key_) {
7175 const MutableSpan active_key_data(static_cast<float3 *>(key->data), key->totelem);
7176 if (basis_active_) {
7177 /* The active shape key positions and the mesh positions are always kept in sync. */
7178 apply_translations(translations, verts, orig_);
7179 copy_indices(orig_, verts, active_key_data);
7180 }
7181 else {
7182 apply_translations(translations, verts, active_key_data);
7183 }
7184
7185 if (dependent_keys_) {
7186 int i;
7187 LISTBASE_FOREACH_INDEX (KeyBlock *, other_key, &keys_->block, i) {
7188 if ((other_key != key) && (*dependent_keys_)[i]) {
7189 MutableSpan data(static_cast<float3 *>(other_key->data), other_key->totelem);
7190 apply_translations(translations, verts, data);
7191 }
7192 }
7193 }
7194 }
7195 else {
7196 apply_translations(translations, verts, orig_);
7197 }
7198}
7199
7201 const Mesh &mesh,
7202 const KeyBlock &active_key,
7203 const Span<int> verts,
7204 const Span<float3> translations,
7205 const Span<float3> positions_orig)
7206{
7207 const MutableSpan active_key_data(static_cast<float3 *>(active_key.data), active_key.totelem);
7208 if (&active_key == mesh.key->refkey) {
7209 for (const int vert : verts) {
7210 active_key_data[vert] = positions_orig[vert];
7211 }
7212 }
7213 else {
7214 apply_translations(translations, verts, active_key_data);
7215 }
7216
7217 if (std::optional<Array<bool>> dependent = BKE_keyblock_get_dependent_keys(mesh.key,
7218 object.shapenr - 1))
7219 {
7220 int i;
7221 LISTBASE_FOREACH_INDEX (KeyBlock *, other_key, &mesh.key->block, i) {
7222 if ((other_key != &active_key) && (*dependent)[i]) {
7223 MutableSpan<float3> data(static_cast<float3 *>(other_key->data), other_key->totelem);
7224 apply_translations(translations, verts, data);
7225 }
7226 }
7227 }
7228}
7229
7230void scale_translations(const MutableSpan<float3> translations, const Span<float> factors)
7231{
7232 for (const int i : translations.index_range()) {
7233 translations[i] *= factors[i];
7234 }
7235}
7236
7237void scale_translations(const MutableSpan<float3> translations, const float factor)
7238{
7239 if (factor == 1.0f) {
7240 return;
7241 }
7242 for (const int i : translations.index_range()) {
7243 translations[i] *= factor;
7244 }
7245}
7246
7247void scale_factors(const MutableSpan<float> factors, const float strength)
7248{
7249 if (strength == 1.0f) {
7250 return;
7251 }
7252 for (float &factor : factors) {
7253 factor *= strength;
7254 }
7255}
7256
7257void scale_factors(const MutableSpan<float> factors, const Span<float> strengths)
7258{
7259 BLI_assert(factors.size() == strengths.size());
7260
7261 for (const int i : factors.index_range()) {
7262 factors[i] *= strengths[i];
7263 }
7264}
7265
7267 const Span<float> factors,
7268 const MutableSpan<float3> r_translations)
7269{
7270 BLI_assert(r_translations.size() == factors.size());
7271
7272 for (const int i : factors.index_range()) {
7273 r_translations[i] = offset * factors[i];
7274 }
7275}
7276
7278 const Span<int> verts,
7279 const Span<float3> old_positions,
7280 const MutableSpan<float3> translations)
7281{
7282 BLI_assert(new_positions.size() == verts.size());
7283 for (const int i : verts.index_range()) {
7284 translations[i] = new_positions[i] - old_positions[verts[i]];
7285 }
7286}
7287
7289 const Span<float3> old_positions,
7290 const MutableSpan<float3> translations)
7291{
7292 BLI_assert(new_positions.size() == old_positions.size());
7293 for (const int i : new_positions.index_range()) {
7294 translations[i] = new_positions[i] - old_positions[i];
7295 }
7296}
7297
7299 const float4x4 &transform,
7300 const MutableSpan<float3> dst)
7301{
7302 BLI_assert(src.size() == dst.size());
7303
7304 for (const int i : src.index_range()) {
7305 dst[i] = math::transform_point(transform, src[i]);
7306 }
7307}
7308
7310{
7311 for (const int i : positions.index_range()) {
7312 positions[i] = math::transform_point(transform, positions[i]);
7313 }
7314}
7315
7317 const IndexMask &node_mask,
7318 Array<int> &node_data)
7319{
7320 node_data.reinitialize(node_mask.size() + 1);
7321 node_mask.foreach_index(
7322 [&](const int i, const int pos) { node_data[pos] = nodes[i].verts().size(); });
7324}
7325
7328 const IndexMask &node_mask,
7329 Array<int> &node_data)
7330{
7331 node_data.reinitialize(node_mask.size() + 1);
7332 node_mask.foreach_index([&](const int i, const int pos) {
7333 node_data[pos] = nodes[i].grids().size() * key.grid_area;
7334 });
7336}
7337
7339 const IndexMask &node_mask,
7340 Array<int> &node_data)
7341{
7342 node_data.reinitialize(node_mask.size() + 1);
7343 node_mask.foreach_index([&](const int i, const int pos) {
7344 node_data[pos] =
7346 });
7348}
7349
7351 const Span<int> corner_verts,
7352 const GroupedSpan<int> vert_to_face,
7353 const Span<bool> hide_poly,
7354 const Span<int> verts,
7356{
7357 BLI_assert(result.size() == verts.size());
7358 BLI_assert(corner_verts.size() == faces.total_size());
7359 for (const int i : verts.index_range()) {
7360 vert_neighbors_get_mesh(faces, corner_verts, vert_to_face, hide_poly, verts[i], result[i]);
7361 }
7362}
7363
7364void calc_vert_neighbors(const SubdivCCG &subdiv_ccg,
7365 const Span<int> grids,
7367{
7368 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
7369 SubdivCCGNeighbors neighbors;
7370 BLI_assert(result.size() == grids.size() * key.grid_area);
7371 for (const int i : grids.index_range()) {
7372 const int grid = grids[i];
7373 const int node_verts_start = i * key.grid_area;
7374
7375 for (const int y : IndexRange(key.grid_size)) {
7376 for (const int x : IndexRange(key.grid_size)) {
7377 const int offset = CCG_grid_xy_to_index(key.grid_size, x, y);
7378 const int node_vert_index = node_verts_start + offset;
7379
7380 SubdivCCGCoord coord{};
7381 coord.grid_index = grid;
7382 coord.x = x;
7383 coord.y = y;
7384
7385 BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, false, neighbors);
7386
7387 result[node_vert_index] = Vector<SubdivCCGCoord>(neighbors.coords.as_span());
7388 }
7389 }
7390 }
7391}
7393{
7394 BLI_assert(verts.size() == result.size());
7395
7396 int i = 0;
7397 Vector<BMVert *, 64> neighbor_data;
7398 for (BMVert *vert : verts) {
7399 Span<BMVert *> neighbors = vert_neighbors_get_bmesh(*vert, neighbor_data);
7400 result[i] = Vector<BMVert *>(neighbors);
7401 i++;
7402 }
7403}
7404
7406 const Span<int> corner_verts,
7407 const GroupedSpan<int> vert_to_face,
7408 const BitSpan boundary_verts,
7409 const Span<bool> hide_poly,
7410 const Span<int> verts,
7412{
7413 BLI_assert(result.size() == verts.size());
7414 BLI_assert(corner_verts.size() == faces.total_size());
7415
7416 for (const int i : verts.index_range()) {
7417 const int vert = verts[i];
7418 Vector<int> &neighbors = result[i];
7419 vert_neighbors_get_mesh(faces, corner_verts, vert_to_face, hide_poly, verts[i], neighbors);
7420
7421 if (boundary_verts[vert]) {
7422 if (neighbors.size() == 2) {
7423 /* Do not include neighbors of corner vertices. */
7424 neighbors.clear();
7425 }
7426 else {
7427 /* Only include other boundary vertices as neighbors of boundary vertices. */
7428 neighbors.remove_if([&](const int vert) { return !boundary_verts[vert]; });
7429 }
7430 }
7431 }
7432}
7433
7435 const Span<int> corner_verts,
7436 const BitSpan boundary_verts,
7437 const SubdivCCG &subdiv_ccg,
7438 const Span<int> grids,
7440{
7441 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
7442
7443 BLI_assert(grids.size() * key.grid_area == result.size());
7444
7445 for (const int i : grids.index_range()) {
7446 const int grid = grids[i];
7447 const int node_verts_start = i * key.grid_area;
7448
7449 /* TODO: This loop could be optimized in the future by skipping unnecessary logic for
7450 * non-boundary grid vertices. */
7451 for (const int y : IndexRange(key.grid_size)) {
7452 for (const int x : IndexRange(key.grid_size)) {
7453 const int offset = CCG_grid_xy_to_index(key.grid_size, x, y);
7454 const int node_vert_index = node_verts_start + offset;
7455
7456 SubdivCCGCoord coord{};
7457 coord.grid_index = grid;
7458 coord.x = x;
7459 coord.y = y;
7460
7461 SubdivCCGNeighbors neighbors;
7462 BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, false, neighbors);
7463
7465 faces, corner_verts, boundary_verts, subdiv_ccg, coord))
7466 {
7467 if (neighbors.coords.size() == 2) {
7468 /* Do not include neighbors of corner vertices. */
7469 neighbors.coords.clear();
7470 }
7471 else {
7472 /* Only include other boundary vertices as neighbors of boundary vertices. */
7473 neighbors.coords.remove_if([&](const SubdivCCGCoord coord) {
7475 faces, corner_verts, boundary_verts, subdiv_ccg, coord);
7476 });
7477 }
7478 }
7479 result[node_vert_index] = neighbors.coords;
7480 }
7481 }
7482 }
7483}
7484
7487{
7488 BLI_assert(verts.size() == result.size());
7489 Vector<BMVert *, 64> neighbor_data;
7490
7491 int i = 0;
7492 for (BMVert *vert : verts) {
7493 vert_neighbors_get_interior_bmesh(*vert, neighbor_data);
7494 result[i] = neighbor_data;
7495 i++;
7496 }
7497}
7498
7500 const Span<int> verts,
7501 const float4 &plane,
7502 const MutableSpan<float3> translations)
7503{
7504 for (const int i : verts.index_range()) {
7505 const float3 &position = vert_positions[verts[i]];
7507 closest_to_plane_normalized_v3(closest, plane, position);
7508 translations[i] = closest - position;
7509 }
7510}
7511
7513 const float4 &plane,
7514 const MutableSpan<float3> translations)
7515{
7516 for (const int i : positions.index_range()) {
7517 const float3 &position = positions[i];
7519 closest_to_plane_normalized_v3(closest, plane, position);
7520 translations[i] = closest - position;
7521 }
7522}
7523
7525 const float3 &pivot,
7526 const ePaintSymmetryFlags symm,
7527 const MutableSpan<float> factors)
7528{
7529 BLI_assert(positions.size() == factors.size());
7530
7531 for (const int i : positions.index_range()) {
7532 if (!SCULPT_check_vertex_pivot_symmetry(positions[i], pivot, symm)) {
7533 factors[i] = 0.0f;
7534 }
7535 }
7536}
7537
7539 const StrokeCache &cache,
7540 const Span<float3> translations,
7541 const MutableSpan<float> factors)
7542{
7543 if (!(brush.flag & BRUSH_PLANE_TRIM)) {
7544 return;
7545 }
7546 const float threshold = cache.radius_squared * cache.plane_trim_squared;
7547 for (const int i : translations.index_range()) {
7548 if (math::length_squared(translations[i]) > threshold) {
7549 factors[i] = 0.0f;
7550 }
7551 }
7552}
7553
7555 const Span<int> verts,
7556 const float4 &plane,
7557 const MutableSpan<float> factors)
7558{
7559 for (const int i : verts.index_range()) {
7560 if (plane_point_side_v3(plane, vert_positions[verts[i]]) <= 0.0f) {
7561 factors[i] = 0.0f;
7562 }
7563 }
7564}
7565
7567 const float4 &plane,
7568 const MutableSpan<float> factors)
7569{
7570 for (const int i : positions.index_range()) {
7571 if (plane_point_side_v3(plane, positions[i]) <= 0.0f) {
7572 factors[i] = 0.0f;
7573 }
7574 }
7575}
7576
7578 const Span<int> verts,
7579 const float4 &plane,
7580 const MutableSpan<float> factors)
7581{
7582 for (const int i : verts.index_range()) {
7583 if (plane_point_side_v3(plane, vert_positions[verts[i]]) > 0.0f) {
7584 factors[i] = 0.0f;
7585 }
7586 }
7587}
7588
7590 const float4 &plane,
7591 const MutableSpan<float> factors)
7592{
7593 for (const int i : positions.index_range()) {
7594 if (plane_point_side_v3(plane, positions[i]) > 0.0f) {
7595 factors[i] = 0.0f;
7596 }
7597 }
7598}
7599
7600} // namespace blender::ed::sculpt_paint
const MTex * BKE_brush_mask_texture_get(const Brush *brush, const eObjectMode object_mode)
Definition brush.cc:762
bool BKE_brush_use_alpha_pressure(const Brush *brush)
Definition brush.cc:1096
float BKE_brush_unprojected_radius_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1133
int BKE_brush_size_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1075
void BKE_brush_unprojected_radius_set(Scene *scene, Brush *brush, float unprojected_radius)
Definition brush.cc:1120
void BKE_brush_size_set(Scene *scene, Brush *brush, int size)
Definition brush.cc:1059
float BKE_brush_sample_tex_3d(const Scene *scene, const Brush *br, const MTex *mtex, const float point[3], float rgba[4], int thread, ImagePool *pool)
Definition brush.cc:778
bool BKE_brush_use_size_pressure(const Brush *brush)
Definition brush.cc:1091
bool BKE_brush_has_cube_tip(const Brush *brush, PaintMode paint_mode)
Definition brush.cc:1514
float BKE_brush_alpha_get(const Scene *scene, const Brush *brush)
Definition brush.cc:1153
bool BKE_brush_use_locked_size(const Scene *scene, const Brush *brush)
Definition brush.cc:1083
void BKE_brush_calc_curve_factors(eBrushCurvePreset preset, const CurveMapping *cumap, blender::Span< float > distances, float brush_radius, blender::MutableSpan< float > factors)
Definition brush.cc:1265
int CCG_grid_xy_to_index(const int grid_size, const int x, const int y)
Definition BKE_ccg.hh:77
void BKE_curvemapping_init(CurveMapping *cumap)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Base * CTX_data_active_base(const bContext *C)
Main * CTX_data_main(const bContext *C)
ToolSettings * CTX_data_tool_settings(const bContext *C)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
ImagePool * BKE_image_pool_new(void)
KeyBlock * BKE_keyblock_from_object(Object *ob)
Definition key.cc:1905
KeyBlock * BKE_keyblock_find_by_index(Key *key, int index)
Definition key.cc:1923
std::optional< blender::Array< bool > > BKE_keyblock_get_dependent_keys(const Key *key, int index)
Definition key.cc:2578
bool BKE_base_is_visible(const View3D *v3d, const Base *base)
Mesh * BKE_mesh_from_object(Object *ob)
void multires_stitch_grids(Object *)
Definition multires.cc:1196
void multires_mark_as_modified(Depsgraph *depsgraph, Object *object, MultiresModifiedFlags flags)
Definition multires.cc:373
General operations, lookup, etc. for blender objects.
std::optional< blender::Bounds< blender::float3 > > BKE_object_boundbox_get(const Object *ob)
bool BKE_paint_brush_set_essentials(Main *bmain, Paint *paint, const char *name)
Definition paint.cc:1102
#define PAINT_SYMM_AREA_DEFAULT
Definition BKE_paint.hh:142
bool BKE_paint_brush_set(Paint *paint, Brush *brush)
Definition paint.cc:714
bool BKE_sculptsession_use_pbvh_draw(const Object *ob, const RegionView3D *rv3d)
Definition paint.cc:2862
std::variant< std::monostate, int, SubdivCCGCoord, BMVert * > ActiveVert
Definition BKE_paint.hh:377
ePaintSymmetryAreas
Definition BKE_paint.hh:144
@ PAINT_SYMM_AREA_Z
Definition BKE_paint.hh:147
@ PAINT_SYMM_AREA_X
Definition BKE_paint.hh:145
@ PAINT_SYMM_AREA_Y
Definition BKE_paint.hh:146
#define SCULPT_FACE_SET_NONE
Definition BKE_paint.hh:341
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:654
MultiresModifierData * BKE_sculpt_multires_active(const Scene *scene, Object *ob)
Definition paint.cc:2316
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
Definition paint.cc:2601
void BKE_sculpt_color_layer_create_if_needed(Object *object)
Definition paint.cc:2577
Paint * BKE_paint_get_active_from_context(const bContext *C)
Definition paint.cc:477
Brush * BKE_paint_brush(Paint *paint)
Definition paint.cc:649
void BKE_sculpt_mask_layers_ensure(Depsgraph *depsgraph, Main *bmain, Object *ob, MultiresModifierData *mmd)
Definition paint.cc:2610
@ PBVH_FullyHidden
Definition BKE_pbvh.hh:34
A BVH for high poly meshes.
bool BKE_pbvh_node_fully_hidden_get(const blender::bke::pbvh::Node &node)
Definition pbvh.cc:1542
blender::Bounds< blender::float3 > BKE_pbvh_redraw_BB(const blender::bke::pbvh::Tree &pbvh)
Definition pbvh.cc:1439
blender::Bounds< blender::float3 > BKE_pbvh_node_get_original_BB(const blender::bke::pbvh::Node *node)
Definition pbvh.cc:1611
void BKE_pbvh_node_mark_topology_update(blender::bke::pbvh::Node &node)
int BKE_pbvh_get_grid_num_verts(const Object &object)
Definition pbvh.cc:1494
float BKE_pbvh_node_get_tmin(const blender::bke::pbvh::Node *node)
Definition pbvh.cc:766
bool BKE_pbvh_node_fully_masked_get(const blender::bke::pbvh::Node &node)
Definition pbvh.cc:1559
void BKE_pbvh_bmesh_after_stroke(BMesh &bm, blender::bke::pbvh::Tree &pbvh)
const blender::Set< BMFace *, 0 > & BKE_pbvh_bmesh_node_faces(blender::bke::pbvh::BMeshNode *node)
PBVHTopologyUpdateMode
@ PBVH_Collapse
@ PBVH_Subdivide
const blender::Set< BMVert *, 0 > & BKE_pbvh_bmesh_node_unique_verts(blender::bke::pbvh::BMeshNode *node)
void BKE_pbvh_bmesh_node_save_orig(BMesh *bm, BMLog *log, blender::bke::pbvh::BMeshNode *node, bool use_original)
void BKE_pbvh_node_get_bm_orco_data(const blender::bke::pbvh::BMeshNode &node, blender::Span< blender::float3 > &r_orig_positions, blender::Span< blender::int3 > &r_orig_tris)
Definition pbvh.cc:1617
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
bool BKE_subdiv_ccg_coord_is_mesh_boundary(blender::OffsetIndices< int > faces, blender::Span< int > corner_verts, blender::BitSpan boundary_verts, const SubdivCCG &subdiv_ccg, SubdivCCGCoord coord)
int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG &subdiv_ccg, const int grid_index)
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
SubdivCCGAdjacencyType
@ SUBDIV_CCG_ADJACENT_EDGE
@ SUBDIV_CCG_ADJACENT_VERTEX
@ SUBDIV_CCG_ADJACENT_NONE
void BKE_subdiv_ccg_foreach_visible_grid_vert(const CCGKey &key, const blender::BitGroupVector<> &grid_hidden, const int grid, const Fn &fn)
SubdivCCGAdjacencyType BKE_subdiv_ccg_coarse_mesh_adjacency_info_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, blender::Span< int > corner_verts, blender::OffsetIndices< int > faces, int &r_v1, int &r_v2)
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, bool include_duplicates, SubdivCCGNeighbors &r_neighbors)
@ MULTIRES_COORDS_MODIFIED
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
Dial * BLI_dial_init(const float start_position[2], float threshold)
Definition BLI_dial_2d.c:37
float BLI_dial_angle(Dial *dial, const float current_position[2])
Definition BLI_dial_2d.c:47
#define LISTBASE_FOREACH(type, var, list)
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
MINLINE float max_ff(float a, float b)
#define M_SQRT2
MINLINE float pow2f(float x)
#define M_PI_2
MINLINE float square_f(float a)
MINLINE float pow3f(float x)
#define M_PI
MINLINE float pow4f(float x)
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition math_geom.cc:215
void isect_ray_tri_watertight_v3_precalc(struct IsectRayPrecalc *isect_precalc, const float ray_direction[3])
struct DistRayAABB_Precalc dist_squared_ray_to_aabb_v3_precalc(const float ray_origin[3], const float ray_direction[3])
Definition math_geom.cc:683
MINLINE float plane_point_side_v3(const float plane[4], const float co[3])
void closest_to_plane_normalized_v3(float r_close[3], const float plane[4], const float pt[3])
Definition math_geom.cc:440
void closest_on_tri_to_point_v3(float r[3], const float p[3], const float v1[3], const float v2[3], const float v3[3])
float dist_squared_ray_to_aabb_v3(const struct DistRayAABB_Precalc *data, const float bb_min[3], const float bb_max[3], float r_point[3], float *r_depth)
void mul_m3_v3(const float M[3][3], float r[3])
void zero_m4(float m[4][4])
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
void mul_m4_v3(const float M[4][4], float r[3])
void scale_m4_fl(float R[4][4], float scale)
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
void rotate_m4(float mat[4][4], char axis, float angle)
void mul_v3_mat3_m4v3(float r[3], const float mat[4][4], const float vec[3])
void mul_mat3_m4_v3(const float mat[4][4], float r[3])
void normalize_m4(float R[4][4]) ATTR_NONNULL()
void axis_angle_to_mat3_single(float R[3][3], char axis, float angle)
void axis_angle_normalized_to_quat(float r[4], const float axis[3], float angle)
void quat_to_axis_angle(float axis[3], float *angle, const float q[4])
void rotate_v3_v3v3fl(float r[3], const float p[3], const float axis[3], float angle)
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 add_v3_fl(float r[3], float f)
MINLINE void sub_v3_v3(float r[3], const float a[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 copy_v2_v2(float r[2], const float a[2])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_v3_int(int r[3], const int a[3])
void project_plane_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
Definition math_vector.c:36
MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v2(float r[2])
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])
MINLINE void copy_v4_fl(float r[4], float f)
MINLINE float normalize_v3(float n[3])
void BLI_rcti_union(struct rcti *rct_a, const struct rcti *rct_b)
bool BLI_rcti_is_empty(const struct rcti *rect)
int BLI_task_parallel_thread_id(const TaskParallelTLS *tls)
#define ARRAY_SET_ITEMS(...)
#define UNPACK3(a)
#define ELEM(...)
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_SHADING
Definition DNA_ID.h:1061
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
#define ID_REAL_USERS(id)
Definition DNA_ID.h:637
@ SCULPT_DISP_DIR_VIEW
@ SCULPT_DISP_DIR_X
@ SCULPT_DISP_DIR_Z
@ SCULPT_DISP_DIR_Y
@ SCULPT_DISP_DIR_AREA
eBrushCurvePreset
@ BRUSH_DEFORM_TARGET_CLOTH_SIM
#define SCULPT_BRUSH_TYPE_HAS_DYNTOPO(t)
eBrushSculptType
@ SCULPT_BRUSH_TYPE_DRAW_SHARP
@ SCULPT_BRUSH_TYPE_THUMB
@ SCULPT_BRUSH_TYPE_GRAB
@ SCULPT_BRUSH_TYPE_BOUNDARY
@ SCULPT_BRUSH_TYPE_DISPLACEMENT_SMEAR
@ SCULPT_BRUSH_TYPE_MASK
@ SCULPT_BRUSH_TYPE_DRAW_FACE_SETS
@ SCULPT_BRUSH_TYPE_FILL
@ SCULPT_BRUSH_TYPE_DRAW
@ SCULPT_BRUSH_TYPE_NUDGE
@ SCULPT_BRUSH_TYPE_CLAY
@ SCULPT_BRUSH_TYPE_CLOTH
@ SCULPT_BRUSH_TYPE_PINCH
@ SCULPT_BRUSH_TYPE_SMEAR
@ SCULPT_BRUSH_TYPE_POSE
@ SCULPT_BRUSH_TYPE_CLAY_THUMB
@ SCULPT_BRUSH_TYPE_MULTIPLANE_SCRAPE
@ SCULPT_BRUSH_TYPE_SIMPLIFY
@ SCULPT_BRUSH_TYPE_SNAKE_HOOK
@ SCULPT_BRUSH_TYPE_CREASE
@ SCULPT_BRUSH_TYPE_LAYER
@ SCULPT_BRUSH_TYPE_SLIDE_RELAX
@ SCULPT_BRUSH_TYPE_ELASTIC_DEFORM
@ SCULPT_BRUSH_TYPE_FLATTEN
@ SCULPT_BRUSH_TYPE_SMOOTH
@ SCULPT_BRUSH_TYPE_PAINT
@ SCULPT_BRUSH_TYPE_DISPLACEMENT_ERASER
@ SCULPT_BRUSH_TYPE_SCRAPE
@ SCULPT_BRUSH_TYPE_INFLATE
@ SCULPT_BRUSH_TYPE_BLOB
@ SCULPT_BRUSH_TYPE_ROTATE
@ SCULPT_BRUSH_TYPE_CLAY_STRIPS
@ BRUSH_OFFSET_PRESSURE
@ BRUSH_ORIGINAL_NORMAL
@ BRUSH_FRONTFACE
@ BRUSH_DRAG_DOT
@ BRUSH_GRAB_ACTIVE_VERTEX
@ BRUSH_EDGE_TO_EDGE
@ BRUSH_ORIGINAL_PLANE
@ BRUSH_ACCUMULATE
@ BRUSH_DIR_IN
@ BRUSH_ANCHORED
@ BRUSH_PLANE_TRIM
@ BRUSH_INVERSE_SMOOTH_PRESSURE
@ BRUSH_INVERT_TO_SCRAPE_FILL
@ BRUSH_CLOTH_DEFORM_EXPAND
@ BRUSH_CLOTH_DEFORM_GRAB
@ BRUSH_CLOTH_DEFORM_SNAKE_HOOK
#define SCULPT_BRUSH_TYPE_HAS_ACCUMULATE(t)
#define SCULPT_BRUSH_TYPE_HAS_RAKE(t)
@ BRUSH_SNAKE_HOOK_DEFORM_ELASTIC
eBrushFalloffShape
@ PAINT_FALLOFF_SHAPE_SPHERE
@ PAINT_FALLOFF_SHAPE_TUBE
@ BRUSH_SMOOTH_DEFORM_SURFACE
@ BRUSH_SMOOTH_DEFORM_LAPLACIAN
@ BRUSH_PAINT_WET_MIX_PRESSURE
@ BRUSH_PAINT_HARDNESS_PRESSURE
@ BRUSH_PAINT_FLOW_PRESSURE
@ BRUSH_PAINT_DENSITY_PRESSURE
@ BRUSH_PAINT_WET_PERSISTENCE_PRESSURE
@ BRUSH_PAINT_WET_MIX_PRESSURE_INVERT
@ BRUSH_PAINT_HARDNESS_PRESSURE_INVERT
@ BRUSH_PAINT_FLOW_PRESSURE_INVERT
@ BRUSH_PAINT_DENSITY_PRESSURE_INVERT
@ BRUSH_PAINT_WET_PERSISTENCE_PRESSURE_INVERT
@ BRUSH_USE_COLOR_AS_DISPLACEMENT
@ BRUSH_AREA_RADIUS_PRESSURE
BrushMaskTool
@ BRUSH_MASK_DRAW
@ BRUSH_MASK_SMOOTH
#define SCULPT_BRUSH_TYPE_HAS_NORMAL_WEIGHT(t)
#define SCULPT_BRUSH_TYPE_HAS_TOPOLOGY_RAKE(t)
@ CD_PROP_FLOAT
@ KEYBLOCK_LOCKED_SHAPE
@ eModifierMode_Realtime
@ MOD_MIR_CLIPPING
@ MOD_MIR_AXIS_X
@ eModifierType_Mirror
@ OB_SOLID
@ OB_MODE_SCULPT
Object is a sort of wrapper for general info.
@ OB_MESH
ePaintSymmetryFlags
@ PAINT_SYMM_Y
@ PAINT_SYMMETRY_FEATHER
@ PAINT_TILE_X
@ PAINT_SYMM_X
@ PAINT_SYMM_Z
@ SCULPT_DYNTOPO_SUBDIVIDE
@ SCULPT_DYNTOPO_DETAIL_MANUAL
@ SCULPT_LOCK_X
@ SCULPT_DYNTOPO_DETAIL_CONSTANT
@ SCULPT_DYNTOPO_COLLAPSE
@ SCULPT_DYNTOPO_DETAIL_BRUSH
@ RGN_TYPE_WINDOW
@ SPACE_IMAGE
@ SPACE_VIEW3D
@ MTEX_MAP_MODE_AREA
@ MTEX_MAP_MODE_3D
@ TEX_NOISE
@ V3D_SHADING_VERTEX_COLOR
@ RV3D_PAINTING
#define RV3D_CLIPPING_ENABLED(v3d, rv3d)
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
#define OPERATOR_RETVAL_CHECK(ret)
void ED_image_undo_push_begin(const char *name, PaintMode paint_mode)
void ED_image_undo_push_end()
void ED_image_paint_brush_type_update_sticky_shading_color(bContext *C, Object *ob)
void ED_area_tag_redraw_regiontype(ScrArea *area, int regiontype)
Definition area.cc:726
void ED_region_tag_redraw_partial(ARegion *region, const rcti *rct, bool rebuild)
Definition area.cc:681
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:634
blender::float2 ED_view3d_project_float_v2_m4(const ARegion *region, const float co[3], const blender::float4x4 &mat)
void ED_view3d_win_to_3d(const View3D *v3d, const ARegion *region, const float depth_pt[3], const float mval[2], float r_out[3])
void ED_view3d_init_mats_rv3d(const Object *ob, RegionView3D *rv3d)
ViewContext ED_view3d_viewcontext_init(bContext *C, Depsgraph *depsgraph)
void ED_view3d_win_to_delta(const ARegion *region, const float xy_delta[2], float zfac, float r_out[3])
blender::float4x4 ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, const Object *ob)
bool ED_view3d_win_to_segment_clipped(const Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const float mval[2], float r_ray_start[3], float r_ray_end[3], bool do_clip_planes)
void view3d_operator_needs_opengl(const bContext *C)
void ED_view3d_win_to_origin(const ARegion *region, const float mval[2], float r_out[3])
float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3])
bool ED_view3d_clipping_test(const RegionView3D *rv3d, const float co[3], bool is_local)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:125
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
void ntreeTexEndExecTree(struct bNodeTreeExec *exec)
struct bNodeTreeExec * ntreeTexBeginExecTree(struct bNodeTree *ntree)
#define C
Definition RandGen.cpp:29
#define ND_DRAW
Definition WM_types.hh:428
@ OPTYPE_BLOCKING
Definition WM_types.hh:164
#define NC_OBJECT
Definition WM_types.hh:346
#define U
#define BM_ELEM_CD_SET_FLOAT(ele, offset, f)
#define BM_ELEM_CD_GET_FLOAT(ele, offset)
#define BM_ELEM_CD_GET_INT(ele, offset)
@ BM_ELEM_HIDDEN
#define BM_elem_index_get(ele)
#define BM_elem_flag_test(ele, hflag)
#define BM_elem_flag_test_bool(ele, hflag)
#define BM_ITER_ELEM(ele, iter, data, itype)
@ BM_FACES_OF_VERT
@ BM_LOOPS_OF_VERT
ATTR_WARN_UNUSED_RESULT BMesh * bm
const float * BM_log_find_original_vert_mask(BMLog *log, BMVert *v)
Definition bmesh_log.cc:932
const float * BM_log_find_original_vert_co(BMLog *log, BMVert *v)
Definition bmesh_log.cc:921
int BM_mesh_elem_count(BMesh *bm, const char htype)
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
#define BM_VERT
bool BM_vert_is_boundary(const BMVert *v)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMLoop * l
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
SIMD_FORCE_INLINE void invalidate()
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
bool closest(btVector3 &v)
bool is_empty() const
Definition BLI_array.hh:253
bool is_empty() const
int64_t size() const
Definition BLI_set.hh:564
int64_t size() const
int64_t remove_if(Predicate &&predicate)
void reinitialize(const int64_t new_size)
Span< T > as_span() const
void clear()
int64_t size() const
Definition BLI_array.hh:245
IndexRange index_range() const
Definition BLI_array.hh:349
void reinitialize(const int64_t new_size)
Definition BLI_array.hh:388
int calc_reduced_ids(MutableSpan< int > result) const
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
static IndexMask from_bools_inverse(const IndexMask &universe, Span< bool > bools, IndexMaskMemory &memory)
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
constexpr IndexRange drop_front(int64_t n) const
constexpr int64_t size() const
Definition BLI_span.hh:494
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
Definition BLI_span.hh:574
constexpr T * data() const
Definition BLI_span.hh:540
constexpr void fill(const T &value) const
Definition BLI_span.hh:518
constexpr IndexRange index_range() const
Definition BLI_span.hh:671
constexpr void copy_from(Span< T > values) const
Definition BLI_span.hh:726
constexpr Span slice(int64_t start, int64_t size) const
Definition BLI_span.hh:138
constexpr const T & first() const
Definition BLI_span.hh:316
constexpr int64_t size() const
Definition BLI_span.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
constexpr bool is_empty() const
Definition BLI_span.hh:261
int64_t size() const
int64_t remove_if(Predicate &&predicate)
void append(const T &value)
void resize(const int64_t new_size)
void append_non_duplicates(const T &value)
Span< T > as_span() const
void resize(const int64_t new_size_in_bits, const bool value=false)
GAttributeReader lookup(const StringRef attribute_id) const
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
void tag_attribute_changed(const IndexMask &node_mask, StringRef attribute_name)
Definition pbvh.cc:593
void tag_positions_changed(const IndexMask &node_mask)
Definition pbvh.cc:549
Span< NodeT > nodes() const
void tag_face_sets_changed(const IndexMask &node_mask)
Definition pbvh.cc:579
void tag_masks_changed(const IndexMask &node_mask)
Definition pbvh.cc:586
void tag_topology_changed(const IndexMask &node_mask)
Definition pbvh.cc:572
void deform(MutableSpan< float3 > translations, Span< int > verts) const
Definition sculpt.cc:7159
PositionDeformData(const Depsgraph &depsgraph, Object &object_orig)
Definition sculpt.cc:7123
IndexMask slice(IndexRange range) const
void foreach_index(Fn &&fn) const
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
local_group_size(16, 16) .push_constant(Type b
#define printf
VecBase< float, 2 > float2
CCL_NAMESPACE_BEGIN ccl_device_inline float frac(float x, ccl_private int *ix)
#define sinf(x)
#define cosf(x)
#define powf(x, y)
#define fabsf(x)
#define sqrtf(x)
draw_view in_light_buf[] float
static ushort indices[]
static float verts[][3]
static float normals[][3]
int ED_gpencil_session_active()
static void transform_positions(const Span< blender::float3 > src, const blender::float4x4 &transform, blender::MutableSpan< blender::float3 > dst)
CCL_NAMESPACE_BEGIN ccl_device float invert(float color, float factor)
Definition invert.h:9
#define LOG(severity)
Definition log.h:33
static char faces[256]
#define G(x, y, z)
void count_indices(Span< int > indices, MutableSpan< int > counts)
IndexRange grid_range(const int grid_area, const int grid)
int2 face_find_adjacent_verts(const IndexRange face, const Span< int > corner_verts, const int vert)
Definition BKE_mesh.hh:275
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2846
IndexMask search_nodes(const Tree &pbvh, IndexMaskMemory &memory, FunctionRef< bool(const Node &)> filter_fn)
Definition pbvh.cc:2647
void update_normals(const Depsgraph &depsgraph, Object &object_orig, Tree &pbvh)
Definition pbvh.cc:1058
IndexMask all_leaf_nodes(const Tree &pbvh, IndexMaskMemory &memory)
Definition pbvh.cc:2612
void clip_ray_ortho(Tree &pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3])
Definition pbvh.cc:2013
bool node_raycast_bmesh(BMeshNode &node, const float3 &ray_start, const float3 &ray_normal, IsectRayPrecalc *isect_precalc, float *depth, bool use_original, BMVert **r_active_vertex, float3 &r_face_normal)
bool node_raycast_mesh(const MeshNode &node, Span< float3 > node_positions, Span< float3 > vert_positions, OffsetIndices< int > faces, Span< int > corner_verts, Span< int3 > corner_tris, Span< bool > hide_poly, const float3 &ray_start, const float3 &ray_normal, IsectRayPrecalc *isect_precalc, float *depth, int &r_active_vertex, int &r_active_face_index, float3 &r_face_normal)
Definition pbvh.cc:1807
void node_update_mask_bmesh(int mask_offset, BMeshNode &node)
Definition pbvh.cc:1277
void node_update_mask_mesh(Span< float > mask, MeshNode &node)
Definition pbvh.cc:1219
void node_update_mask_grids(const CCGKey &key, Span< float > masks, GridsNode &node)
Definition pbvh.cc:1247
bool node_raycast_grids(const SubdivCCG &subdiv_ccg, GridsNode &node, Span< float3 > node_positions, const float3 &ray_start, const float3 &ray_normal, const IsectRayPrecalc *isect_precalc, float *depth, SubdivCCGCoord &r_active_vertex, int &r_active_grid_index, float3 &r_face_normal)
Definition pbvh.cc:1923
Bounds< float3 > bounds_get(const Tree &pbvh)
Definition pbvh.cc:1480
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2502
MutableSpan< float3 > vert_positions_eval_for_write(const Depsgraph &depsgraph, Object &object_orig)
Definition pbvh.cc:2496
Bounds< float3 > node_bounds(const Node &node)
Definition pbvh.cc:1604
bool bmesh_update_topology(BMesh &bm, Tree &pbvh, BMLog &bm_log, PBVHTopologyUpdateMode mode, float min_edge_len, float max_edge_len, const float center[3], const float view_normal[3], float radius, bool use_frontface, bool use_projected)
void build_pixels(const Depsgraph &depsgraph, Object &object, Image &image, ImageUser &image_user)
bool find_nearest_to_ray_node(Tree &pbvh, Node &node, Span< float3 > node_positions, bool use_origco, Span< float3 > vert_positions, const OffsetIndices< int > faces, Span< int > corner_verts, Span< int3 > corner_tris, Span< bool > hide_poly, const SubdivCCG *subdiv_ccg, const float ray_start[3], const float ray_normal[3], float *depth, float *dist_sq)
Definition pbvh.cc:2263
void store_bounds_orig(Tree &pbvh)
Definition pbvh.cc:1206
Span< int > node_face_indices_calc_grids(const SubdivCCG &subdiv_ccg, const GridsNode &node, Vector< int > &faces)
Definition pbvh.cc:1583
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2482
void find_nearest_to_ray(Tree &pbvh, const FunctionRef< void(Node &node, float *tmin)> fn, const float3 &ray_start, const float3 &ray_normal, bool original)
Definition pbvh.cc:2125
void raycast(Tree &pbvh, FunctionRef< void(Node &node, float *tmin)> cb, const float3 &ray_start, const float3 &ray_normal, bool original)
void calc_grids_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, const bke::pbvh::GridsNode &node, Span< int > grids, MutableSpan< float > factors)
bool needs_normal(const SculptSession &ss, const Sculpt &sd, const Brush *brush)
std::unique_ptr< Cache > cache_init(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob)
bool is_enabled(const Sculpt &sd, const Object &object, const Brush *br)
void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, const bke::pbvh::MeshNode &node, Span< int > verts, MutableSpan< float > factors)
void do_boundary_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
bool vert_is_boundary(const GroupedSpan< int > vert_to_face_map, const Span< bool > hide_poly, const BitSpan boundary, const int vert)
Definition sculpt.cc:454
void ensure_boundary_info(Object &object)
Definition sculpt.cc:5784
bool is_cloth_deform_brush(const Brush &brush)
void brush_store_simulation_state(const Depsgraph &depsgraph, const Object &object, SimulationData &cloth_sim)
void ensure_nodes_constraints(const Sculpt &sd, Object &object, const IndexMask &node_mask, SimulationData &cloth_sim, const float3 &initial_location, const float radius)
void sim_activate_nodes(Object &object, SimulationData &cloth_sim, const IndexMask &node_mask)
IndexMask brush_affected_nodes_gather(const Object &object, const Brush &brush, IndexMaskMemory &memory)
void do_cloth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void do_simulation_step(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, SimulationData &cloth_sim, const IndexMask &node_mask)
std::unique_ptr< SimulationData > brush_simulation_create(const Depsgraph &depsgraph, Object &ob, const float cloth_mass, const float cloth_damping, const float cloth_softbody_strength, const bool use_collisions, const bool needs_deform_coords)
bke::GSpanAttributeWriter active_color_attribute_for_write(Mesh &mesh)
void do_smear_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const IndexMask &node_mask)
void color_vert_set(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face_map, bke::AttrDomain color_domain, int vert, const float4 &color, GMutableSpan color_attribute)
void do_paint_brush(const Scene &scene, const Depsgraph &depsgraph, PaintModeSettings &paint_mode_settings, const Sculpt &sd, Object &ob, const IndexMask &node_mask, const IndexMask &texnode_mask)
static BLI_NOINLINE void fill_factor_from_hide_and_mask(const Mesh &mesh, const Span< int > face_indices, const MutableSpan< float > r_factors)
float relative_to_detail_size(const float relative_detail, const float brush_radius, const float pixel_radius, const float pixel_size)
float constant_to_detail_size(const float constant_detail, const Object &ob)
float brush_to_detail_size(const float brush_percent, const float brush_radius)
bool stroke_is_dyntopo(const Object &object, const Brush &brush)
Definition sculpt.cc:829
int vert_face_set_get(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const int vert)
Definition sculpt.cc:232
bool vert_has_unique_face_set(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, int vert)
Definition sculpt.cc:294
bool vert_has_face_set(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const int vert, const int face_set)
Definition sculpt.cc:254
bke::SpanAttributeWriter< int > ensure_face_sets_mesh(Mesh &mesh)
int active_face_set_get(const Object &object)
Definition sculpt.cc:198
static bool sculpt_check_unique_face_set_for_edge_in_base_mesh(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const Span< int > corner_verts, const OffsetIndices< int > faces, int v1, int v2)
Definition sculpt.cc:320
bool vert_all_faces_visible_get(const Span< bool > hide_poly, const GroupedSpan< int > vert_to_face_map, const int vert)
void ensure_cache(Object &object)
Definition sculpt.cc:6027
static SculptTopologyIslandCache calc_topology_islands_grids(const Object &object)
Definition sculpt.cc:5960
static SculptTopologyIslandCache vert_disjoint_set_to_islands(const AtomicDisjointSet &vert_sets, const int verts_num)
Definition sculpt.cc:5914
static SculptTopologyIslandCache calc_topology_islands_mesh(const Mesh &mesh)
Definition sculpt.cc:5935
static SculptTopologyIslandCache calculate_cache(const Object &object)
Definition sculpt.cc:6013
static SculptTopologyIslandCache calc_topology_islands_bmesh(const Object &object)
Definition sculpt.cc:5985
int vert_id_get(const SculptSession &ss, const int vert)
Definition sculpt.cc:5894
void do_pose_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const IndexMask &node_mask)
void pose_brush_init(const Depsgraph &depsgraph, Object &ob, SculptSession &ss, const Brush &brush)
void push_nodes(const Depsgraph &depsgraph, Object &object, const IndexMask &node_mask, const Type type)
static void restore_from_undo_step(const Depsgraph &depsgraph, const Sculpt &sd, Object &object)
Definition sculpt.cc:1134
static void restore_color_from_undo_step(Object &object)
Definition sculpt.cc:929
static void restore_face_set_from_undo_step(Object &object)
Definition sculpt.cc:962
void push_begin_ex(const Scene &, Object &ob, const char *name)
void restore_position_from_undo_step(const Depsgraph &depsgraph, Object &object)
Definition sculpt.cc:1014
static void restore_mask_from_undo_step(Object &object)
Definition sculpt.cc:854
static void calc_local_from_screen(const ViewContext &vc, const float center[3], const float screen_dir[2], float r_local_dir[3])
Definition sculpt.cc:2463
std::optional< Span< float > > orig_mask_data_lookup_grids(const Object &object, const bke::pbvh::GridsNode &node)
void do_clay_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition clay.cc:152
int paint_stroke_exec(bContext *C, wmOperator *op, PaintStroke *stroke)
static bool stroke_test_start(bContext *C, wmOperator *op, const float mouse[2])
void do_bmesh_topology_rake_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask, const float input_strength)
void do_blob_brush(const Depsgraph &depsgraph, const Scene &scene, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition crease.cc:279
void do_snake_hook_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void update_shape_keys(Object &object, const Mesh &mesh, const KeyBlock &active_key, Span< int > verts, Span< float3 > translations, Span< float3 > positions_orig)
Definition sculpt.cc:7200
static bool brush_needs_rake_rotation(const Brush &brush)
Definition sculpt.cc:808
MutableSpan< float3 > gather_grids_positions(const SubdivCCG &subdiv_ccg, const Span< int > grids, Vector< float3 > &positions)
static float brush_dynamic_size_get(const Brush &brush, const StrokeCache &cache, float initial_size)
Definition sculpt.cc:3980
static void fake_neighbor_search_mesh(const SculptSession &ss, const Span< float3 > vert_positions, const Span< bool > hide_vert, const float3 &location, const float max_distance_sq, const int island_id, const bke::pbvh::MeshNode &node, NearestVertData &nvtd)
Definition sculpt.cc:5550
bool node_in_sphere(const bke::pbvh::Node &node, const float3 &location, const float radius_sq, const bool original)
Definition sculpt.cc:2326
void scatter_data_bmesh(Span< T > node_data, const Set< BMVert *, 0 > &verts, MutableSpan< T > dst)
Definition sculpt.cc:6162
bool node_in_cylinder(const DistRayAABB_Precalc &ray_dist_precalc, const bke::pbvh::Node &node, const float radius_sq, const bool original)
Definition sculpt.cc:2337
static int sculpt_brush_needs_normal(const SculptSession &ss, const Sculpt &sd, const Brush &brush)
Definition sculpt.cc:785
void calc_factors_common_from_orig_data_grids(const Depsgraph &depsgraph, const Brush &brush, const Object &object, Span< float3 > positions, Span< float3 > normals, const bke::pbvh::GridsNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6387
static void do_radial_symmetry(const Depsgraph &depsgraph, const Scene &scene, const Sculpt &sd, Object &ob, const Brush &brush, UnifiedPaintSettings &ups, PaintModeSettings &paint_mode_settings, const BrushActionFunc action, const ePaintSymmetryFlags symm, const int axis, const float)
Definition sculpt.cc:3481
static int brush_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
Definition sculpt.cc:5480
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6068
void do_nudge_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition draw.cc:197
void do_displacement_eraser_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void do_relax_face_sets_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition relax.cc:772
void do_displacement_smear_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const IndexMask &node_mask)
void calc_brush_strength_factors(const StrokeCache &cache, const Brush &brush, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:6903
static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition sculpt.cc:5358
std::optional< Span< int > > orig_face_set_data_lookup_mesh(const Object &object, const bke::pbvh::MeshNode &node)
void gather_data_grids(const SubdivCCG &subdiv_ccg, Span< T > src, Span< int > grids, MutableSpan< T > node_data)
Definition sculpt.cc:6106
static void redo_empty_ui(bContext *, wmOperator *)
Definition sculpt.cc:5485
void calc_vert_neighbors_interior(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face, BitSpan boundary_verts, Span< bool > hide_poly, Span< int > verts, MutableSpan< Vector< int > > result)
Definition sculpt.cc:7405
std::optional< int > nearest_vert_calc_mesh(const bke::pbvh::Tree &pbvh, const Span< float3 > vert_positions, const Span< bool > hide_vert, const float3 &location, const float max_distance, const bool use_original)
Definition sculpt.cc:563
void do_rotate_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void filter_below_plane_factors(Span< float3 > vert_positions, Span< int > verts, const float4 &plane, MutableSpan< float > factors)
Definition sculpt.cc:7554
static void stroke_update_step(bContext *C, wmOperator *op, PaintStroke *, PointerRNA *stroke_element)
void apply_hardness_to_distances(float radius, float hardness, MutableSpan< float > distances)
Definition sculpt.cc:6876
void calc_factors_common_grids(const Depsgraph &depsgraph, const Brush &brush, const Object &object, Span< float3 > positions, const bke::pbvh::GridsNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6284
void gather_bmesh_normals(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > normals)
Definition sculpt.cc:6086
static void pose_fake_neighbors_free(SculptSession &ss)
Definition sculpt.cc:5526
bool node_fully_masked_or_hidden(const bke::pbvh::Node &node)
Definition sculpt.cc:2315
void calc_factors_common_mesh_indexed(const Depsgraph &depsgraph, const Brush &brush, const Object &object, const MeshAttributeData &attribute_data, Span< float3 > vert_positions, Span< float3 > vert_normals, const bke::pbvh::MeshNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6213
void filter_distances_with_radius(float radius, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:6786
void do_multiplane_scrape_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
static void copy_indices(const Span< float3 > src, const Span< int > indices, MutableSpan< float3 > dst)
Definition sculpt.cc:7152
void do_surface_smooth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
std::optional< OrigPositionData > orig_position_data_lookup_grids(const Object &object, const bke::pbvh::GridsNode &node)
static void smooth_brush_toggle_off(const bContext *C, Paint *paint, StrokeCache *cache)
Definition sculpt.cc:3794
static void cache_paint_invariants_update(StrokeCache &cache, const Brush &brush)
Definition sculpt.cc:4185
OffsetIndices< int > create_node_vert_offsets_bmesh(const Span< bke::pbvh::BMeshNode > nodes, const IndexMask &nodes_mask, Array< int > &node_data)
Definition sculpt.cc:7338
void filter_region_clip_factors(const SculptSession &ss, Span< float3 > vert_positions, Span< int > verts, MutableSpan< float > factors)
Definition sculpt.cc:6653
void gather_data_bmesh(Span< T > src, const Set< BMVert *, 0 > &verts, MutableSpan< T > node_data)
Definition sculpt.cc:6122
void flush_update_done(const bContext *C, Object &ob, UpdateType update_type)
Definition sculpt.cc:5069
static void fake_neighbor_init(Object &object, const float max_dist)
Definition sculpt.cc:5518
void reset_translations_to_original(MutableSpan< float3 > translations, Span< float3 > positions, Span< float3 > orig_positions)
Definition sculpt.cc:6966
float3 symmetry_flip(const float3 &src, const ePaintSymmetryFlags symm)
void calc_brush_distances(const SculptSession &ss, Span< float3 > vert_positions, Span< int > vert_indices, eBrushFalloffShape falloff_shape, MutableSpan< float > r_distances)
Definition sculpt.cc:6736
void orig_position_data_gather_bmesh(const BMLog &bm_log, const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions, MutableSpan< float3 > normals)
static float area_normal_calc_weight(const float distance, const float radius_inv)
Definition sculpt.cc:1344
void scale_translations(MutableSpan< float3 > translations, Span< float > factors)
Definition sculpt.cc:7230
void paint_stroke_cancel(bContext *C, wmOperator *op, PaintStroke *stroke)
void flush_update_step(bContext *C, UpdateType update_type)
Definition sculpt.cc:4960
static IndexMask pbvh_gather_generic(Object &ob, const Brush &brush, bool use_original, float radius_scale, IndexMaskMemory &memory)
Definition sculpt.cc:2364
void do_elastic_deform_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void do_draw_sharp_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
float clay_thumb_get_stabilized_pressure(const StrokeCache &cache)
void do_grab_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition grab.cc:163
static bool brush_type_needs_original(const char sculpt_brush_type)
Definition sculpt.cc:762
bool paint_supports_dynamic_size(const Brush &br, PaintMode mode)
static void sculpt_update_cache_invariants(bContext *C, Sculpt &sd, SculptSession &ss, wmOperator *op, const float mval[2])
Definition sculpt.cc:3824
static void sculpt_init_mirror_clipping(const Object &ob, const SculptSession &ss)
Definition sculpt.cc:3715
static IndexMask pbvh_gather_texpaint(Object &ob, const Brush &brush, const bool use_original, const float radius_scale, IndexMaskMemory &memory)
Definition sculpt.cc:2398
static void stroke_done(const bContext *C, PaintStroke *stroke)
static void brush_exit_tex(Sculpt &sd)
Definition sculpt.cc:5298
void do_topology_relax_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition relax.cc:806
static bool need_delta_from_anchored_origin(const Brush &brush)
Definition sculpt.cc:4000
static bool sculpt_needs_connectivity_info(const Sculpt &sd, const Brush &brush, const Object &object, int stroke_mode)
Definition sculpt.cc:4331
bool report_if_shape_key_is_locked(const Object &ob, ReportList *reports)
Definition sculpt.cc:128
static void calc_area_normal_and_center_node_bmesh(const Object &object, const Brush &brush, const bool use_area_nos, const bool use_area_cos, const bool has_bm_orco, const bke::pbvh::BMeshNode &node, SampleLocalData &tls, AreaNormalCenterData &anctd)
Definition sculpt.cc:1585
void filter_verts_outside_symmetry_area(Span< float3 > positions, const float3 &pivot, ePaintSymmetryFlags symm, MutableSpan< float > factors)
Definition sculpt.cc:7524
static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
Definition sculpt.cc:5438
static void accumulate_area_center(const float3 &test_location, const float3 &position, const float distance, const float radius_inv, const int flip_index, AreaNormalCenterData &anctd)
Definition sculpt.cc:1364
static void rake_data_update(SculptRakeData *srd, const float co[3])
Definition sculpt.cc:815
void calc_translations_to_plane(Span< float3 > vert_positions, Span< int > verts, const float4 &plane, MutableSpan< float3 > translations)
Definition sculpt.cc:7499
void scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7247
void calc_factors_common_from_orig_data_mesh(const Depsgraph &depsgraph, const Brush &brush, const Object &object, const MeshAttributeData &attribute_data, Span< float3 > positions, Span< float3 > normals, const bke::pbvh::MeshNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6351
static void smooth_brush_toggle_on(const bContext *C, Paint *paint, StrokeCache *cache)
Definition sculpt.cc:3752
static float3 calc_sculpt_normal(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const IndexMask &node_mask)
Definition sculpt.cc:2408
void translations_from_new_positions(Span< float3 > new_positions, Span< int > verts, Span< float3 > old_positions, MutableSpan< float3 > translations)
Definition sculpt.cc:7277
static bool need_delta_for_tip_orientation(const Brush &brush)
Definition sculpt.cc:4025
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7042
static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
Definition sculpt.cc:5457
static void do_brush_action(const Depsgraph &depsgraph, const Scene &scene, const Sculpt &sd, Object &ob, const Brush &brush, UnifiedPaintSettings &ups, PaintModeSettings &paint_mode_settings)
Definition sculpt.cc:3022
static void push_undo_nodes(const Depsgraph &depsgraph, Object &ob, const Brush &brush, const IndexMask &node_mask)
Definition sculpt.cc:2990
std::optional< Span< float4 > > orig_color_data_lookup_mesh(const Object &object, const bke::pbvh::MeshNode &node)
void scatter_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6136
void do_draw_face_sets_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void SCULPT_OT_brush_stroke(wmOperatorType *ot)
Definition sculpt.cc:5487
void project_translations(MutableSpan< float3 > translations, const float3 &plane)
Definition sculpt.cc:7018
static void dynamic_topology_update(const Depsgraph &depsgraph, const Scene &, const Sculpt &sd, Object &ob, const Brush &brush, UnifiedPaintSettings &, PaintModeSettings &)
Definition sculpt.cc:2904
void calc_brush_plane(const Depsgraph &depsgraph, const Brush &brush, Object &ob, const IndexMask &node_mask, float3 &r_area_no, float3 &r_area_co)
Definition sculpt.cc:2789
static void calc_brush_local_mat(const float rotation, const Object &ob, float local_mat[4][4], float local_mat_inv[4][4])
Definition sculpt.cc:2481
void do_draw_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition draw.cc:180
std::optional< float3 > calc_area_normal(const Depsgraph &depsgraph, const Brush &brush, const Object &ob, const IndexMask &node_mask)
Definition sculpt.cc:1848
void filter_plane_trim_limit_factors(const Brush &brush, const StrokeCache &cache, Span< float3 > translations, MutableSpan< float > factors)
Definition sculpt.cc:7538
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6978
void do_smooth_mask_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask, float brush_strength)
void calc_factors_common_mesh(const Depsgraph &depsgraph, const Brush &brush, const Object &object, const MeshAttributeData &attribute_data, Span< float3 > positions, Span< float3 > vert_normals, const bke::pbvh::MeshNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6249
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, Vector< BMVert *, 64 > &r_neighbors)
Definition sculpt.cc:389
ViewContext * paint_stroke_view_context(PaintStroke *stroke)
void do_draw_vector_displacement_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void do_layer_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6096
void calc_vert_neighbors(OffsetIndices< int > faces, Span< int > corner_verts, GroupedSpan< int > vert_to_face, Span< bool > hide_poly, Span< int > verts, MutableSpan< Vector< int > > result)
Definition sculpt.cc:7350
static void fake_neighbor_search_bmesh(const SculptSession &ss, const float3 &location, const float max_distance_sq, const int island_id, const bke::pbvh::BMeshNode &node, NearestVertData &nvtd)
Definition sculpt.cc:5606
bool paint_brush_cursor_poll(bContext *C)
static void sculpt_fix_noise_tear(const Sculpt &sd, Object &ob)
Definition sculpt.cc:3507
static AreaNormalCenterData calc_area_normal_and_center_reduce(const AreaNormalCenterData &a, const AreaNormalCenterData &b)
Definition sculpt.cc:1728
void filter_above_plane_factors(Span< float3 > vert_positions, Span< int > verts, const float4 &plane, MutableSpan< float > factors)
Definition sculpt.cc:7577
void calc_area_center(const Depsgraph &depsgraph, const Brush &brush, const Object &ob, const IndexMask &node_mask, float r_area_co[3])
Definition sculpt.cc:1746
void do_fill_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition plane.cc:271
static void sculpt_update_cache_variants(bContext *C, Sculpt &sd, Object &ob, PointerRNA *ptr)
Definition sculpt.cc:4230
void calc_brush_cube_distances(const Brush &brush, const float4x4 &mat, Span< float3 > positions, Span< int > verts, MutableSpan< float > r_distances, MutableSpan< float > factors)
Definition sculpt.cc:6797
int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event, PaintStroke **stroke_p)
void do_topology_slide_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void apply_crazyspace_to_translations(Span< float3x3 > deform_imats, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7031
void do_thumb_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition thumb.cc:134
static void brush_delta_update(const Depsgraph &depsgraph, UnifiedPaintSettings &ups, const Object &ob, const Brush &brush)
Definition sculpt.cc:4039
std::optional< BMVert * > nearest_vert_calc_bmesh(const bke::pbvh::Tree &pbvh, const float3 &location, const float max_distance, const bool use_original)
Definition sculpt.cc:664
void do_smooth_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask, const float brush_strength)
Definition smooth.cc:227
static void fake_neighbor_search(const Depsgraph &depsgraph, const Object &ob, const float max_distance_sq, MutableSpan< int > fake_neighbors)
Definition sculpt.cc:5634
void calc_front_face(const float3 &view_normal, Span< float3 > normals, MutableSpan< float > factors)
Definition sculpt.cc:6595
static void calc_area_normal_and_center_node_grids(const Object &object, const Brush &brush, const bool use_area_nos, const bool use_area_cos, const bke::pbvh::GridsNode &node, SampleLocalData &tls, AreaNormalCenterData &anctd)
Definition sculpt.cc:1479
static void do_symmetrical_brush_actions(const Depsgraph &depsgraph, const Scene &scene, const Sculpt &sd, Object &ob, const BrushActionFunc action, UnifiedPaintSettings &ups, PaintModeSettings &paint_mode_settings)
Definition sculpt.cc:3518
void(*)(const Depsgraph &depsgraph, const Scene &scene, const Sculpt &sd, Object &ob, const Brush &brush, UnifiedPaintSettings &ups, PaintModeSettings &paint_mode_settings) BrushActionFunc
Definition sculpt.cc:3406
float paint_stroke_distance_get(PaintStroke *stroke)
static float3 area_center_calc_weighted(const float3 &test_location, const float distance, const float radius_inv, const float3 &co)
Definition sculpt.cc:1351
static void fake_neighbor_search_grids(const SculptSession &ss, const CCGKey &key, const Span< float3 > positions, const BitGroupVector<> &grid_hidden, const float3 &location, const float max_distance_sq, const int island_id, const bke::pbvh::GridsNode &node, NearestVertData &nvtd)
Definition sculpt.cc:5577
static void update_sculpt_normal(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const IndexMask &node_mask)
Definition sculpt.cc:2431
float sculpt_calc_radius(const ViewContext &vc, const Brush &brush, const Scene &scene, const float3 location)
Definition sculpt.cc:115
std::optional< Span< float > > orig_mask_data_lookup_mesh(const Object &object, const bke::pbvh::MeshNode &node)
std::optional< SubdivCCGCoord > nearest_vert_calc_grids(const bke::pbvh::Tree &pbvh, const SubdivCCG &subdiv_ccg, const float3 &location, const float max_distance, const bool use_original)
Definition sculpt.cc:610
void do_flatten_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition plane.cc:251
std::optional< OrigPositionData > orig_position_data_lookup_mesh_all_verts(const Object &object, const bke::pbvh::MeshNode &node)
Span< BMVert * > vert_neighbors_get_interior_bmesh(BMVert &vert, Vector< BMVert *, 64 > &r_neighbors)
Definition sculpt.cc:404
static IndexMask pbvh_gather_cursor_update(Object &ob, bool use_original, IndexMaskMemory &memory)
Definition sculpt.cc:2353
static bool brush_uses_topology_rake(const SculptSession &ss, const Brush &brush)
Definition sculpt.cc:776
OffsetIndices< int > create_node_vert_offsets(const Span< bke::pbvh::MeshNode > nodes, const IndexMask &nodes_mask, Array< int > &node_data)
Definition sculpt.cc:7316
static void calc_area_normal_and_center_node_mesh(const Object &object, const Span< float3 > vert_positions, const Span< float3 > vert_normals, const Span< bool > hide_vert, const Brush &brush, const bool use_area_nos, const bool use_area_cos, const bke::pbvh::MeshNode &node, SampleLocalData &tls, AreaNormalCenterData &anctd)
Definition sculpt.cc:1391
void gather_grids_normals(const SubdivCCG &subdiv_ccg, Span< int > grids, MutableSpan< float3 > normals)
Definition sculpt.cc:6079
void do_inflate_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition inflate.cc:133
void calc_area_normal_and_center(const Depsgraph &depsgraph, const Brush &brush, const Object &ob, const IndexMask &node_mask, float r_area_no[3], float r_area_co[3])
Definition sculpt.cc:1944
void paint_stroke_free(bContext *C, wmOperator *op, PaintStroke *stroke)
PaintStroke * paint_stroke_new(bContext *C, wmOperator *op, StrokeGetLocation get_location, StrokeTestStart test_start, StrokeUpdateStep update_step, StrokeRedraw redraw, StrokeDone done, int event_type)
void translations_from_offset_and_factors(const float3 &offset, Span< float > factors, MutableSpan< float3 > r_translations)
Definition sculpt.cc:7266
static float area_normal_and_center_get_normal_radius(const SculptSession &ss, const Brush &brush)
Definition sculpt.cc:1312
void do_clay_strips_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
static void do_tiled(const Depsgraph &depsgraph, const Scene &scene, const Sculpt &sd, Object &ob, const Brush &brush, UnifiedPaintSettings &ups, PaintModeSettings &paint_mode_settings, const BrushActionFunc action)
Definition sculpt.cc:3414
std::optional< OrigPositionData > orig_position_data_lookup_mesh(const Object &object, const bke::pbvh::MeshNode &node)
std::optional< Span< int > > orig_face_set_data_lookup_grids(const Object &object, const bke::pbvh::GridsNode &node)
Span< int > vert_neighbors_get_mesh(const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face, const Span< bool > hide_poly, const int vert, Vector< int > &r_neighbors)
Definition sculpt.cc:431
void calc_brush_texture_factors(const SculptSession &ss, const Brush &brush, Span< float3 > vert_positions, Span< int > vert_indices, MutableSpan< float > factors)
Definition sculpt.cc:6912
void fill_factor_from_hide(Span< bool > hide_vert, Span< int > verts, MutableSpan< float > r_factors)
Definition sculpt.cc:6456
void scatter_data_grids(const SubdivCCG &subdiv_ccg, Span< T > node_data, Span< int > grids, MutableSpan< T > dst)
Definition sculpt.cc:6146
void do_crease_brush(const Depsgraph &depsgraph, const Scene &scene, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition crease.cc:270
void do_pinch_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition pinch.cc:175
void do_gravity_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition draw.cc:211
void calc_factors_common_bmesh(const Depsgraph &depsgraph, const Brush &brush, const Object &object, Span< float3 > positions, bke::pbvh::BMeshNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6318
void do_scrape_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition plane.cc:293
void do_mask_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void do_enhance_details_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
static void accumulate_area_normal(const float3 &normal, const float distance, const float radius_inv, const int flip_index, AreaNormalCenterData &anctd)
Definition sculpt.cc:1376
bool paint_brush_tool_poll(bContext *C)
void calc_factors_common_from_orig_data_bmesh(const Depsgraph &depsgraph, const Brush &brush, const Object &object, Span< float3 > positions, Span< float3 > normals, bke::pbvh::BMeshNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6422
Span< float3 > vert_positions_for_grab_active_get(const Depsgraph &depsgraph, const Object &object)
Definition sculpt.cc:171
static float area_normal_and_center_get_position_radius(const SculptSession &ss, const Brush &brush)
Definition sculpt.cc:1321
void calc_brush_distances_squared(const SculptSession &ss, Span< float3 > vert_positions, Span< int > vert_indices, eBrushFalloffShape falloff_shape, MutableSpan< float > r_distances)
Definition sculpt.cc:6708
void do_clay_thumb_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
QuaternionBase< float > Quaternion
T length_squared(const VecBase< T, Size > &a)
VecBase< T, 3 > normal_tri(const VecBase< T, 3 > &v1, const VecBase< T, 3 > &v2, const VecBase< T, 3 > &v3)
T clamp(const T &a, const T &min, const T &max)
QuaternionBase< T > to_quaternion(const AxisAngleBase< T, AngleT > &axis_angle)
T safe_divide(const T &a, const T &b)
T distance(const T &a, const T &b)
AxisAngleBase< float, AngleRadianBase< float > > AxisAngle
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
bool is_zero(const T &a)
CartesianBasis invert(const CartesianBasis &basis)
T rcp(const T &a)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
T square(const T &a)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
T abs(const T &a)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
void isolate_task(const Function &function)
Definition BLI_task.hh:226
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:95
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
Definition BLI_task.hh:153
MatBase< float, 4, 4 > float4x4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< float, 3 > float3
float distance(float a, float b)
bool paint_convert_bb_to_rect(rcti *rect, const float bb_min[3], const float bb_max[3], const ARegion &region, const RegionView3D &rv3d, const Object &ob)
@ BRUSH_STROKE_SMOOTH
@ BRUSH_STROKE_INVERT
float paint_calc_object_space_radius(const ViewContext &vc, const blender::float3 &center, float pixel_radius)
bool paint_get_tex_pixel(const MTex *mtex, float u, float v, ImagePool *pool, int thread, float *r_intensity, float r_rgba[4])
void paint_stroke_operator_properties(wmOperatorType *ot)
const btScalar eps
Definition poly34.cpp:11
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
float RNA_float_get(PointerRNA *ptr, const char *name)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
static void stroke_undo_end(const bContext *C, Brush *brush)
Definition sculpt.cc:5175
bool SCULPT_stroke_is_first_brush_step_of_symmetry_pass(const blender::ed::sculpt_paint::StrokeCache &cache)
Definition sculpt.cc:513
bool SCULPT_get_redraw_rect(const ARegion &region, const RegionView3D &rv3d, const Object &ob, rcti &rect)
Definition sculpt.cc:1191
bool SCULPT_brush_cursor_poll(bContext *C)
Definition sculpt.cc:3617
ePaintSymmetryFlags SCULPT_mesh_symmetry_xyz_get(const Object &object)
Definition sculpt.cc:186
void SCULPT_calc_vertex_displacement(const SculptSession &ss, const Brush &brush, float rgba[3], float r_offset[3])
Definition sculpt.cc:2285
static void restore_from_undo_step_if_necessary(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob)
Definition sculpt.cc:4907
bool SCULPT_cursor_geometry_info_update(bContext *C, SculptCursorGeometryInfo *out, const float mval[2], bool use_sampled_normal)
Definition sculpt.cc:4580
StrokeFlags
Definition sculpt.cc:3706
bool SCULPT_stroke_get_location(bContext *C, float out[3], const float mval[2], bool force_original)
Definition sculpt.cc:4732
static float calc_symmetry_feather(const Sculpt &sd, const blender::ed::sculpt_paint::StrokeCache &cache)
Definition sculpt.cc:1261
static void sculpt_raycast_cb(blender::bke::pbvh::Node &node, SculptRaycastData &srd, float *tmin)
Definition sculpt.cc:4375
static void brush_stroke_init(bContext *C)
Definition sculpt.cc:4878
const float * SCULPT_brush_frontface_normal_from_falloff_shape(const SculptSession &ss, char falloff_shape)
Definition sculpt.cc:1212
Span< int > SCULPT_fake_neighbors_ensure(const Depsgraph &depsgraph, Object &ob, const float max_dist)
Definition sculpt.cc:5809
bool SCULPT_is_symmetry_iteration_valid(char i, char symm)
Definition sculpt.cc:713
bool SCULPT_brush_type_needs_all_pbvh_nodes(const Brush &brush)
Definition sculpt.cc:2754
void SCULPT_vertex_random_access_ensure(Object &object)
Definition sculpt.cc:144
static void brush_init_tex(const Sculpt &sd, SculptSession &ss)
Definition sculpt.cc:4862
static bool sculpt_needs_pbvh_pixels(PaintModeSettings &paint_mode_settings, const Brush &brush, Object &ob)
Definition sculpt.cc:2593
static bool over_mesh(bContext *C, wmOperator *, const float mval[2])
Definition sculpt.cc:5143
void SCULPT_stroke_modifiers_check(const bContext *C, Object &ob, const Brush &brush)
Definition sculpt.cc:4358
void sculpt_apply_texture(const SculptSession &ss, const Brush &brush, const float brush_point[3], const int thread_id, float *r_value, float r_rgba[4])
Definition sculpt.cc:2219
static void sculpt_pbvh_update_pixels(const Depsgraph &depsgraph, PaintModeSettings &paint_mode_settings, Object &ob)
Definition sculpt.cc:2608
bool SCULPT_vertex_is_occluded(const Depsgraph &depsgraph, const Object &object, const float3 &position, bool original)
Definition sculpt.cc:5838
static const char * sculpt_brush_type_name(const Sculpt &sd)
Definition sculpt.cc:3623
float SCULPT_raycast_init(ViewContext *vc, const float mval[2], float ray_start[3], float ray_end[3], float ray_normal[3], bool original)
Definition sculpt.cc:4536
void SCULPT_cache_calc_brushdata_symm(blender::ed::sculpt_paint::StrokeCache &cache, const ePaintSymmetryFlags symm, const char axis, const float angle)
Definition sculpt.cc:3346
bool SCULPT_stroke_get_location_ex(bContext *C, float out[3], const float mval[2], bool force_original, bool check_closest, bool limit_closest_radius)
Definition sculpt.cc:4743
static void sculpt_find_nearest_to_ray_cb(blender::bke::pbvh::Node &node, SculptFindNearestToRayData &srd, float *tmin)
Definition sculpt.cc:4478
bool SCULPT_mode_poll_view3d(bContext *C)
Definition sculpt.cc:3566
float3 SCULPT_flip_v3_by_symm_area(const float3 &vector, const ePaintSymmetryFlags symm, const ePaintSymmetryAreas symmarea, const float3 &pivot)
Definition sculpt.cc:2714
bool SCULPT_mode_poll(bContext *C)
Definition sculpt.cc:3560
static void stroke_undo_begin(const bContext *C, wmOperator *op)
Definition sculpt.cc:5154
static bool is_brush_related_tool(bContext *C)
Definition sculpt.cc:3585
bool SCULPT_stroke_is_main_symmetry_pass(const blender::ed::sculpt_paint::StrokeCache &cache)
Definition sculpt.cc:501
#define SCULPT_TILT_SENSITIVITY
Definition sculpt.cc:2549
static void extend_redraw_rect_previous(Object &ob, rcti &rect)
Definition sculpt.cc:1170
static void flip_qt(float quat[4], const ePaintSymmetryFlags symm)
Definition sculpt.cc:2709
static void flip_qt_qt(float out[4], const float in[4], const ePaintSymmetryFlags symm)
Definition sculpt.cc:2686
int SCULPT_vertex_count_get(const Object &object)
Definition sculpt.cc:153
void sculpt_project_v3_normal_align(const SculptSession &ss, const float normal_weight, float grab_delta[3])
Definition sculpt.cc:538
static void update_brush_local_mat(const Sculpt &sd, Object &ob)
Definition sculpt.cc:2574
void SCULPT_cube_tip_init(const Sculpt &, const Object &ob, const Brush &brush, float mat[4][4])
Definition sculpt.cc:6038
void SCULPT_fake_neighbors_free(Object &ob)
Definition sculpt.cc:5831
bool SCULPT_is_vertex_inside_brush_radius_symm(const float vertex[3], const float br_co[3], float radius, char symm)
Definition sculpt.cc:718
bool SCULPT_check_vertex_pivot_symmetry(const float vco[3], const float pco[3], const char symm)
Definition sculpt.cc:519
bool SCULPT_handles_colors_report(const Object &object, ReportList *reports)
Definition sculpt.cc:5191
void SCULPT_tilt_apply_to_normal(float r_normal[3], blender::ed::sculpt_paint::StrokeCache *cache, const float tilt_strength)
Definition sculpt.cc:2550
bool SCULPT_poll(bContext *C)
Definition sculpt.cc:3572
ePaintSymmetryAreas SCULPT_get_vertex_symm_area(const float co[3])
Definition sculpt.cc:2671
static float calc_overlap(const blender::ed::sculpt_paint::StrokeCache &cache, const ePaintSymmetryFlags symm, const char axis, const float angle)
Definition sculpt.cc:1225
float SCULPT_brush_plane_offset_get(const Sculpt &sd, const SculptSession &ss)
Definition sculpt.cc:2883
static float brush_strength(const Sculpt &sd, const blender::ed::sculpt_paint::StrokeCache &cache, const float feather, const UnifiedPaintSettings &ups, const PaintModeSettings &)
Definition sculpt.cc:2067
void SCULPT_tilt_effective_normal_get(const SculptSession &ss, const Brush &brush, float r_no[3])
Definition sculpt.cc:2568
void SCULPT_flip_quat_by_symm_area(float quat[4], const ePaintSymmetryFlags symm, const ePaintSymmetryAreas symmarea, const float pivot[3])
Definition sculpt.cc:2735
bool SCULPT_stroke_is_first_brush_step(const blender::ed::sculpt_paint::StrokeCache &cache)
Definition sculpt.cc:507
static float calc_radial_symmetry_feather(const Sculpt &sd, const blender::ed::sculpt_paint::StrokeCache &cache, const ePaintSymmetryFlags symm, const char axis)
Definition sculpt.cc:1246
#define PIXEL_INPUT_THRESHHOLD
void SCULPT_tag_update_overlays(bContext *C)
Definition sculpt.cc:735
#define SCULPT_RAKE_BRUSH_FACTOR
#define FAKE_NEIGHBOR_NONE
bool SCULPT_brush_type_is_mask(int tool)
BLI_INLINE bool SCULPT_brush_type_is_attribute_only(int tool)
bool SCULPT_brush_type_is_paint(int tool)
bool SCULPT_use_image_paint_brush(PaintModeSettings &settings, Object &ob)
bool SCULPT_paint_image_canvas_get(PaintModeSettings &paint_mode_settings, Object &ob, Image **r_image, ImageUser **r_image_user) ATTR_NONNULL()
Get the image canvas for painting on the given object.
unsigned char uint8_t
Definition stdint.h:78
float co[3]
CustomData vdata
float topology_rake_factor
char sculpt_brush_type
int sculpt_plane
int cloth_deform_type
float area_radius_factor
int snake_hook_deform_type
float density
float normal_radius_factor
struct MTex mtex
float normal_weight
float rake_factor
short ob_mode
int curve_preset
struct CurveMapping * curve
float tip_scale_x
float texture_sample_bias
float plane_trim
char falloff_shape
float tilt_strength_factor
float hardness
char mask_tool
int smooth_deform_type
float wet_mix
float wet_persistence
int deform_target
float plane_offset
float tip_roundness
float autosmooth_factor
int paint_flags
int grid_size
Definition BKE_ccg.hh:33
int grid_area
Definition BKE_ccg.hh:35
char name[66]
Definition DNA_ID.h:425
void * data
char brush_map_mode
float ofs[3]
float size[3]
struct Tex * tex
char symmetry
int edges_num
int verts_num
struct Object * mirror_ob
ObjectRuntimeHandle * runtime
ListBase modifiers
float loc[3]
float scale[3]
struct SculptSession * sculpt
float tile_offset[3]
int symmetry_flags
float viewinv[4][4]
struct ToolSettings * toolsettings
struct bToolRef * tool
ScrArea_Runtime runtime
blender::float3 active_vertex_co
blender::Array< int > fake_neighbor_index
Definition BKE_paint.hh:366
Span< blender::int3 > corner_tris
Definition sculpt.cc:2665
const float * ray_normal
Definition sculpt.cc:2657
const SubdivCCG * subdiv_ccg
Definition sculpt.cc:2668
blender::VArraySpan< bool > hide_poly
Definition sculpt.cc:2666
blender::OffsetIndices< int > faces
Definition sculpt.cc:2663
Span< float3 > vert_positions
Definition sculpt.cc:2662
const float * ray_start
Definition sculpt.cc:2657
blender::float3 follow_co
blender::OffsetIndices< int > faces
Definition sculpt.cc:2639
int active_face_grid_index
Definition sculpt.cc:2649
blender::VArraySpan< bool > hide_poly
Definition sculpt.cc:2642
Object * object
Definition sculpt.cc:2631
const SubdivCCG * subdiv_ccg
Definition sculpt.cc:2644
const float * ray_normal
Definition sculpt.cc:2634
IsectRayPrecalc isect_precalc
Definition sculpt.cc:2651
Span< blender::float3 > vert_positions
Definition sculpt.cc:2638
Span< int > corner_verts
Definition sculpt.cc:2640
Span< blender::int3 > corner_tris
Definition sculpt.cc:2641
const float * ray_start
Definition sculpt.cc:2633
SculptSession * ss
Definition sculpt.cc:2632
ActiveVert active_vertex
Definition sculpt.cc:2646
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:427
BMLog * bm_log
Definition BKE_paint.hh:402
std::optional< int > active_grid_index
Definition BKE_paint.hh:433
RegionView3D * rv3d
Definition BKE_paint.hh:446
void clear_active_vert(bool persist_last_active)
Definition paint.cc:2245
blender::ed::sculpt_paint::filter::Cache * filter_cache
Definition BKE_paint.hh:428
std::optional< int > active_face_index
Definition BKE_paint.hh:432
KeyBlock * shapekey_active
Definition BKE_paint.hh:387
blender::float3 cursor_normal
Definition BKE_paint.hh:441
SculptVertexInfo vertex_info
Definition BKE_paint.hh:458
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
blender::float3 cursor_view_normal
Definition BKE_paint.hh:443
struct SculptSession::@251246223064352150223005211001050162321211037052 multires
float cursor_radius
Definition BKE_paint.hh:439
ActiveVert active_vert() const
Definition paint.cc:2180
blender::float3 cursor_location
Definition BKE_paint.hh:440
blender::float3 active_vert_position(const Depsgraph &depsgraph, const Object &object) const
Definition paint.cc:2224
ImagePool * tex_pool
Definition BKE_paint.hh:425
std::unique_ptr< SculptTopologyIslandCache > topology_island_cache
Definition BKE_paint.hh:513
View3D * v3d
Definition BKE_paint.hh:447
blender::Array< blender::float3x3, 0 > deform_imats
Definition BKE_paint.hh:415
MultiresModifierData * modifier
Definition BKE_paint.hh:383
blender::float3 cursor_sampled_normal
Definition BKE_paint.hh:442
SculptFakeNeighbors fake_neighbors
Definition BKE_paint.hh:459
bool deform_modifiers_active
Definition BKE_paint.hh:411
void set_active_vert(ActiveVert vert)
Definition paint.cc:2258
blender::Array< uint8_t > vert_island_ids
Definition BKE_paint.hh:374
blender::BitVector boundary
Definition BKE_paint.hh:351
struct Object * gravity_object
float detail_percent
int radial_symm[3]
float detail_size
float gravity_factor
float constant_detail
blender::Vector< SubdivCCGCoord, 256 > coords
blender::Array< blender::float3 > normals
blender::BitGroupVector grid_hidden
blender::Array< float > masks
blender::Array< blender::float3 > positions
struct bNodeTree * nodetree
struct PaintModeSettings paint_mode
struct UnifiedPaintSettings unified_paint_settings
View3DShading shading
RegionView3D * rv3d
Definition ED_view3d.hh:76
ARegion * region
Definition ED_view3d.hh:73
Scene * scene
Definition ED_view3d.hh:69
View3D * v3d
Definition ED_view3d.hh:74
Object * obact
Definition ED_view3d.hh:71
Depsgraph * depsgraph
Definition ED_view3d.hh:68
bNodeTreeRuntimeHandle * runtime
ListBase areabase
bToolRef_Runtime * runtime
const c_style_mat & ptr() const
Span< int > verts() const
static NearestVertData join(const NearestVertData &a, const NearestVertData &b)
Definition sculpt.cc:5535
std::optional< math::Quaternion > rake_rotation
std::unique_ptr< auto_mask::Cache > automasking
struct blender::ed::sculpt_paint::StrokeCache::@071376261162074003032026334226365275312312340070 clay_thumb_brush
std::optional< math::Quaternion > rake_rotation_symm
struct blender::ed::sculpt_paint::StrokeCache::@261300056333112274033101043253304111230017234302 paint_brush
struct blender::ed::sculpt_paint::StrokeCache::@023327346277034157315226366126266322372173113025 mirror_modifier_clip
std::unique_ptr< cloth::SimulationData > cloth_sim
std::array< float, 10 > pressure_stabilizer
int ymin
int ymax
int xmin
int xmax
int mval[2]
Definition WM_types.hh:728
short type
Definition WM_types.hh:722
const char * name
Definition WM_types.hh:990
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
struct ReportList * reports
struct wmOperatorType * type
struct PointerRNA * ptr
VecBase< float, 4 > float4
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4126
wmOperatorType * ot
Definition wm_files.cc:4125
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
bScreen * WM_window_get_active_screen(const wmWindow *win)