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
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{
236 int face_set = SCULPT_FACE_SET_NONE;
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()) {
260 return face_set == SCULPT_FACE_SET_NONE;
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()) {
273 return face_set == SCULPT_FACE_SET_NONE;
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,
324 const OffsetIndices<int> faces,
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
754
755/* -------------------------------------------------------------------- */
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
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/* -------------------------------------------------------------------- */
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
848/* -------------------------------------------------------------------- */
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();
868 bke::SpanAttributeWriter<float> mask = attributes.lookup_or_add_for_write_span<float>(
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);
876 bke::pbvh::node_update_mask_mesh(mask.span, nodes[i]);
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) {
888 for (BMVert *vert : BKE_pbvh_bmesh_node_unique_verts(&nodes[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);
891 bke::pbvh::node_update_mask_bmesh(offset, nodes[i]);
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 }
919 bke::pbvh::node_update_mask_grids(key, masks, nodes[i]);
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
1287/* -------------------------------------------------------------------- */
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());
1661 orig_position_data_gather_bmesh(*ss.bm_log, verts, positions, normals);
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 }
1810 const Span<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
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
1867 anctd = threading::parallel_reduce(
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 }
1890 case bke::pbvh::Type::BMesh: {
1891 const bool has_bm_orco = ss.bm && dyntopo::stroke_is_dyntopo(ob, brush);
1892
1894 anctd = threading::parallel_reduce(
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 }
1916 case bke::pbvh::Type::Grids: {
1917 const Span<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
1918 anctd = threading::parallel_reduce(
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 },
1929 calc_area_normal_and_center_reduce);
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
1966 anctd = threading::parallel_reduce(
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 }
1989 case bke::pbvh::Type::BMesh: {
1990 const bool has_bm_orco = ss.bm && dyntopo::stroke_is_dyntopo(ob, brush);
1991
1993 anctd = threading::parallel_reduce(
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 }
2008 case bke::pbvh::Type::Grids: {
2009 const Span<bke::pbvh::GridsNode> nodes = pbvh.nodes<bke::pbvh::GridsNode>();
2010 anctd = threading::parallel_reduce(
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 },
2021 calc_area_normal_and_center_reduce);
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
2058/* -------------------------------------------------------------------- */
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) {
2249 mul_m4_v3(cache.symm_rot_mat_inv.ptr(), point);
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);
2582 calc_brush_local_mat(
2583 mask_tex->rot, ob, cache->brush_local_mat.ptr(), cache->brush_local_mat_inv.ptr());
2584 }
2585}
2586
2589/* -------------------------------------------------------------------- */
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
2626/* -------------------------------------------------------------------- */
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
2706 axis_angle_normalized_to_quat(out, axis, angle);
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{
2719 float3 result = vector;
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) {
2726 result = blender::ed::sculpt_paint::symmetry_flip(result, symm_it);
2727 }
2728 if (pivot[i] < 0.0f) {
2729 result = blender::ed::sculpt_paint::symmetry_flip(result, symm_it);
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
2898/* -------------------------------------------------------------------- */
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;
3352 cache.location_symm = ed::sculpt_paint::symmetry_flip(cache.location, symm);
3353 cache.last_location_symm = ed::sculpt_paint::symmetry_flip(cache.last_location, symm);
3354 cache.grab_delta_symm = ed::sculpt_paint::symmetry_flip(cache.grab_delta, symm);
3355 cache.view_normal_symm = ed::sculpt_paint::symmetry_flip(cache.view_normal, symm);
3356
3357 cache.initial_location_symm = ed::sculpt_paint::symmetry_flip(cache.initial_location, symm);
3358 cache.initial_normal_symm = ed::sculpt_paint::symmetry_flip(cache.initial_normal, symm);
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
3375 cache.symm_rot_mat = float4x4::identity();
3376 cache.symm_rot_mat_inv = float4x4::identity();
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) {
3389 cache.gravity_direction_symm = ed::sculpt_paint::symmetry_flip(cache.gravity_direction, symm);
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'];
3498 SCULPT_cache_calc_brushdata_symm(*ss.cache, symm, axis, angle);
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
3618{
3619 using namespace blender::ed::sculpt_paint;
3620 return SCULPT_mode_poll(C) && (paint_brush_cursor_poll(C) || is_brush_related_tool(C));
3621}
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
3700{
3701 MEM_SAFE_FREE(this->dial);
3702}
3703
3704} // namespace blender::ed::sculpt_paint
3705
3706enum class StrokeFlags : uint8_t {
3707 ClipX = 1,
3708 ClipY = 2,
3709 ClipZ = 4,
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{
3717 ss.cache->mirror_modifier_clip.mat = float4x4::identity();
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
3752static void smooth_brush_toggle_on(const bContext *C, Paint *paint, StrokeCache *cache)
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
3794static void smooth_brush_toggle_off(const bContext *C, Paint *paint, StrokeCache *cache)
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);
4234 UnifiedPaintSettings &ups = scene.toolsettings->unified_paint_settings;
4235 SculptSession &ss = *ob.sculpt;
4236 StrokeCache &cache = *ss.cache;
4237 Brush &brush = *BKE_paint_brush(&sd.paint);
4238
4240 !((brush.flag & BRUSH_ANCHORED) ||
4243 cloth::is_cloth_deform_brush(brush)))
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 {
4369 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
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 =
4390 orig_position_data_lookup_mesh_all_verts(
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 =
4494 orig_position_data_lookup_mesh_all_verts(
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;
4587 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
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);
4607 zero_v3(out->active_vertex_co);
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);
4623 srd.vert_positions = bke::pbvh::vert_positions_eval(*depsgraph, ob);
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
4638 isect_ray_tri_watertight_v3_precalc(&srd.isect_precalc, ray_normal);
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);
4650 zero_v3(out->active_vertex_co);
4651 ss.clear_active_vert(true);
4652 return false;
4653 }
4654
4655 /* Update the active vertex of the SculptSession. */
4656 ss.set_active_vert(srd.active_vertex);
4657 out->active_vertex_co = ss.active_vert_position(*depsgraph, ob);
4658
4659 switch (pbvh->type()) {
4661 ss.active_face_index = srd.active_face_grid_index;
4662 ss.active_grid_index = std::nullopt;
4663 break;
4665 ss.active_face_index = std::nullopt;
4666 ss.active_grid_index = srd.active_face_grid_index;
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);
4694 copy_v3_v3(ss.cursor_normal, srd.face_normal);
4695 copy_v3_v3(ss.cursor_location, out->location);
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;
4752 Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
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);
4825 srd.vert_positions = bke::pbvh::vert_positions_eval(*depsgraph, ob);
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 {
4929 undo::restore_from_undo_step(depsgraph, sd, ob);
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
4946 undo::restore_from_undo_step(depsgraph, sd, ob);
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
4970 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
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 /* Updating mesh positions without marking caches dirty is generally not good, but since
5028 * sculpt mode has special requirements and is expected to have sole ownership of the mesh it
5029 * modifies, it's generally okay. */
5030 if (use_pbvh_draw) {
5031 /* When drawing from bke::pbvh::Tree is used, vertex and face normals are updated
5032 * later in #bke::pbvh::update_normals. However, we update the mesh's bounds eagerly here
5033 * since they are trivial to access from the bke::pbvh::Tree. Updating the
5034 * object's evaluated geometry bounding box is necessary because sculpt strokes don't cause
5035 * an object reevaluation. */
5036 mesh->tag_positions_changed_no_normals();
5037 /* Sculpt mode does not use or recalculate face corner normals, so they are cleared. */
5038 mesh->runtime->corner_normals_cache.tag_dirty();
5039 }
5040 else {
5041 /* Drawing happens from the modifier stack evaluation result.
5042 * Tag both coordinates and normals as modified, as both needed for proper drawing and the
5043 * modifier stack is not guaranteed to tag normals for update. */
5044 mesh->tag_positions_changed();
5045 }
5046
5047 mesh->bounds_set_eager(bke::pbvh::bounds_get(pbvh));
5048 if (ob.runtime->bounds_eval) {
5049 ob.runtime->bounds_eval = mesh->bounds_min_max();
5050 }
5051 }
5052 }
5053}
5054
5055void flush_update_done(const bContext *C, Object &ob, UpdateType update_type)
5056{
5057 /* After we are done drawing the stroke, check if we need to do a more
5058 * expensive depsgraph tag to update geometry. */
5060 RegionView3D *current_rv3d = CTX_wm_region_view3d(C);
5061 SculptSession &ss = *ob.sculpt;
5062 Mesh *mesh = static_cast<Mesh *>(ob.data);
5063
5064 /* Always needed for linked duplicates. */
5065 bool need_tag = (ID_REAL_USERS(&mesh->id) > 1);
5066
5067 if (current_rv3d) {
5068 current_rv3d->rflag &= ~RV3D_PAINTING;
5069 }
5070
5071 LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
5072 bScreen *screen = WM_window_get_active_screen(win);
5073 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
5074 SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
5075 if (sl->spacetype != SPACE_VIEW3D) {
5076 continue;
5077 }
5078
5079 /* Tag all 3D viewports for redraw now that we are done. Others
5080 * viewports did not get a full redraw, and anti-aliasing for the
5081 * current viewport was deactivated. */
5082 LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
5083 if (region->regiontype == RGN_TYPE_WINDOW) {
5084 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
5085 if (rv3d != current_rv3d) {
5086 need_tag |= !BKE_sculptsession_use_pbvh_draw(&ob, rv3d);
5087 }
5088
5089 ED_region_tag_redraw(region);
5090 }
5091 }
5092 }
5093
5094 if (update_type == UpdateType::Image) {
5095 LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
5096 SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
5097 if (sl->spacetype != SPACE_IMAGE) {
5098 continue;
5099 }
5101 }
5102 }
5103 }
5104
5105 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
5106
5107 if (update_type == UpdateType::Position) {
5108 bke::pbvh::store_bounds_orig(pbvh);
5109
5110 /* Coordinates were modified, so fake neighbors are not longer valid. */
5112 }
5113
5114 if (update_type == UpdateType::Position) {
5115 if (pbvh.type() == bke::pbvh::Type::BMesh) {
5117 }
5118 }
5119
5120 if (need_tag) {
5122 }
5123}
5124
5125} // namespace blender::ed::sculpt_paint
5126
5127/* Returns whether the mouse/stylus is over the mesh (1)
5128 * or over the background (0). */
5129static bool over_mesh(bContext *C, wmOperator * /*op*/, const float mval[2])
5130{
5131 float co_dummy[3];
5133 Brush *brush = BKE_paint_brush(&sd->paint);
5134
5135 bool check_closest = brush->falloff_shape == PAINT_FALLOFF_SHAPE_TUBE;
5136
5137 return SCULPT_stroke_get_location_ex(C, co_dummy, mval, false, check_closest, true);
5138}
5139
5140static void stroke_undo_begin(const bContext *C, wmOperator *op)
5141{
5142 using namespace blender::ed::sculpt_paint;
5143 const Scene &scene = *CTX_data_scene(C);
5145 const Sculpt &sd = *CTX_data_tool_settings(C)->sculpt;
5146 const Brush *brush = BKE_paint_brush_for_read(&sd.paint);
5147 ToolSettings *tool_settings = CTX_data_tool_settings(C);
5148
5149 /* Setup the correct undo system. Image painting and sculpting are mutual exclusive.
5150 * Color attributes are part of the sculpting undo system. */
5151 if (brush && brush->sculpt_brush_type == SCULPT_BRUSH_TYPE_PAINT &&
5152 SCULPT_use_image_paint_brush(tool_settings->paint_mode, ob))
5153 {
5155 }
5156 else {
5157 undo::push_begin_ex(scene, ob, sculpt_brush_type_name(sd));
5158 }
5159}
5160
5161static void stroke_undo_end(const bContext *C, Brush *brush)
5162{
5163 using namespace blender::ed::sculpt_paint;
5165 ToolSettings *tool_settings = CTX_data_tool_settings(C);
5166
5167 if (brush && brush->sculpt_brush_type == SCULPT_BRUSH_TYPE_PAINT &&
5168 SCULPT_use_image_paint_brush(tool_settings->paint_mode, ob))
5169 {
5171 }
5172 else {
5173 undo::push_end(ob);
5174 }
5175}
5176
5178{
5179 switch (blender::bke::object::pbvh_get(object)->type()) {
5181 return true;
5183 BKE_report(reports, RPT_ERROR, "Not supported in dynamic topology mode");
5184 return false;
5186 BKE_report(reports, RPT_ERROR, "Not supported in multiresolution mode");
5187 return false;
5188 }
5190 return false;
5191}
5192
5193namespace blender::ed::sculpt_paint {
5194
5195static bool stroke_test_start(bContext *C, wmOperator *op, const float mval[2])
5196{
5197 /* Don't start the stroke until `mval` goes over the mesh.
5198 * NOTE: `mval` will only be null when re-executing the saved stroke.
5199 * We have exception for 'exec' strokes since they may not set `mval`,
5200 * only 'location', see: #52195. */
5201 if (((op->flag & OP_IS_INVOKE) == 0) || (mval == nullptr) || over_mesh(C, op, mval)) {
5203 SculptSession &ss = *ob.sculpt;
5205 Brush *brush = BKE_paint_brush(&sd.paint);
5206 ToolSettings *tool_settings = CTX_data_tool_settings(C);
5207
5208 /* NOTE: This should be removed when paint mode is available. Paint mode can force based on the
5209 * canvas it is painting on. (ref. use_sculpt_texture_paint). */
5210 if (brush && SCULPT_brush_type_is_paint(brush->sculpt_brush_type) &&
5211 !SCULPT_use_image_paint_brush(tool_settings->paint_mode, ob))
5212 {
5213 View3D *v3d = CTX_wm_view3d(C);
5214 if (v3d->shading.type == OB_SOLID) {
5216 }
5217 }
5218
5220
5221 sculpt_update_cache_invariants(C, sd, ss, op, mval);
5222
5224 SCULPT_cursor_geometry_info_update(C, &sgi, mval, false);
5225
5226 stroke_undo_begin(C, op);
5227
5228 return true;
5229 }
5230 return false;
5231}
5232
5234 wmOperator * /*op*/,
5235 PaintStroke *stroke,
5236 PointerRNA *itemptr)
5237{
5239 const Scene &scene = *CTX_data_scene(C);
5240 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
5243 SculptSession &ss = *ob.sculpt;
5244 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
5245 ToolSettings &tool_settings = *CTX_data_tool_settings(C);
5246 StrokeCache *cache = ss.cache;
5248
5249 SCULPT_stroke_modifiers_check(C, ob, brush);
5250 sculpt_update_cache_variants(C, sd, ob, itemptr);
5252
5253 if (dyntopo::stroke_is_dyntopo(ob, brush)) {
5255 depsgraph, scene, sd, ob, dynamic_topology_update, ups, tool_settings.paint_mode);
5256 }
5257
5259 depsgraph, scene, sd, ob, do_brush_action, ups, tool_settings.paint_mode);
5260
5261 /* Hack to fix noise texture tearing mesh. */
5262 sculpt_fix_noise_tear(sd, ob);
5263
5264 ss.cache->first_time = false;
5266
5267 /* Cleanup. */
5269 flush_update_step(C, UpdateType::Mask);
5270 }
5272 if (SCULPT_use_image_paint_brush(tool_settings.paint_mode, ob)) {
5273 flush_update_step(C, UpdateType::Image);
5274 }
5275 else {
5276 flush_update_step(C, UpdateType::Color);
5277 }
5278 }
5279 else {
5280 flush_update_step(C, UpdateType::Position);
5281 }
5282}
5283
5284static void brush_exit_tex(Sculpt &sd)
5285{
5286 Brush *brush = BKE_paint_brush(&sd.paint);
5287 const MTex *mask_tex = BKE_brush_mask_texture_get(brush, OB_MODE_SCULPT);
5288
5289 if (mask_tex->tex && mask_tex->tex->nodetree) {
5290 ntreeTexEndExecTree(mask_tex->tex->nodetree->runtime->execdata);
5291 }
5292}
5293
5294static void stroke_done(const bContext *C, PaintStroke * /*stroke*/)
5295{
5297 SculptSession &ss = *ob.sculpt;
5299 ToolSettings *tool_settings = CTX_data_tool_settings(C);
5300
5301 /* Finished. */
5302 if (!ss.cache) {
5303 brush_exit_tex(sd);
5304 return;
5305 }
5307 Brush *brush = BKE_paint_brush(&sd.paint);
5308 BLI_assert(brush == ss.cache->brush); /* const, so we shouldn't change. */
5309 ups->draw_inverted = false;
5310
5311 SCULPT_stroke_modifiers_check(C, ob, *brush);
5312
5313 /* Alt-Smooth. */
5314 if (ss.cache->alt_smooth) {
5315 smooth_brush_toggle_off(C, &sd.paint, ss.cache);
5316 /* Refresh the brush pointer in case we switched brush in the toggle function. */
5317 brush = BKE_paint_brush(&sd.paint);
5318 }
5319
5320 MEM_delete(ss.cache);
5321 ss.cache = nullptr;
5322
5323 stroke_undo_end(C, brush);
5324
5326 flush_update_done(C, ob, UpdateType::Mask);
5327 }
5328 else if (brush->sculpt_brush_type == SCULPT_BRUSH_TYPE_PAINT) {
5329 if (SCULPT_use_image_paint_brush(tool_settings->paint_mode, ob)) {
5330 flush_update_done(C, ob, UpdateType::Image);
5331 }
5332 else {
5333 flush_update_done(C, ob, UpdateType::Color);
5334 }
5335 }
5336 else {
5337 flush_update_done(C, ob, UpdateType::Position);
5338 }
5339
5341 brush_exit_tex(sd);
5342}
5343
5345{
5346 PaintStroke *stroke;
5347 int ignore_background_click;
5348 int retval;
5350 Scene &scene = *CTX_data_scene(C);
5351 const View3D *v3d = CTX_wm_view3d(C);
5352 const Base *base = CTX_data_active_base(C);
5353 /* Test that ob is visible; otherwise we won't be able to get evaluated data
5354 * from the depsgraph. We do this here instead of SCULPT_mode_poll
5355 * to avoid falling through to the translate operator in the
5356 * global view3d keymap. */
5357 if (!BKE_base_is_visible(v3d, base)) {
5358 return OPERATOR_CANCELLED;
5359 }
5360
5362
5364 Brush &brush = *BKE_paint_brush(&sd.paint);
5365
5368 {
5369 return OPERATOR_CANCELLED;
5370 }
5374 }
5377 {
5378 return OPERATOR_CANCELLED;
5379 }
5380 if (ELEM(brush.sculpt_brush_type,
5383 {
5385 if (!pbvh || pbvh->type() != bke::pbvh::Type::Grids) {
5386 BKE_report(op->reports, RPT_ERROR, "Only supported in multiresolution mode");
5387 return OPERATOR_CANCELLED;
5388 }
5389 }
5390
5391 stroke = paint_stroke_new(C,
5392 op,
5396 nullptr,
5398 event->type);
5399
5400 op->customdata = stroke;
5401
5402 /* For tablet rotation. */
5403 ignore_background_click = RNA_boolean_get(op->ptr, "ignore_background_click");
5404 const float mval[2] = {float(event->mval[0]), float(event->mval[1])};
5405 if (ignore_background_click && !over_mesh(C, op, mval)) {
5406 paint_stroke_free(C, op, static_cast<PaintStroke *>(op->customdata));
5407 return OPERATOR_PASS_THROUGH;
5408 }
5409
5410 retval = op->type->modal(C, op, event);
5412 paint_stroke_free(C, op, static_cast<PaintStroke *>(op->customdata));
5413 return retval;
5414 }
5415 /* Add modal handler. */
5417
5418 OPERATOR_RETVAL_CHECK(retval);
5420
5422}
5423
5425{
5427
5429 op,
5433 nullptr,
5435 0);
5436
5437 /* Frees op->customdata. */
5438 paint_stroke_exec(C, op, static_cast<PaintStroke *>(op->customdata));
5439
5440 return OPERATOR_FINISHED;
5441}
5442
5444{
5445 using namespace blender::ed::sculpt_paint;
5446 const Depsgraph &depsgraph = *CTX_data_depsgraph_pointer(C);
5448 SculptSession &ss = *ob.sculpt;
5450 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
5451
5452 /* XXX Canceling strokes that way does not work with dynamic topology,
5453 * user will have to do real undo for now. See #46456. */
5454 if (ss.cache && !dyntopo::stroke_is_dyntopo(ob, brush)) {
5455 undo::restore_from_undo_step(depsgraph, sd, ob);
5456 }
5457
5458 paint_stroke_cancel(C, op, static_cast<PaintStroke *>(op->customdata));
5459
5460 MEM_delete(ss.cache);
5461 ss.cache = nullptr;
5462
5463 brush_exit_tex(sd);
5464}
5465
5466static int brush_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
5467{
5468 return paint_stroke_modal(C, op, event, (PaintStroke **)&op->customdata);
5469}
5470
5471static void redo_empty_ui(bContext * /*C*/, wmOperator * /*op*/) {}
5472
5474{
5475 /* Identifiers. */
5476 ot->name = "Sculpt";
5477 ot->idname = "SCULPT_OT_brush_stroke";
5478 ot->description = "Sculpt a stroke into the geometry";
5479
5480 /* API callbacks. */
5484 ot->poll = SCULPT_poll;
5486 ot->ui = redo_empty_ui;
5487
5488 /* Flags (sculpt does its own undo? (ton)). */
5490
5491 /* Properties. */
5492
5494
5496 "ignore_background_click",
5497 false,
5498 "Ignore Background Click",
5499 "Clicks on the background do not start the stroke");
5500}
5501
5502/* Fake Neighbors. */
5503
5504static void fake_neighbor_init(Object &object, const float max_dist)
5505{
5506 SculptSession &ss = *object.sculpt;
5507 const int totvert = SCULPT_vertex_count_get(object);
5510}
5511
5516
5518 int vert = -1;
5519 float distance_sq = std::numeric_limits<float>::max();
5520
5522 {
5523 NearestVertData joined = a;
5524 if (joined.vert == -1) {
5525 joined.vert = b.vert;
5526 joined.distance_sq = b.distance_sq;
5527 }
5528 else if (b.distance_sq < joined.distance_sq) {
5529 joined.vert = b.vert;
5530 joined.distance_sq = b.distance_sq;
5531 }
5532 return joined;
5533 }
5534};
5535
5537 const Span<float3> vert_positions,
5538 const Span<bool> hide_vert,
5539 const float3 &location,
5540 const float max_distance_sq,
5541 const int island_id,
5542 const bke::pbvh::MeshNode &node,
5543 NearestVertData &nvtd)
5544{
5545 for (const int vert : node.verts()) {
5546 if (!hide_vert.is_empty() && hide_vert[vert]) {
5547 continue;
5548 }
5550 continue;
5551 }
5552 if (islands::vert_id_get(ss, vert) == island_id) {
5553 continue;
5554 }
5555 const float distance_sq = math::distance_squared(vert_positions[vert], location);
5556 if (distance_sq < max_distance_sq && distance_sq < nvtd.distance_sq) {
5557 nvtd.vert = vert;
5558 nvtd.distance_sq = distance_sq;
5559 }
5560 }
5561}
5562
5564 const CCGKey &key,
5565 const Span<float3> positions,
5566 const BitGroupVector<> &grid_hidden,
5567 const float3 &location,
5568 const float max_distance_sq,
5569 const int island_id,
5570 const bke::pbvh::GridsNode &node,
5571 NearestVertData &nvtd)
5572{
5573 for (const int grid : node.grids()) {
5574 const IndexRange grid_range = bke::ccg::grid_range(key, grid);
5575 BKE_subdiv_ccg_foreach_visible_grid_vert(key, grid_hidden, grid, [&](const int offset) {
5576 const int vert = grid_range[offset];
5578 return;
5579 }
5580 if (islands::vert_id_get(ss, vert) == island_id) {
5581 return;
5582 }
5583 const float distance_sq = math::distance_squared(positions[vert], location);
5584 if (distance_sq < max_distance_sq && distance_sq < nvtd.distance_sq) {
5585 nvtd.vert = vert;
5586 nvtd.distance_sq = distance_sq;
5587 }
5588 });
5589 }
5590}
5591
5593 const float3 &location,
5594 const float max_distance_sq,
5595 const int island_id,
5596 const bke::pbvh::BMeshNode &node,
5597 NearestVertData &nvtd)
5598{
5599 for (const BMVert *bm_vert :
5601 {
5602 if (BM_elem_flag_test(bm_vert, BM_ELEM_HIDDEN)) {
5603 continue;
5604 }
5605 const int vert = BM_elem_index_get(bm_vert);
5607 continue;
5608 }
5609 if (islands::vert_id_get(ss, vert) == island_id) {
5610 continue;
5611 }
5612 const float distance_sq = math::distance_squared(float3(bm_vert->co), location);
5613 if (distance_sq < max_distance_sq && distance_sq < nvtd.distance_sq) {
5614 nvtd.vert = vert;
5615 nvtd.distance_sq = distance_sq;
5616 }
5617 }
5618}
5619
5620static void fake_neighbor_search(const Depsgraph &depsgraph,
5621 const Object &ob,
5622 const float max_distance_sq,
5623 MutableSpan<int> fake_neighbors)
5624{
5625 /* NOTE: This algorithm is extremely slow, it has O(n^2) runtime for the entire mesh. This looks
5626 * like the "closest pair of points" problem which should have far better solutions. */
5627 SculptSession &ss = *ob.sculpt;
5628 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
5629
5630 switch (pbvh.type()) {
5631 case bke::pbvh::Type::Mesh: {
5632 const Mesh &mesh = *static_cast<const Mesh *>(ob.data);
5633 const Span<float3> vert_positions = bke::pbvh::vert_positions_eval(depsgraph, ob);
5634 const bke::AttributeAccessor attributes = mesh.attributes();
5635 const VArraySpan<bool> hide_vert = *attributes.lookup<bool>(".hide_vert",
5636 bke::AttrDomain::Point);
5637 for (const int vert : vert_positions.index_range()) {
5638 if (fake_neighbors[vert] != FAKE_NEIGHBOR_NONE) {
5639 continue;
5640 }
5641 const int island_id = islands::vert_id_get(ss, vert);
5642 const float3 &location = vert_positions[vert];
5643
5644 IndexMaskMemory memory;
5645 const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
5646 pbvh, memory, [&](const bke::pbvh::Node &node) {
5647 return node_in_sphere(node, location, max_distance_sq, false);
5648 });
5649 if (nodes_in_sphere.is_empty()) {
5650 continue;
5651 }
5653 const NearestVertData nvtd = threading::parallel_reduce(
5654 nodes_in_sphere.index_range(),
5655 1,
5657 [&](const IndexRange range, NearestVertData nvtd) {
5658 nodes_in_sphere.slice(range).foreach_index([&](const int i) {
5660 vert_positions,
5661 hide_vert,
5662 location,
5663 max_distance_sq,
5664 island_id,
5665 nodes[i],
5666 nvtd);
5667 });
5668 return nvtd;
5669 },
5670 NearestVertData::join);
5671 if (nvtd.vert == -1) {
5672 continue;
5673 }
5674 fake_neighbors[vert] = nvtd.vert;
5675 fake_neighbors[nvtd.vert] = vert;
5676 }
5677 break;
5678 }
5679 case bke::pbvh::Type::Grids: {
5680 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
5681 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
5682 const Span<float3> positions = subdiv_ccg.positions;
5683 const BitGroupVector<> grid_hidden = subdiv_ccg.grid_hidden;
5684 for (const int vert : positions.index_range()) {
5685 if (fake_neighbors[vert] != FAKE_NEIGHBOR_NONE) {
5686 continue;
5687 }
5688 const int island_id = islands::vert_id_get(ss, vert);
5689 const float3 &location = positions[vert];
5690 IndexMaskMemory memory;
5691 const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
5692 pbvh, memory, [&](const bke::pbvh::Node &node) {
5693 return node_in_sphere(node, location, max_distance_sq, false);
5694 });
5695 if (nodes_in_sphere.is_empty()) {
5696 continue;
5697 }
5699 const NearestVertData nvtd = threading::parallel_reduce(
5700 nodes_in_sphere.index_range(),
5701 1,
5703 [&](const IndexRange range, NearestVertData nvtd) {
5704 nodes_in_sphere.slice(range).foreach_index([&](const int i) {
5706 key,
5707 positions,
5708 grid_hidden,
5709 location,
5710 max_distance_sq,
5711 island_id,
5712 nodes[i],
5713 nvtd);
5714 });
5715 return nvtd;
5716 },
5717 NearestVertData::join);
5718 if (nvtd.vert == -1) {
5719 continue;
5720 }
5721 fake_neighbors[vert] = nvtd.vert;
5722 fake_neighbors[nvtd.vert] = vert;
5723 }
5724 break;
5725 }
5726 case bke::pbvh::Type::BMesh: {
5727 const BMesh &bm = *ss.bm;
5728 for (const int vert : IndexRange(bm.totvert)) {
5729 if (fake_neighbors[vert] != FAKE_NEIGHBOR_NONE) {
5730 continue;
5731 }
5732 const int island_id = islands::vert_id_get(ss, vert);
5733 const float3 &location = BM_vert_at_index(&const_cast<BMesh &>(bm), vert)->co;
5734 IndexMaskMemory memory;
5735 const IndexMask nodes_in_sphere = bke::pbvh::search_nodes(
5736 pbvh, memory, [&](const bke::pbvh::Node &node) {
5737 return node_in_sphere(node, location, max_distance_sq, false);
5738 });
5739 if (nodes_in_sphere.is_empty()) {
5740 continue;
5741 }
5743 const NearestVertData nvtd = threading::parallel_reduce(
5744 nodes_in_sphere.index_range(),
5745 1,
5747 [&](const IndexRange range, NearestVertData nvtd) {
5748 nodes_in_sphere.slice(range).foreach_index([&](const int i) {
5750 ss, location, max_distance_sq, island_id, nodes[i], nvtd);
5751 });
5752 return nvtd;
5753 },
5754 NearestVertData::join);
5755 if (nvtd.vert == -1) {
5756 continue;
5757 }
5758 fake_neighbors[vert] = nvtd.vert;
5759 fake_neighbors[nvtd.vert] = vert;
5760 }
5761 break;
5762 }
5763 }
5764}
5765
5766} // namespace blender::ed::sculpt_paint
5767
5769
5771{
5772 SculptSession &ss = *object.sculpt;
5773 if (!ss.vertex_info.boundary.is_empty()) {
5774 return;
5775 }
5776
5777 Mesh *base_mesh = BKE_mesh_from_object(&object);
5778
5779 ss.vertex_info.boundary.resize(base_mesh->verts_num);
5780 Array<int> adjacent_faces_edge_count(base_mesh->edges_num, 0);
5781 array_utils::count_indices(base_mesh->corner_edges(), adjacent_faces_edge_count);
5782
5783 const Span<int2> edges = base_mesh->edges();
5784 for (const int e : edges.index_range()) {
5785 if (adjacent_faces_edge_count[e] < 2) {
5786 const int2 &edge = edges[e];
5787 ss.vertex_info.boundary[edge[0]].set();
5788 ss.vertex_info.boundary[edge[1]].set();
5789 }
5790 }
5791}
5792
5793} // namespace blender::ed::sculpt_paint::boundary
5794
5796 Object &ob,
5797 const float max_dist)
5798{
5799 using namespace blender::ed::sculpt_paint;
5800 SculptSession &ss = *ob.sculpt;
5801
5802 /* Fake neighbors were already initialized with the same distance, so no need to be
5803 * recalculated. */
5805 ss.fake_neighbors.current_max_distance == max_dist)
5806 {
5808 }
5809
5810 islands::ensure_cache(ob);
5811 fake_neighbor_init(ob, max_dist);
5812 fake_neighbor_search(depsgraph, ob, max_dist * max_dist, ss.fake_neighbors.fake_neighbor_index);
5813
5815}
5816
5818{
5819 using namespace blender::ed::sculpt_paint;
5820 SculptSession &ss = *ob.sculpt;
5821 pose_fake_neighbors_free(ss);
5822}
5823
5825 const Object &object,
5826 const float3 &position,
5827 bool original)
5828{
5829 using namespace blender;
5830 SculptSession &ss = *object.sculpt;
5831 float ray_start[3], ray_end[3], ray_normal[3];
5832
5833 ViewContext *vc = ss.cache ? ss.cache->vc : &ss.filter_cache->vc;
5834
5836 vc->region, position, ss.cache ? ss.cache->projection_mat : ss.filter_cache->viewmat);
5837
5838 int depth = SCULPT_raycast_init(vc, mouse, ray_end, ray_start, ray_normal, original);
5839
5840 negate_v3(ray_normal);
5841
5842 copy_v3_v3(ray_start, position);
5843 madd_v3_v3fl(ray_start, ray_normal, 0.002);
5844
5845 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(const_cast<Object &>(object));
5846
5847 SculptRaycastData srd = {nullptr};
5848 srd.original = original;
5849 srd.object = &const_cast<Object &>(object);
5850 srd.ss = &ss;
5851 srd.hit = false;
5852 srd.ray_start = ray_start;
5853 srd.ray_normal = ray_normal;
5854 srd.depth = depth;
5855 if (pbvh.type() == bke::pbvh::Type::Mesh) {
5856 const Mesh &mesh = *static_cast<const Mesh *>(object.data);
5858 srd.faces = mesh.faces();
5859 srd.corner_verts = mesh.corner_verts();
5860 srd.corner_tris = mesh.corner_tris();
5861 }
5862 else if (pbvh.type() == bke::pbvh::Type::Grids) {
5863 srd.subdiv_ccg = ss.subdiv_ccg;
5864 }
5865 SCULPT_vertex_random_access_ensure(const_cast<Object &>(object));
5866
5869 pbvh,
5870 [&](bke::pbvh::Node &node, float *tmin) { sculpt_raycast_cb(node, srd, tmin); },
5871 ray_start,
5872 ray_normal,
5873 srd.original);
5874
5875 return srd.hit;
5876}
5877
5879
5880int vert_id_get(const SculptSession &ss, const int vert)
5881{
5883 if (!ss.topology_island_cache) {
5884 /* The cache should be calculated whenever it's necessary.
5885 * Still avoid crashing in release builds though. */
5886 return 0;
5887 }
5889 if (!cache.vert_island_ids.is_empty()) {
5890 return cache.vert_island_ids[vert];
5891 }
5892 return 0;
5893}
5894
5896{
5897 ss.topology_island_cache.reset();
5898}
5899
5901 const int verts_num)
5902{
5903 Array<int> island_indices(verts_num);
5904 const int islands_num = vert_sets.calc_reduced_ids(island_indices);
5905 if (islands_num == 1) {
5906 return {};
5907 }
5908
5909 Array<uint8_t> island_ids(island_indices.size());
5910 threading::parallel_for(island_ids.index_range(), 4096, [&](const IndexRange range) {
5911 for (const int i : range) {
5912 island_ids[i] = uint8_t(island_indices[i]);
5913 }
5914 });
5915
5917 cache.vert_island_ids = std::move(island_ids);
5918 return cache;
5919}
5920
5922{
5923 const OffsetIndices<int> faces = mesh.faces();
5924 const Span<int> corner_verts = mesh.corner_verts();
5925 const bke::AttributeAccessor attributes = mesh.attributes();
5926 const VArraySpan<bool> hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
5927 IndexMaskMemory memory;
5928 const IndexMask visible_faces = hide_poly.is_empty() ?
5929 IndexMask(faces.size()) :
5931 faces.index_range(), hide_poly, memory);
5932
5933 AtomicDisjointSet disjoint_set(mesh.verts_num);
5934 visible_faces.foreach_index(GrainSize(1024), [&](const int face) {
5935 const Span<int> face_verts = corner_verts.slice(faces[face]);
5936 for (const int i : face_verts.index_range().drop_front(1)) {
5937 disjoint_set.join(face_verts.first(), face_verts[i]);
5938 }
5939 });
5940 return vert_disjoint_set_to_islands(disjoint_set, mesh.verts_num);
5941}
5942
5947{
5948 const SculptSession &ss = *object.sculpt;
5949 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
5950 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
5951 AtomicDisjointSet disjoint_set(subdiv_ccg.positions.size());
5952 threading::parallel_for(IndexRange(subdiv_ccg.grids_num), 512, [&](const IndexRange range) {
5953 for (const int grid : range) {
5954 SubdivCCGNeighbors neighbors;
5955 for (const short y : IndexRange(key.grid_size)) {
5956 for (const short x : IndexRange(key.grid_size)) {
5957 const SubdivCCGCoord coord{grid, x, y};
5958 SubdivCCGNeighbors neighbors;
5959 BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, true, neighbors);
5960 for (const SubdivCCGCoord neighbor : neighbors.coords) {
5961 disjoint_set.join(coord.to_index(key), neighbor.to_index(key));
5962 }
5963 }
5964 }
5965 }
5966 });
5967
5968 return vert_disjoint_set_to_islands(disjoint_set, subdiv_ccg.positions.size());
5969}
5970
5972{
5973 const SculptSession &ss = *object.sculpt;
5974 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
5976 BMesh &bm = *ss.bm;
5978
5979 IndexMaskMemory memory;
5980 const IndexMask node_mask = bke::pbvh::all_leaf_nodes(pbvh, memory);
5981 AtomicDisjointSet disjoint_set(bm.totvert);
5982 node_mask.foreach_index(GrainSize(1), [&](const int i) {
5983 for (const BMFace *face :
5984 BKE_pbvh_bmesh_node_faces(&const_cast<bke::pbvh::BMeshNode &>(nodes[i])))
5985 {
5986 if (BM_elem_flag_test(face, BM_ELEM_HIDDEN)) {
5987 continue;
5988 }
5989 disjoint_set.join(BM_elem_index_get(face->l_first->v),
5990 BM_elem_index_get(face->l_first->next->v));
5991 disjoint_set.join(BM_elem_index_get(face->l_first->v),
5992 BM_elem_index_get(face->l_first->next->next->v));
5993 }
5994 });
5995
5996 return vert_disjoint_set_to_islands(disjoint_set, bm.totvert);
5997}
5998
6000{
6001 switch (bke::object::pbvh_get(object)->type()) {
6003 return calc_topology_islands_mesh(*static_cast<const Mesh *>(object.data));
6005 return calc_topology_islands_grids(object);
6007 return calc_topology_islands_bmesh(object);
6008 }
6010 return {};
6011}
6012
6014{
6015 SculptSession &ss = *object.sculpt;
6016 if (ss.topology_island_cache) {
6017 return;
6018 }
6019 ss.topology_island_cache = std::make_unique<SculptTopologyIslandCache>(calculate_cache(object));
6020}
6021
6022} // namespace blender::ed::sculpt_paint::islands
6023
6024void SCULPT_cube_tip_init(const Sculpt & /*sd*/,
6025 const Object &ob,
6026 const Brush &brush,
6027 float mat[4][4])
6028{
6029 using namespace blender::ed::sculpt_paint;
6030 SculptSession &ss = *ob.sculpt;
6031 float scale[4][4];
6032 float tmat[4][4];
6033 float unused[4][4];
6034
6035 zero_m4(mat);
6036 calc_brush_local_mat(0.0, ob, unused, mat);
6037
6038 /* NOTE: we ignore the radius scaling done inside of calc_brush_local_mat to
6039 * duplicate prior behavior.
6040 *
6041 * TODO: try disabling this and check that all edge cases work properly.
6042 */
6043 normalize_m4(mat);
6044
6045 scale_m4_fl(scale, ss.cache->radius);
6046 mul_m4_m4m4(tmat, mat, scale);
6047 mul_v3_fl(tmat[1], brush.tip_scale_x);
6048 invert_m4_m4(mat, tmat);
6049}
6052namespace blender::ed::sculpt_paint {
6053
6055{
6056 BLI_assert(verts.size() == positions.size());
6057
6058 int i = 0;
6059 for (const BMVert *vert : verts) {
6060 positions[i] = vert->co;
6061 i++;
6062 }
6063}
6064
6065void gather_grids_normals(const SubdivCCG &subdiv_ccg,
6066 const Span<int> grids,
6067 const MutableSpan<float3> normals)
6068{
6069 gather_data_grids(subdiv_ccg, subdiv_ccg.normals.as_span(), grids, normals);
6070}
6071
6073{
6074 int i = 0;
6075 for (const BMVert *vert : verts) {
6076 normals[i] = vert->no;
6077 i++;
6078 }
6079}
6080
6081template<typename T>
6082void gather_data_mesh(const Span<T> src, const Span<int> indices, const MutableSpan<T> dst)
6083{
6084 BLI_assert(indices.size() == dst.size());
6085
6086 for (const int i : indices.index_range()) {
6087 dst[i] = src[indices[i]];
6088 }
6089}
6090
6091template<typename T>
6092void gather_data_grids(const SubdivCCG &subdiv_ccg,
6093 const Span<T> src,
6094 const Span<int> grids,
6095 const MutableSpan<T> node_data)
6096{
6097 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
6098 BLI_assert(grids.size() * key.grid_area == node_data.size());
6099
6100 for (const int i : grids.index_range()) {
6101 const IndexRange grids_range = bke::ccg::grid_range(key, grids[i]);
6102 const IndexRange node_range = bke::ccg::grid_range(key, i);
6103 node_data.slice(node_range).copy_from(src.slice(grids_range));
6104 }
6105}
6106
6107template<typename T>
6109 const Set<BMVert *, 0> &verts,
6110 const MutableSpan<T> node_data)
6111{
6112 BLI_assert(verts.size() == node_data.size());
6113
6114 int i = 0;
6115 for (const BMVert *vert : verts) {
6116 node_data[i] = src[BM_elem_index_get(vert)];
6117 i++;
6118 }
6119}
6120
6121template<typename T>
6122void scatter_data_mesh(const Span<T> src, const Span<int> indices, const MutableSpan<T> dst)
6123{
6124 BLI_assert(indices.size() == src.size());
6125
6126 for (const int i : indices.index_range()) {
6127 dst[indices[i]] = src[i];
6128 }
6129}
6130
6131template<typename T>
6132void scatter_data_grids(const SubdivCCG &subdiv_ccg,
6133 const Span<T> node_data,
6134 const Span<int> grids,
6135 const MutableSpan<T> dst)
6136{
6137 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
6138 BLI_assert(grids.size() * key.grid_area == node_data.size());
6139
6140 for (const int i : grids.index_range()) {
6141 const IndexRange grids_range = bke::ccg::grid_range(key, grids[i]);
6142 const IndexRange node_range = bke::ccg::grid_range(key, i);
6143 dst.slice(grids_range).copy_from(node_data.slice(node_range));
6144 }
6145}
6146
6147template<typename T>
6148void scatter_data_bmesh(const Span<T> node_data,
6149 const Set<BMVert *, 0> &verts,
6150 const MutableSpan<T> dst)
6151{
6152 BLI_assert(verts.size() == node_data.size());
6153
6154 int i = 0;
6155 for (const BMVert *vert : verts) {
6156 dst[BM_elem_index_get(vert)] = node_data[i];
6157 i++;
6158 }
6159}
6160
6161template void gather_data_mesh<bool>(Span<bool>, Span<int>, MutableSpan<bool>);
6162template void gather_data_mesh<int>(Span<int>, Span<int>, MutableSpan<int>);
6163template void gather_data_mesh<float>(Span<float>, Span<int>, MutableSpan<float>);
6164template void gather_data_mesh<float3>(Span<float3>, Span<int>, MutableSpan<float3>);
6165template void gather_data_mesh<float4>(Span<float4>, Span<int>, MutableSpan<float4>);
6166template void gather_data_grids<int>(const SubdivCCG &, Span<int>, Span<int>, MutableSpan<int>);
6167template void gather_data_grids<float>(const SubdivCCG &,
6169 Span<int>,
6171template void gather_data_grids<float3>(const SubdivCCG &,
6173 Span<int>,
6175template void gather_data_bmesh<int>(Span<int>, const Set<BMVert *, 0> &, MutableSpan<int>);
6176template void gather_data_bmesh<float>(Span<float>, const Set<BMVert *, 0> &, MutableSpan<float>);
6177template void gather_data_bmesh<float3>(Span<float3>,
6178 const Set<BMVert *, 0> &,
6180
6181template void scatter_data_mesh<bool>(Span<bool>, Span<int>, MutableSpan<bool>);
6182template void scatter_data_mesh<int>(Span<int>, Span<int>, MutableSpan<int>);
6183template void scatter_data_mesh<float>(Span<float>, Span<int>, MutableSpan<float>);
6184template void scatter_data_mesh<float3>(Span<float3>, Span<int>, MutableSpan<float3>);
6185template void scatter_data_mesh<float4>(Span<float4>, Span<int>, MutableSpan<float4>);
6186template void scatter_data_grids<float>(const SubdivCCG &,
6188 Span<int>,
6190template void scatter_data_grids<float3>(const SubdivCCG &,
6192 Span<int>,
6194template void scatter_data_bmesh<float>(Span<float>, const Set<BMVert *, 0> &, MutableSpan<float>);
6195template void scatter_data_bmesh<float3>(Span<float3>,
6196 const Set<BMVert *, 0> &,
6198
6200 const Brush &brush,
6201 const Object &object,
6202 const MeshAttributeData &attribute_data,
6203 const Span<float3> vert_positions,
6204 const Span<float3> vert_normals,
6205 const bke::pbvh::MeshNode &node,
6206 Vector<float> &r_factors,
6207 Vector<float> &r_distances)
6208{
6209 const SculptSession &ss = *object.sculpt;
6210 const StrokeCache &cache = *ss.cache;
6211
6212 const Span<int> verts = node.verts();
6213
6214 r_factors.resize(verts.size());
6215 const MutableSpan<float> factors = r_factors;
6216 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
6217 filter_region_clip_factors(ss, vert_positions, verts, factors);
6218 if (brush.flag & BRUSH_FRONTFACE) {
6219 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
6220 }
6221
6222 r_distances.resize(verts.size());
6223 const MutableSpan<float> distances = r_distances;
6225 ss, vert_positions, verts, eBrushFalloffShape(brush.falloff_shape), distances);
6226 filter_distances_with_radius(cache.radius, distances, factors);
6227 apply_hardness_to_distances(cache, distances);
6228 calc_brush_strength_factors(cache, brush, distances, factors);
6229
6230 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
6231
6232 calc_brush_texture_factors(ss, brush, vert_positions, verts, factors);
6233}
6234
6236 const Brush &brush,
6237 const Object &object,
6238 const MeshAttributeData &attribute_data,
6239 const Span<float3> positions,
6240 const Span<float3> vert_normals,
6241 const bke::pbvh::MeshNode &node,
6242 Vector<float> &r_factors,
6243 Vector<float> &r_distances)
6244{
6245 const SculptSession &ss = *object.sculpt;
6246 const StrokeCache &cache = *ss.cache;
6247
6248 const Span<int> verts = node.verts();
6249
6250 r_factors.resize(verts.size());
6251 const MutableSpan<float> factors = r_factors;
6252 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
6253 filter_region_clip_factors(ss, positions, factors);
6254 if (brush.flag & BRUSH_FRONTFACE) {
6255 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
6256 }
6257
6258 r_distances.resize(verts.size());
6259 const MutableSpan<float> distances = r_distances;
6260 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
6261 filter_distances_with_radius(cache.radius, distances, factors);
6262 apply_hardness_to_distances(cache, distances);
6263 calc_brush_strength_factors(cache, brush, distances, factors);
6264
6265 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
6266
6267 calc_brush_texture_factors(ss, brush, positions, factors);
6268}
6269
6271 const Brush &brush,
6272 const Object &object,
6273 const Span<float3> positions,
6274 const bke::pbvh::GridsNode &node,
6275 Vector<float> &r_factors,
6276 Vector<float> &r_distances)
6277{
6278 const SculptSession &ss = *object.sculpt;
6279 const StrokeCache &cache = *ss.cache;
6280 const SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
6281
6282 const Span<int> grids = node.grids();
6283
6284 r_factors.resize(positions.size());
6285 const MutableSpan<float> factors = r_factors;
6286 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
6287 filter_region_clip_factors(ss, positions, factors);
6288 if (brush.flag & BRUSH_FRONTFACE) {
6289 calc_front_face(cache.view_normal_symm, subdiv_ccg, grids, factors);
6290 }
6291
6292 r_distances.resize(positions.size());
6293 const MutableSpan<float> distances = r_distances;
6294 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
6295 filter_distances_with_radius(cache.radius, distances, factors);
6296 apply_hardness_to_distances(cache, distances);
6297 calc_brush_strength_factors(cache, brush, distances, factors);
6298
6299 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
6300
6301 calc_brush_texture_factors(ss, brush, positions, factors);
6302}
6303
6305 const Brush &brush,
6306 const Object &object,
6307 const Span<float3> positions,
6309 Vector<float> &r_factors,
6310 Vector<float> &r_distances)
6311{
6312 const SculptSession &ss = *object.sculpt;
6313 const StrokeCache &cache = *ss.cache;
6314
6316
6317 r_factors.resize(verts.size());
6318 const MutableSpan<float> factors = r_factors;
6320 filter_region_clip_factors(ss, positions, factors);
6321 if (brush.flag & BRUSH_FRONTFACE) {
6322 calc_front_face(cache.view_normal_symm, verts, factors);
6323 }
6324
6325 r_distances.resize(verts.size());
6326 const MutableSpan<float> distances = r_distances;
6327 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
6328 filter_distances_with_radius(cache.radius, distances, factors);
6329 apply_hardness_to_distances(cache, distances);
6330 calc_brush_strength_factors(cache, brush, distances, factors);
6331
6332 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
6333
6334 calc_brush_texture_factors(ss, brush, positions, factors);
6335}
6336
6338 const Brush &brush,
6339 const Object &object,
6340 const MeshAttributeData &attribute_data,
6341 const Span<float3> positions,
6342 const Span<float3> normals,
6343 const bke::pbvh::MeshNode &node,
6344 Vector<float> &r_factors,
6345 Vector<float> &r_distances)
6346{
6347 const SculptSession &ss = *object.sculpt;
6348 const StrokeCache &cache = *ss.cache;
6349
6350 const Span<int> verts = node.verts();
6351
6352 r_factors.resize(verts.size());
6353 const MutableSpan<float> factors = r_factors;
6354 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
6355 filter_region_clip_factors(ss, positions, factors);
6356
6357 if (brush.flag & BRUSH_FRONTFACE) {
6358 calc_front_face(cache.view_normal_symm, normals, factors);
6359 }
6360
6361 r_distances.resize(verts.size());
6362 const MutableSpan<float> distances = r_distances;
6363 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
6364 filter_distances_with_radius(cache.radius, distances, factors);
6365 apply_hardness_to_distances(cache, distances);
6366 calc_brush_strength_factors(cache, brush, distances, factors);
6367
6368 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
6369
6370 calc_brush_texture_factors(ss, brush, positions, factors);
6371}
6372
6374 const Brush &brush,
6375 const Object &object,
6376 const Span<float3> positions,
6377 const Span<float3> normals,
6378 const bke::pbvh::GridsNode &node,
6379 Vector<float> &r_factors,
6380 Vector<float> &r_distances)
6381{
6382 SculptSession &ss = *object.sculpt;
6383 const StrokeCache &cache = *ss.cache;
6384 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
6385
6386 const Span<int> grids = node.grids();
6387
6388 r_factors.resize(positions.size());
6389 const MutableSpan<float> factors = r_factors;
6390 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
6391 filter_region_clip_factors(ss, positions, factors);
6392 if (brush.flag & BRUSH_FRONTFACE) {
6393 calc_front_face(cache.view_normal_symm, normals, grids, factors);
6394 }
6395
6396 r_distances.resize(positions.size());
6397 const MutableSpan<float> distances = r_distances;
6398 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
6399 filter_distances_with_radius(cache.radius, distances, factors);
6400 apply_hardness_to_distances(cache, distances);
6401 calc_brush_strength_factors(cache, brush, distances, factors);
6402
6403 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
6404
6405 calc_brush_texture_factors(ss, brush, positions, factors);
6406}
6407
6409 const Brush &brush,
6410 const Object &object,
6411 const Span<float3> positions,
6412 const Span<float3> normals,
6414 Vector<float> &r_factors,
6415 Vector<float> &r_distances)
6416{
6417 SculptSession &ss = *object.sculpt;
6418 const StrokeCache &cache = *ss.cache;
6419
6421
6422 r_factors.resize(verts.size());
6423 const MutableSpan<float> factors = r_factors;
6425 filter_region_clip_factors(ss, positions, factors);
6426 if (brush.flag & BRUSH_FRONTFACE) {
6427 calc_front_face(cache.view_normal_symm, normals, factors);
6428 }
6429
6430 r_distances.resize(verts.size());
6431 const MutableSpan<float> distances = r_distances;
6432 calc_brush_distances(ss, positions, eBrushFalloffShape(brush.falloff_shape), distances);
6433 filter_distances_with_radius(cache.radius, distances, factors);
6434 apply_hardness_to_distances(cache, distances);
6435 calc_brush_strength_factors(cache, brush, distances, factors);
6436
6437 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
6438
6439 calc_brush_texture_factors(ss, brush, positions, factors);
6440}
6441
6443 const Span<int> verts,
6444 const MutableSpan<float> r_factors)
6445{
6446 BLI_assert(verts.size() == r_factors.size());
6447
6448 if (!hide_vert.is_empty()) {
6449 for (const int i : verts.index_range()) {
6450 r_factors[i] = hide_vert[verts[i]] ? 0.0f : 1.0f;
6451 }
6452 }
6453 else {
6454 r_factors.fill(1.0f);
6455 }
6456}
6457
6458void fill_factor_from_hide(const SubdivCCG &subdiv_ccg,
6459 const Span<int> grids,
6460 const MutableSpan<float> r_factors)
6461{
6462 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
6463 BLI_assert(grids.size() * key.grid_area == r_factors.size());
6464
6465 const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
6466 if (grid_hidden.is_empty()) {
6467 r_factors.fill(1.0f);
6468 return;
6469 }
6470 for (const int i : grids.index_range()) {
6471 const BitSpan hidden = grid_hidden[grids[i]];
6472 const int start = i * key.grid_area;
6473 for (const int offset : IndexRange(key.grid_area)) {
6474 r_factors[start + offset] = hidden[offset] ? 0.0f : 1.0f;
6475 }
6476 }
6477}
6478
6480{
6481 BLI_assert(verts.size() == r_factors.size());
6482
6483 int i = 0;
6484 for (const BMVert *vert : verts) {
6485 r_factors[i] = BM_elem_flag_test_bool(vert, BM_ELEM_HIDDEN) ? 0.0f : 1.0f;
6486 i++;
6487 }
6488}
6489
6491 const Span<float> mask,
6492 const Span<int> verts,
6493 const MutableSpan<float> r_factors)
6494{
6495 BLI_assert(verts.size() == r_factors.size());
6496
6497 if (!mask.is_empty()) {
6498 for (const int i : verts.index_range()) {
6499 r_factors[i] = 1.0f - mask[verts[i]];
6500 }
6501 }
6502 else {
6503 r_factors.fill(1.0f);
6504 }
6505
6506 if (!hide_vert.is_empty()) {
6507 for (const int i : verts.index_range()) {
6508 if (hide_vert[verts[i]]) {
6509 r_factors[i] = 0.0f;
6510 }
6511 }
6512 }
6513}
6514
6516 const Set<BMVert *, 0> &verts,
6517 const MutableSpan<float> r_factors)
6518{
6519 BLI_assert(verts.size() == r_factors.size());
6520
6521 /* TODO: Avoid overhead of accessing attributes for every bke::pbvh::Tree node. */
6522 const int mask_offset = CustomData_get_offset_named(&bm.vdata, CD_PROP_FLOAT, ".sculpt_mask");
6523 int i = 0;
6524 for (const BMVert *vert : verts) {
6525 r_factors[i] = (mask_offset == -1) ? 1.0f : 1.0f - BM_ELEM_CD_GET_FLOAT(vert, mask_offset);
6526 if (BM_elem_flag_test(vert, BM_ELEM_HIDDEN)) {
6527 r_factors[i] = 0.0f;
6528 }
6529 i++;
6530 }
6531}
6532
6534 const Span<int> grids,
6535 const MutableSpan<float> r_factors)
6536{
6537 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
6538 BLI_assert(grids.size() * key.grid_area == r_factors.size());
6539
6540 if (!subdiv_ccg.masks.is_empty()) {
6541 const Span<float> masks = subdiv_ccg.masks;
6542 for (const int i : grids.index_range()) {
6543 const Span src = masks.slice(bke::ccg::grid_range(key, grids[i]));
6544 MutableSpan dst = r_factors.slice(bke::ccg::grid_range(key, i));
6545 for (const int offset : dst.index_range()) {
6546 dst[offset] = 1.0f - src[offset];
6547 }
6548 }
6549 }
6550 else {
6551 r_factors.fill(1.0f);
6552 }
6553
6554 const BitGroupVector<> &grid_hidden = subdiv_ccg.grid_hidden;
6555 if (!grid_hidden.is_empty()) {
6556 for (const int i : grids.index_range()) {
6557 const BitSpan hidden = grid_hidden[grids[i]];
6558 const int start = i * key.grid_area;
6559 for (const int offset : IndexRange(key.grid_area)) {
6560 if (hidden[offset]) {
6561 r_factors[start + offset] = 0.0f;
6562 }
6563 }
6564 }
6565 }
6566}
6567
6568void calc_front_face(const float3 &view_normal,
6569 const Span<float3> vert_normals,
6570 const Span<int> verts,
6571 const MutableSpan<float> factors)
6572{
6573 BLI_assert(verts.size() == factors.size());
6574
6575 for (const int i : verts.index_range()) {
6576 const float dot = math::dot(view_normal, vert_normals[verts[i]]);
6577 factors[i] *= std::max(dot, 0.0f);
6578 }
6579}
6580
6581void calc_front_face(const float3 &view_normal,
6582 const Span<float3> normals,
6583 const MutableSpan<float> factors)
6584{
6585 BLI_assert(normals.size() == factors.size());
6586
6587 for (const int i : normals.index_range()) {
6588 const float dot = math::dot(view_normal, normals[i]);
6589 factors[i] *= std::max(dot, 0.0f);
6590 }
6591}
6592void calc_front_face(const float3 &view_normal,
6593 const SubdivCCG &subdiv_ccg,
6594 const Span<int> grids,
6595 const MutableSpan<float> factors)
6596{
6597 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
6598 const Span<float3> normals = subdiv_ccg.normals;
6599 BLI_assert(grids.size() * key.grid_area == factors.size());
6600
6601 for (const int i : grids.index_range()) {
6602 const Span<float3> grid_normals = normals.slice(bke::ccg::grid_range(key, grids[i]));
6603 MutableSpan<float> grid_factors = factors.slice(bke::ccg::grid_range(key, i));
6604 for (const int offset : grid_factors.index_range()) {
6605 const float dot = math::dot(view_normal, grid_normals[offset]);
6606 grid_factors[offset] *= std::max(dot, 0.0f);
6607 }
6608 }
6609}
6610
6611void calc_front_face(const float3 &view_normal,
6612 const Set<BMVert *, 0> &verts,
6613 const MutableSpan<float> factors)
6614{
6615 BLI_assert(verts.size() == factors.size());
6616
6617 int i = 0;
6618 for (const BMVert *vert : verts) {
6619 const float dot = math::dot(view_normal, float3(vert->no));
6620 factors[i] *= std::max(dot, 0.0f);
6621 i++;
6622 }
6623}
6624
6625void calc_front_face(const float3 &view_normal,
6626 const Set<BMFace *, 0> &faces,
6627 const MutableSpan<float> factors)
6628{
6629 BLI_assert(faces.size() == factors.size());
6630
6631 int i = 0;
6632 for (const BMFace *face : faces) {
6633 const float dot = math::dot(view_normal, float3(face->no));
6634 factors[i] *= std::max(dot, 0.0f);
6635 i++;
6636 }
6637}
6638
6640 const Span<float3> positions,
6641 const Span<int> verts,
6642 const MutableSpan<float> factors)
6643{
6644 BLI_assert(verts.size() == factors.size());
6645
6646 const RegionView3D *rv3d = ss.cache ? ss.cache->vc->rv3d : ss.rv3d;
6647 const View3D *v3d = ss.cache ? ss.cache->vc->v3d : ss.v3d;
6648 if (!RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
6649 return;
6650 }
6651
6652 const ePaintSymmetryFlags mirror_symmetry_pass = ss.cache ? ss.cache->mirror_symmetry_pass :
6654 const int radial_symmetry_pass = ss.cache ? ss.cache->radial_symmetry_pass : 0;
6655 const float4x4 symm_rot_mat_inv = ss.cache ? ss.cache->symm_rot_mat_inv : float4x4::identity();
6656 for (const int i : verts.index_range()) {
6657 float3 symm_co = symmetry_flip(positions[verts[i]], mirror_symmetry_pass);
6658 if (radial_symmetry_pass) {
6659 symm_co = math::transform_point(symm_rot_mat_inv, symm_co);
6660 }
6661 if (ED_view3d_clipping_test(rv3d, symm_co, true)) {
6662 factors[i] = 0.0f;
6663 }
6664 }
6665}
6666
6668 const Span<float3> positions,
6669 const MutableSpan<float> factors)
6670{
6671 BLI_assert(positions.size() == factors.size());
6672
6673 const RegionView3D *rv3d = ss.cache ? ss.cache->vc->rv3d : ss.rv3d;
6674 const View3D *v3d = ss.cache ? ss.cache->vc->v3d : ss.v3d;
6675 if (!RV3D_CLIPPING_ENABLED(v3d, rv3d)) {
6676 return;
6677 }
6678
6679 const ePaintSymmetryFlags mirror_symmetry_pass = ss.cache ? ss.cache->mirror_symmetry_pass :
6681 const int radial_symmetry_pass = ss.cache ? ss.cache->radial_symmetry_pass : 0;
6682 const float4x4 symm_rot_mat_inv = ss.cache ? ss.cache->symm_rot_mat_inv : float4x4::identity();
6683 for (const int i : positions.index_range()) {
6684 float3 symm_co = symmetry_flip(positions[i], mirror_symmetry_pass);
6685 if (radial_symmetry_pass) {
6686 symm_co = math::transform_point(symm_rot_mat_inv, symm_co);
6687 }
6688 if (ED_view3d_clipping_test(rv3d, symm_co, true)) {
6689 factors[i] = 0.0f;
6690 }
6691 }
6692}
6693
6695 const Span<float3> positions,
6696 const Span<int> verts,
6697 const eBrushFalloffShape falloff_shape,
6698 const MutableSpan<float> r_distances)
6699{
6700 BLI_assert(verts.size() == r_distances.size());
6701
6702 const float3 &test_location = ss.cache ? ss.cache->location_symm : ss.cursor_location;
6703 if (falloff_shape == PAINT_FALLOFF_SHAPE_TUBE && (ss.cache || ss.filter_cache)) {
6704 /* The tube falloff shape requires the cached view normal. */
6705 const float3 &view_normal = ss.cache ? ss.cache->view_normal_symm :
6707 float4 test_plane;
6708 plane_from_point_normal_v3(test_plane, test_location, view_normal);
6709 for (const int i : verts.index_range()) {
6710 float3 projected;
6711 closest_to_plane_normalized_v3(projected, test_plane, positions[verts[i]]);
6712 r_distances[i] = math::distance_squared(projected, test_location);
6713 }
6714 }
6715 else {
6716 for (const int i : verts.index_range()) {
6717 r_distances[i] = math::distance_squared(test_location, positions[verts[i]]);
6718 }
6719 }
6720}
6721
6723 const Span<float3> positions,
6724 const Span<int> verts,
6725 const eBrushFalloffShape falloff_shape,
6726 const MutableSpan<float> r_distances)
6727{
6728 calc_brush_distances_squared(ss, positions, verts, falloff_shape, r_distances);
6729 for (float &value : r_distances) {
6730 value = std::sqrt(value);
6731 }
6732}
6733
6735 const Span<float3> positions,
6736 const eBrushFalloffShape falloff_shape,
6737 const MutableSpan<float> r_distances)
6738{
6739 BLI_assert(positions.size() == r_distances.size());
6740
6741 const float3 &test_location = ss.cache ? ss.cache->location_symm : ss.cursor_location;
6742 if (falloff_shape == PAINT_FALLOFF_SHAPE_TUBE && (ss.cache || ss.filter_cache)) {
6743 /* The tube falloff shape requires the cached view normal. */
6744 const float3 &view_normal = ss.cache ? ss.cache->view_normal_symm :
6746 float4 test_plane;
6747 plane_from_point_normal_v3(test_plane, test_location, view_normal);
6748 for (const int i : positions.index_range()) {
6749 float3 projected;
6750 closest_to_plane_normalized_v3(projected, test_plane, positions[i]);
6751 r_distances[i] = math::distance_squared(projected, test_location);
6752 }
6753 }
6754 else {
6755 for (const int i : positions.index_range()) {
6756 r_distances[i] = math::distance_squared(test_location, positions[i]);
6757 }
6758 }
6759}
6760
6762 const Span<float3> positions,
6763 const eBrushFalloffShape falloff_shape,
6764 const MutableSpan<float> r_distances)
6765{
6766 calc_brush_distances_squared(ss, positions, falloff_shape, r_distances);
6767 for (float &value : r_distances) {
6768 value = std::sqrt(value);
6769 }
6770}
6771
6772void filter_distances_with_radius(const float radius,
6773 const Span<float> distances,
6774 const MutableSpan<float> factors)
6775{
6776 for (const int i : distances.index_range()) {
6777 if (distances[i] >= radius) {
6778 factors[i] = 0.0f;
6779 }
6780 }
6781}
6782
6784 const float4x4 &mat,
6785 const Span<float3> positions,
6786 const Span<int> verts,
6787 const MutableSpan<float> r_distances,
6788 const MutableSpan<float> factors)
6789{
6790 BLI_assert(verts.size() == factors.size());
6791 BLI_assert(verts.size() == r_distances.size());
6792
6793 const float roundness = brush.tip_roundness;
6794 const float hardness = 1.0f - roundness;
6795 for (const int i : verts.index_range()) {
6796 if (factors[i] == 0.0f) {
6797 r_distances[i] = std::numeric_limits<float>::max();
6798 continue;
6799 }
6800 const float3 local = math::abs(math::transform_point(mat, positions[verts[i]]));
6801
6802 if (!(local.x <= 1.0f && local.y <= 1.0f && local.z <= 1.0f)) {
6803 factors[i] = 0.0f;
6804 r_distances[i] = std::numeric_limits<float>::max();
6805 continue;
6806 }
6807 if (std::min(local.x, local.y) > hardness) {
6808 /* Corner, distance to the center of the corner circle. */
6809 r_distances[i] = math::distance(float2(hardness), float2(local)) / roundness;
6810 continue;
6811 }
6812 if (std::max(local.x, local.y) > hardness) {
6813 /* Side, distance to the square XY axis. */
6814 r_distances[i] = (std::max(local.x, local.y) - hardness) / roundness;
6815 continue;
6816 }
6817
6818 /* Inside the square, constant distance. */
6819 r_distances[i] = 0.0f;
6820 }
6821}
6822
6824 const float4x4 &mat,
6825 const Span<float3> positions,
6826 const MutableSpan<float> r_distances,
6827 const MutableSpan<float> factors)
6828{
6829 BLI_assert(positions.size() == factors.size());
6830 BLI_assert(positions.size() == r_distances.size());
6831
6832 const float roundness = brush.tip_roundness;
6833 const float hardness = 1.0f - roundness;
6834 for (const int i : positions.index_range()) {
6835 if (factors[i] == 0.0f) {
6836 r_distances[i] = std::numeric_limits<float>::max();
6837 continue;
6838 }
6839 const float3 local = math::abs(math::transform_point(mat, positions[i]));
6840
6841 if (!(local.x <= 1.0f && local.y <= 1.0f && local.z <= 1.0f)) {
6842 factors[i] = 0.0f;
6843 r_distances[i] = std::numeric_limits<float>::max();
6844 continue;
6845 }
6846 if (std::min(local.x, local.y) > hardness) {
6847 /* Corner, distance to the center of the corner circle. */
6848 r_distances[i] = math::distance(float2(hardness), float2(local)) / roundness;
6849 continue;
6850 }
6851 if (std::max(local.x, local.y) > hardness) {
6852 /* Side, distance to the square XY axis. */
6853 r_distances[i] = (std::max(local.x, local.y) - hardness) / roundness;
6854 continue;
6855 }
6856
6857 /* Inside the square, constant distance. */
6858 r_distances[i] = 0.0f;
6859 }
6860}
6861
6862void apply_hardness_to_distances(const float radius,
6863 const float hardness,
6864 const MutableSpan<float> distances)
6865{
6866 if (hardness == 0.0f) {
6867 return;
6868 }
6869 const float threshold = hardness * radius;
6870 if (hardness == 1.0f) {
6871 for (const int i : distances.index_range()) {
6872 distances[i] = distances[i] < threshold ? 0.0f : radius;
6873 }
6874 return;
6875 }
6876 const float radius_inv = math::rcp(radius);
6877 const float hardness_inv_rcp = math::rcp(1.0f - hardness);
6878 for (const int i : distances.index_range()) {
6879 if (distances[i] < threshold) {
6880 distances[i] = 0.0f;
6881 }
6882 else {
6883 const float radius_factor = (distances[i] * radius_inv - hardness) * hardness_inv_rcp;
6884 distances[i] = radius_factor * radius;
6885 }
6886 }
6887}
6888
6890 const Brush &brush,
6891 const Span<float> distances,
6892 const MutableSpan<float> factors)
6893{
6895 eBrushCurvePreset(brush.curve_preset), brush.curve, distances, cache.radius, factors);
6896}
6897
6899 const Brush &brush,
6900 const Span<float3> vert_positions,
6901 const Span<int> verts,
6902 const MutableSpan<float> factors)
6903{
6904 BLI_assert(verts.size() == factors.size());
6905
6906 const int thread_id = BLI_task_parallel_thread_id(nullptr);
6907 const MTex *mtex = BKE_brush_mask_texture_get(&brush, OB_MODE_SCULPT);
6908 if (!mtex->tex) {
6909 return;
6910 }
6911
6912 for (const int i : verts.index_range()) {
6913 float texture_value;
6914 float4 texture_rgba;
6915 /* NOTE: This is not a thread-safe call. */
6917 ss, brush, vert_positions[verts[i]], thread_id, &texture_value, texture_rgba);
6918
6919 factors[i] *= texture_value;
6920 }
6921}
6922
6924 const Brush &brush,
6925 const Span<float3> positions,
6926 const MutableSpan<float> factors)
6927{
6928 BLI_assert(positions.size() == factors.size());
6929
6930 const int thread_id = BLI_task_parallel_thread_id(nullptr);
6931 const MTex *mtex = BKE_brush_mask_texture_get(&brush, OB_MODE_SCULPT);
6932 if (!mtex->tex) {
6933 return;
6934 }
6935
6936 for (const int i : positions.index_range()) {
6937 float texture_value;
6938 float4 texture_rgba;
6939 /* NOTE: This is not a thread-safe call. */
6940 sculpt_apply_texture(ss, brush, positions[i], thread_id, &texture_value, texture_rgba);
6941
6942 factors[i] *= texture_value;
6943 }
6944}
6945
6947 const Span<float3> positions,
6948 const Span<float3> orig_positions)
6949{
6950 BLI_assert(translations.size() == orig_positions.size());
6951 BLI_assert(translations.size() == positions.size());
6952 for (const int i : translations.index_range()) {
6953 const float3 prev_translation = positions[i] - orig_positions[i];
6954 translations[i] -= prev_translation;
6955 }
6956}
6957
6958void apply_translations(const Span<float3> translations,
6959 const Span<int> verts,
6960 const MutableSpan<float3> positions)
6961{
6962 BLI_assert(verts.size() == translations.size());
6963
6964 for (const int i : verts.index_range()) {
6965 const int vert = verts[i];
6966 positions[vert] += translations[i];
6967 }
6968}
6969
6970void apply_translations(const Span<float3> translations,
6971 const Span<int> grids,
6972 SubdivCCG &subdiv_ccg)
6973{
6974 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
6975 MutableSpan<float3> positions = subdiv_ccg.positions;
6976 BLI_assert(grids.size() * key.grid_area == translations.size());
6977
6978 for (const int i : grids.index_range()) {
6979 const Span<float3> grid_translations = translations.slice(bke::ccg::grid_range(key, i));
6980 MutableSpan<float3> grid_positions = positions.slice(bke::ccg::grid_range(key, grids[i]));
6981 for (const int offset : grid_positions.index_range()) {
6982 grid_positions[offset] += grid_translations[offset];
6983 }
6984 }
6985}
6986
6988{
6989 BLI_assert(verts.size() == translations.size());
6990
6991 int i = 0;
6992 for (BMVert *vert : verts) {
6993 add_v3_v3(vert->co, translations[i]);
6994 i++;
6995 }
6996}
6997
6998void project_translations(const MutableSpan<float3> translations, const float3 &plane)
6999{
7000 /* Equivalent to #project_plane_v3_v3v3. */
7001 const float len_sq = math::length_squared(plane);
7002 if (len_sq < std::numeric_limits<float>::epsilon()) {
7003 return;
7004 }
7005 const float dot_factor = -math::rcp(len_sq);
7006 for (const int i : translations.index_range()) {
7007 translations[i] += plane * math::dot(translations[i], plane) * dot_factor;
7008 }
7009}
7010
7012 const Span<int> verts,
7013 const MutableSpan<float3> translations)
7014{
7015 BLI_assert(verts.size() == translations.size());
7016
7017 for (const int i : verts.index_range()) {
7018 translations[i] = math::transform_point(deform_imats[verts[i]], translations[i]);
7019 }
7020}
7021
7023 const SculptSession &ss,
7024 const Span<float3> positions,
7025 const Span<int> verts,
7026 const MutableSpan<float3> translations)
7027{
7028 BLI_assert(verts.size() == translations.size());
7029
7030 const StrokeCache *cache = ss.cache;
7031 if (!cache) {
7032 return;
7033 }
7034 for (const int axis : IndexRange(3)) {
7035 if (sd.flags & (SCULPT_LOCK_X << axis)) {
7036 for (float3 &translation : translations) {
7037 translation[axis] = 0.0f;
7038 }
7039 continue;
7040 }
7041
7042 if (!(cache->mirror_modifier_clip.flag & (uint8_t(StrokeFlags::ClipX) << axis))) {
7043 continue;
7044 }
7045
7046 const float4x4 mirror(cache->mirror_modifier_clip.mat);
7047 const float4x4 mirror_inverse(cache->mirror_modifier_clip.mat_inv);
7048 for (const int i : verts.index_range()) {
7049 const int vert = verts[i];
7050
7051 /* Transform into the space of the mirror plane, check translations, then transform back. */
7052 float3 co_mirror = math::transform_point(mirror, positions[vert]);
7053 if (math::abs(co_mirror[axis]) > cache->mirror_modifier_clip.tolerance[axis]) {
7054 continue;
7055 }
7056 /* Clear the translation in the local space of the mirror object. */
7057 co_mirror[axis] = 0.0f;
7058 const float3 co_local = math::transform_point(mirror_inverse, co_mirror);
7059 translations[i][axis] = co_local[axis] - positions[vert][axis];
7060 }
7061 }
7062}
7063
7065 const SculptSession &ss,
7066 const Span<float3> positions,
7067 const MutableSpan<float3> translations)
7068{
7069 BLI_assert(positions.size() == translations.size());
7070
7071 const StrokeCache *cache = ss.cache;
7072 if (!cache) {
7073 return;
7074 }
7075 for (const int axis : IndexRange(3)) {
7076 if (sd.flags & (SCULPT_LOCK_X << axis)) {
7077 for (float3 &translation : translations) {
7078 translation[axis] = 0.0f;
7079 }
7080 continue;
7081 }
7082
7083 if (!(cache->mirror_modifier_clip.flag & (uint8_t(StrokeFlags::ClipX) << axis))) {
7084 continue;
7085 }
7086
7087 const float4x4 mirror(cache->mirror_modifier_clip.mat);
7088 const float4x4 mirror_inverse(cache->mirror_modifier_clip.mat_inv);
7089 for (const int i : positions.index_range()) {
7090 /* Transform into the space of the mirror plane, check translations, then transform back. */
7091 float3 co_mirror = math::transform_point(mirror, positions[i]);
7092 if (math::abs(co_mirror[axis]) > cache->mirror_modifier_clip.tolerance[axis]) {
7093 continue;
7094 }
7095 /* Clear the translation in the local space of the mirror object. */
7096 co_mirror[axis] = 0.0f;
7097 const float3 co_local = math::transform_point(mirror_inverse, co_mirror);
7098 translations[i][axis] = co_local[axis] - positions[i][axis];
7099 }
7100 }
7101}
7102
7103PositionDeformData::PositionDeformData(const Depsgraph &depsgraph, Object &object_orig)
7104{
7105 Mesh &mesh = *static_cast<Mesh *>(object_orig.data);
7106 this->eval = bke::pbvh::vert_positions_eval(depsgraph, object_orig);
7107
7108 if (!object_orig.sculpt->deform_imats.is_empty()) {
7109 deform_imats_ = object_orig.sculpt->deform_imats;
7110 }
7111 orig_ = mesh.vert_positions_for_write();
7112
7113 MutableSpan eval_mut = bke::pbvh::vert_positions_eval_for_write(depsgraph, object_orig);
7114 if (eval_mut.data() != orig_.data()) {
7115 eval_mut_ = eval_mut;
7116 }
7117
7118 if (Key *keys = mesh.key) {
7119 keys_ = keys;
7120 const int active_index = object_orig.shapenr - 1;
7121 active_key_ = BKE_keyblock_find_by_index(keys, active_index);
7122 basis_active_ = active_key_ == keys->refkey;
7123 dependent_keys_ = BKE_keyblock_get_dependent_keys(keys_, active_index);
7124 }
7125 else {
7126 keys_ = nullptr;
7127 active_key_ = nullptr;
7128 basis_active_ = false;
7129 }
7130}
7131
7132static void copy_indices(const Span<float3> src, const Span<int> indices, MutableSpan<float3> dst)
7133{
7134 for (const int i : indices) {
7135 dst[i] = src[i];
7136 }
7137}
7138
7139void PositionDeformData::deform(MutableSpan<float3> translations, const Span<int> verts) const
7140{
7141 if (eval_mut_) {
7142 /* Apply translations to the evaluated mesh. This is necessary because multiple brush
7143 * evaluations can happen in between object reevaluations (otherwise just deforming the
7144 * original positions would be enough). */
7145 apply_translations(translations, verts, *eval_mut_);
7146 }
7147
7148 if (deform_imats_) {
7149 /* Apply the reverse procedural deformation, since subsequent translation happens to the state
7150 * from "before" deforming modifiers. */
7151 apply_crazyspace_to_translations(*deform_imats_, verts, translations);
7152 }
7153
7154 if (KeyBlock *key = active_key_) {
7155 const MutableSpan active_key_data(static_cast<float3 *>(key->data), key->totelem);
7156 if (basis_active_) {
7157 /* The active shape key positions and the mesh positions are always kept in sync. */
7158 apply_translations(translations, verts, orig_);
7159 copy_indices(orig_, verts, active_key_data);
7160 }
7161 else {
7162 apply_translations(translations, verts, active_key_data);
7163 }
7164
7165 if (dependent_keys_) {
7166 int i;
7167 LISTBASE_FOREACH_INDEX (KeyBlock *, other_key, &keys_->block, i) {
7168 if ((other_key != key) && (*dependent_keys_)[i]) {
7169 MutableSpan data(static_cast<float3 *>(other_key->data), other_key->totelem);
7170 apply_translations(translations, verts, data);
7171 }
7172 }
7173 }
7174 }
7175 else {
7176 apply_translations(translations, verts, orig_);
7177 }
7178}
7179
7181 const Mesh &mesh,
7182 const KeyBlock &active_key,
7183 const Span<int> verts,
7184 const Span<float3> translations,
7185 const Span<float3> positions_orig)
7186{
7187 const MutableSpan active_key_data(static_cast<float3 *>(active_key.data), active_key.totelem);
7188 if (&active_key == mesh.key->refkey) {
7189 for (const int vert : verts) {
7190 active_key_data[vert] = positions_orig[vert];
7191 }
7192 }
7193 else {
7194 apply_translations(translations, verts, active_key_data);
7195 }
7196
7197 if (std::optional<Array<bool>> dependent = BKE_keyblock_get_dependent_keys(mesh.key,
7198 object.shapenr - 1))
7199 {
7200 int i;
7201 LISTBASE_FOREACH_INDEX (KeyBlock *, other_key, &mesh.key->block, i) {
7202 if ((other_key != &active_key) && (*dependent)[i]) {
7203 MutableSpan<float3> data(static_cast<float3 *>(other_key->data), other_key->totelem);
7204 apply_translations(translations, verts, data);
7205 }
7206 }
7207 }
7208}
7209
7210void scale_translations(const MutableSpan<float3> translations, const Span<float> factors)
7211{
7212 for (const int i : translations.index_range()) {
7213 translations[i] *= factors[i];
7214 }
7215}
7216
7217void scale_translations(const MutableSpan<float3> translations, const float factor)
7218{
7219 if (factor == 1.0f) {
7220 return;
7221 }
7222 for (const int i : translations.index_range()) {
7223 translations[i] *= factor;
7224 }
7225}
7226
7227void scale_factors(const MutableSpan<float> factors, const float strength)
7228{
7229 if (strength == 1.0f) {
7230 return;
7231 }
7232 for (float &factor : factors) {
7233 factor *= strength;
7234 }
7235}
7236
7237void scale_factors(const MutableSpan<float> factors, const Span<float> strengths)
7238{
7239 BLI_assert(factors.size() == strengths.size());
7240
7241 for (const int i : factors.index_range()) {
7242 factors[i] *= strengths[i];
7243 }
7244}
7245
7247 const Span<float> factors,
7248 const MutableSpan<float3> r_translations)
7249{
7250 BLI_assert(r_translations.size() == factors.size());
7251
7252 for (const int i : factors.index_range()) {
7253 r_translations[i] = offset * factors[i];
7254 }
7255}
7256
7258 const Span<int> verts,
7259 const Span<float3> old_positions,
7260 const MutableSpan<float3> translations)
7261{
7262 BLI_assert(new_positions.size() == verts.size());
7263 for (const int i : verts.index_range()) {
7264 translations[i] = new_positions[i] - old_positions[verts[i]];
7265 }
7266}
7267
7269 const Span<float3> old_positions,
7270 const MutableSpan<float3> translations)
7271{
7272 BLI_assert(new_positions.size() == old_positions.size());
7273 for (const int i : new_positions.index_range()) {
7274 translations[i] = new_positions[i] - old_positions[i];
7275 }
7276}
7277
7279 const float4x4 &transform,
7280 const MutableSpan<float3> dst)
7281{
7282 BLI_assert(src.size() == dst.size());
7283
7284 for (const int i : src.index_range()) {
7285 dst[i] = math::transform_point(transform, src[i]);
7286 }
7287}
7288
7289void transform_positions(const float4x4 &transform, const MutableSpan<float3> positions)
7290{
7291 for (const int i : positions.index_range()) {
7292 positions[i] = math::transform_point(transform, positions[i]);
7293 }
7294}
7295
7297 const IndexMask &node_mask,
7298 Array<int> &node_data)
7299{
7300 node_data.reinitialize(node_mask.size() + 1);
7301 node_mask.foreach_index(
7302 [&](const int i, const int pos) { node_data[pos] = nodes[i].verts().size(); });
7303 return offset_indices::accumulate_counts_to_offsets(node_data);
7304}
7305
7307 const Span<bke::pbvh::GridsNode> nodes,
7308 const IndexMask &node_mask,
7309 Array<int> &node_data)
7310{
7311 node_data.reinitialize(node_mask.size() + 1);
7312 node_mask.foreach_index([&](const int i, const int pos) {
7313 node_data[pos] = nodes[i].grids().size() * key.grid_area;
7314 });
7315 return offset_indices::accumulate_counts_to_offsets(node_data);
7316}
7317
7319 const IndexMask &node_mask,
7320 Array<int> &node_data)
7321{
7322 node_data.reinitialize(node_mask.size() + 1);
7323 node_mask.foreach_index([&](const int i, const int pos) {
7324 node_data[pos] =
7326 });
7327 return offset_indices::accumulate_counts_to_offsets(node_data);
7328}
7329
7331 const Span<int> corner_verts,
7332 const GroupedSpan<int> vert_to_face,
7333 const Span<bool> hide_poly,
7334 const Span<int> verts,
7335 const MutableSpan<Vector<int>> result)
7336{
7337 BLI_assert(result.size() == verts.size());
7338 BLI_assert(corner_verts.size() == faces.total_size());
7339 for (const int i : verts.index_range()) {
7340 vert_neighbors_get_mesh(faces, corner_verts, vert_to_face, hide_poly, verts[i], result[i]);
7341 }
7342}
7343
7344void calc_vert_neighbors(const SubdivCCG &subdiv_ccg,
7345 const Span<int> grids,
7346 const MutableSpan<Vector<SubdivCCGCoord>> result)
7347{
7348 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
7349 SubdivCCGNeighbors neighbors;
7350 BLI_assert(result.size() == grids.size() * key.grid_area);
7351 for (const int i : grids.index_range()) {
7352 const int grid = grids[i];
7353 const int node_verts_start = i * key.grid_area;
7354
7355 for (const int y : IndexRange(key.grid_size)) {
7356 for (const int x : IndexRange(key.grid_size)) {
7357 const int offset = CCG_grid_xy_to_index(key.grid_size, x, y);
7358 const int node_vert_index = node_verts_start + offset;
7359
7360 SubdivCCGCoord coord{};
7361 coord.grid_index = grid;
7362 coord.x = x;
7363 coord.y = y;
7364
7365 BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, false, neighbors);
7366
7367 result[node_vert_index] = Vector<SubdivCCGCoord>(neighbors.coords.as_span());
7368 }
7369 }
7370 }
7371}
7373{
7374 BLI_assert(verts.size() == result.size());
7375
7376 int i = 0;
7377 Vector<BMVert *, 64> neighbor_data;
7378 for (BMVert *vert : verts) {
7379 Span<BMVert *> neighbors = vert_neighbors_get_bmesh(*vert, neighbor_data);
7380 result[i] = Vector<BMVert *>(neighbors);
7381 i++;
7382 }
7383}
7384
7386 const Span<int> corner_verts,
7387 const GroupedSpan<int> vert_to_face,
7388 const BitSpan boundary_verts,
7389 const Span<bool> hide_poly,
7390 const Span<int> verts,
7391 const MutableSpan<Vector<int>> result)
7392{
7393 BLI_assert(result.size() == verts.size());
7394 BLI_assert(corner_verts.size() == faces.total_size());
7395
7396 for (const int i : verts.index_range()) {
7397 const int vert = verts[i];
7398 Vector<int> &neighbors = result[i];
7399 vert_neighbors_get_mesh(faces, corner_verts, vert_to_face, hide_poly, verts[i], neighbors);
7400
7401 if (boundary_verts[vert]) {
7402 if (neighbors.size() == 2) {
7403 /* Do not include neighbors of corner vertices. */
7404 neighbors.clear();
7405 }
7406 else {
7407 /* Only include other boundary vertices as neighbors of boundary vertices. */
7408 neighbors.remove_if([&](const int vert) { return !boundary_verts[vert]; });
7409 }
7410 }
7411 }
7412}
7413
7415 const Span<int> corner_verts,
7416 const BitSpan boundary_verts,
7417 const SubdivCCG &subdiv_ccg,
7418 const Span<int> grids,
7419 const MutableSpan<Vector<SubdivCCGCoord>> result)
7420{
7421 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
7422
7423 BLI_assert(grids.size() * key.grid_area == result.size());
7424
7425 for (const int i : grids.index_range()) {
7426 const int grid = grids[i];
7427 const int node_verts_start = i * key.grid_area;
7428
7429 /* TODO: This loop could be optimized in the future by skipping unnecessary logic for
7430 * non-boundary grid vertices. */
7431 for (const int y : IndexRange(key.grid_size)) {
7432 for (const int x : IndexRange(key.grid_size)) {
7433 const int offset = CCG_grid_xy_to_index(key.grid_size, x, y);
7434 const int node_vert_index = node_verts_start + offset;
7435
7436 SubdivCCGCoord coord{};
7437 coord.grid_index = grid;
7438 coord.x = x;
7439 coord.y = y;
7440
7441 SubdivCCGNeighbors neighbors;
7442 BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, false, neighbors);
7443
7445 faces, corner_verts, boundary_verts, subdiv_ccg, coord))
7446 {
7447 if (neighbors.coords.size() == 2) {
7448 /* Do not include neighbors of corner vertices. */
7449 neighbors.coords.clear();
7450 }
7451 else {
7452 /* Only include other boundary vertices as neighbors of boundary vertices. */
7453 neighbors.coords.remove_if([&](const SubdivCCGCoord coord) {
7455 faces, corner_verts, boundary_verts, subdiv_ccg, coord);
7456 });
7457 }
7458 }
7459 result[node_vert_index] = neighbors.coords;
7460 }
7461 }
7462 }
7463}
7464
7467{
7468 BLI_assert(verts.size() == result.size());
7469 Vector<BMVert *, 64> neighbor_data;
7470
7471 int i = 0;
7472 for (BMVert *vert : verts) {
7473 vert_neighbors_get_interior_bmesh(*vert, neighbor_data);
7474 result[i] = neighbor_data;
7475 i++;
7476 }
7477}
7478
7480 const Span<int> verts,
7481 const float4 &plane,
7482 const MutableSpan<float3> translations)
7483{
7484 for (const int i : verts.index_range()) {
7485 const float3 &position = vert_positions[verts[i]];
7487 closest_to_plane_normalized_v3(closest, plane, position);
7488 translations[i] = closest - position;
7489 }
7490}
7491
7493 const float4 &plane,
7494 const MutableSpan<float3> translations)
7495{
7496 for (const int i : positions.index_range()) {
7497 const float3 &position = positions[i];
7499 closest_to_plane_normalized_v3(closest, plane, position);
7500 translations[i] = closest - position;
7501 }
7502}
7503
7505 const float3 &pivot,
7506 const ePaintSymmetryFlags symm,
7507 const MutableSpan<float> factors)
7508{
7509 BLI_assert(positions.size() == factors.size());
7510
7511 for (const int i : positions.index_range()) {
7512 if (!SCULPT_check_vertex_pivot_symmetry(positions[i], pivot, symm)) {
7513 factors[i] = 0.0f;
7514 }
7515 }
7516}
7517
7519 const StrokeCache &cache,
7520 const Span<float3> translations,
7521 const MutableSpan<float> factors)
7522{
7523 if (!(brush.flag & BRUSH_PLANE_TRIM)) {
7524 return;
7525 }
7526 const float threshold = cache.radius_squared * cache.plane_trim_squared;
7527 for (const int i : translations.index_range()) {
7528 if (math::length_squared(translations[i]) > threshold) {
7529 factors[i] = 0.0f;
7530 }
7531 }
7532}
7533
7535 const Span<int> verts,
7536 const float4 &plane,
7537 const MutableSpan<float> factors)
7538{
7539 for (const int i : verts.index_range()) {
7540 if (plane_point_side_v3(plane, vert_positions[verts[i]]) <= 0.0f) {
7541 factors[i] = 0.0f;
7542 }
7543 }
7544}
7545
7547 const float4 &plane,
7548 const MutableSpan<float> factors)
7549{
7550 for (const int i : positions.index_range()) {
7551 if (plane_point_side_v3(plane, positions[i]) <= 0.0f) {
7552 factors[i] = 0.0f;
7553 }
7554 }
7555}
7556
7558 const Span<int> verts,
7559 const float4 &plane,
7560 const MutableSpan<float> factors)
7561{
7562 for (const int i : verts.index_range()) {
7563 if (plane_point_side_v3(plane, vert_positions[verts[i]]) > 0.0f) {
7564 factors[i] = 0.0f;
7565 }
7566 }
7567}
7568
7570 const float4 &plane,
7571 const MutableSpan<float> factors)
7572{
7573 for (const int i : positions.index_range()) {
7574 if (plane_point_side_v3(plane, positions[i]) > 0.0f) {
7575 factors[i] = 0.0f;
7576 }
7577 }
7578}
7579
7580} // 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
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)
@ SCULPT_DISP_DIR_VIEW
@ SCULPT_DISP_DIR_X
@ SCULPT_DISP_DIR_Z
@ SCULPT_DISP_DIR_Y
@ SCULPT_DISP_DIR_AREA
@ CD_PROP_FLOAT
@ KEYBLOCK_LOCKED_SHAPE
@ eModifierMode_Realtime
@ eModifierType_Mirror
@ MOD_MIR_CLIPPING
@ MOD_MIR_AXIS_X
@ 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
@ 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 vector
void ntreeTexEndExecTree(struct bNodeTreeExec *exec)
struct bNodeTreeExec * ntreeTexBeginExecTree(struct bNodeTree *ntree)
@ OPTYPE_BLOCKING
Definition WM_types.hh:164
#define ND_DRAW
Definition WM_types.hh:428
#define NC_OBJECT
Definition WM_types.hh:346
#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
SIMD_FORCE_INLINE void invalidate()
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
unsigned int U
Definition btGjkEpa3.h:78
bool closest(btVector3 &v)
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
bool is_empty() const
Definition BLI_array.hh:253
int calc_reduced_ids(MutableSpan< int > result) const
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
int64_t size() const
Definition BLI_set.hh:564
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 reinitialize(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
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
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)
IndexMask slice(IndexRange range) const
static IndexMask from_bools(Span< bool > bools, IndexMaskMemory &memory)
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
CCL_NAMESPACE_BEGIN ccl_device_inline float frac(float x, ccl_private int *ix)
const Depsgraph * depsgraph
#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)
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
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)
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
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)
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 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:5770
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)
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:6013
static SculptTopologyIslandCache calc_topology_islands_grids(const Object &object)
Definition sculpt.cc:5946
static SculptTopologyIslandCache vert_disjoint_set_to_islands(const AtomicDisjointSet &vert_sets, const int verts_num)
Definition sculpt.cc:5900
static SculptTopologyIslandCache calc_topology_islands_mesh(const Mesh &mesh)
Definition sculpt.cc:5921
static SculptTopologyIslandCache calculate_cache(const Object &object)
Definition sculpt.cc:5999
static SculptTopologyIslandCache calc_topology_islands_bmesh(const Object &object)
Definition sculpt.cc:5971
int vert_id_get(const SculptSession &ss, const int vert)
Definition sculpt.cc:5880
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 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
void fill_factor_from_hide_and_mask(Span< bool > hide_vert, Span< float > mask, Span< int > verts, MutableSpan< float > r_factors)
Definition sculpt.cc:6490
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)
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:7180
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:5536
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:6148
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:6373
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:5466
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6054
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)
static void stroke_update_step(bContext *C, wmOperator *, PaintStroke *stroke, PointerRNA *itemptr)
Definition sculpt.cc:5233
void calc_brush_strength_factors(const StrokeCache &cache, const Brush &brush, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:6889
static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition sculpt.cc:5344
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:6092
static void redo_empty_ui(bContext *, wmOperator *)
Definition sculpt.cc:5471
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:7385
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:7534
void apply_hardness_to_distances(float radius, float hardness, MutableSpan< float > distances)
Definition sculpt.cc:6862
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:6270
void gather_bmesh_normals(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > normals)
Definition sculpt.cc:6072
static void pose_fake_neighbors_free(SculptSession &ss)
Definition sculpt.cc:5512
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:6199
void filter_distances_with_radius(float radius, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:6772
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:7132
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 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:7318
void filter_region_clip_factors(const SculptSession &ss, Span< float3 > vert_positions, Span< int > verts, MutableSpan< float > factors)
Definition sculpt.cc:6639
void gather_data_bmesh(Span< T > src, const Set< BMVert *, 0 > &verts, MutableSpan< T > node_data)
Definition sculpt.cc:6108
void flush_update_done(const bContext *C, Object &ob, UpdateType update_type)
Definition sculpt.cc:5055
static void fake_neighbor_init(Object &object, const float max_dist)
Definition sculpt.cc:5504
void reset_translations_to_original(MutableSpan< float3 > translations, Span< float3 > positions, Span< float3 > orig_positions)
Definition sculpt.cc:6946
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:6722
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:7210
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 brush_exit_tex(Sculpt &sd)
Definition sculpt.cc:5284
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:7504
static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op)
Definition sculpt.cc:5424
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:7479
void scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7227
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:6337
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:7257
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:7022
static void sculpt_brush_stroke_cancel(bContext *C, wmOperator *op)
Definition sculpt.cc:5443
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
static void stroke_done(const bContext *C, PaintStroke *)
Definition sculpt.cc:5294
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:6122
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:5473
void project_translations(MutableSpan< float3 > translations, const float3 &plane)
Definition sculpt.cc:6998
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:7518
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6958
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:6235
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:6082
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:7330
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:5592
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:7557
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:6783
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:7011
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:5620
void calc_front_face(const float3 &view_normal, Span< float3 > normals, MutableSpan< float > factors)
Definition sculpt.cc:6581
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 bool stroke_test_start(bContext *C, wmOperator *op, const float mval[2])
Definition sculpt.cc:5195
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:5563
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
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:7296
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:6065
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:7246
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:6898
void fill_factor_from_hide(Span< bool > hide_vert, Span< int > verts, MutableSpan< float > r_factors)
Definition sculpt.cc:6442
void scatter_data_grids(const SubdivCCG &subdiv_ccg, Span< T > node_data, Span< int > grids, MutableSpan< T > dst)
Definition sculpt.cc:6132
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:6304
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:6408
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:6694
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)
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)
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
VecBase< float, 3 > float3
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:5161
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:5795
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:5129
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:5824
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:5140
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:6024
void SCULPT_fake_neighbors_free(Object &ob)
Definition sculpt.cc:5817
static CLG_LogRef LOG
Definition sculpt.cc:111
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:5177
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
struct BMVert * v
struct BMLoop * prev
struct BMLoop * next
float co[3]
int totvert
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
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]
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
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
struct SculptSession::@48 multires
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
bToolRef_Runtime * runtime
const c_style_mat & ptr() const
static NearestVertData join(const NearestVertData &a, const NearestVertData &b)
Definition sculpt.cc:5521
struct blender::ed::sculpt_paint::StrokeCache::@481 clay_thumb_brush
std::optional< math::Quaternion > rake_rotation
struct blender::ed::sculpt_paint::StrokeCache::@480 paint_brush
struct blender::ed::sculpt_paint::StrokeCache::@478 mirror_modifier_clip
std::unique_ptr< auto_mask::Cache > automasking
std::optional< math::Quaternion > rake_rotation_symm
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
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
void(* ui)(bContext *C, wmOperator *op)
Definition WM_types.hh:1053
StructRNA * srna
Definition WM_types.hh:1080
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1028
struct ReportList * reports
struct wmOperatorType * type
struct PointerRNA * ptr
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)