127 if (
angle > limit_lower &&
angle < limit_upper) {
128 float t = 1.0f - (
angle - limit_lower) / (limit_upper - limit_lower);
131 t = t * t * (3.0 - 2.0 * t);
135 if (
angle > limit_upper) {
182 if (automasking_flags &
237 const float3 &vert_position)
253 factor = factor *
sign * 0.5f + 0.5f;
254 CLAMP(factor, 0.0f, 1.0f);
268 const Cache &automasking,
273 struct CavityBlurVert {
295 const int num_steps =
steps + 1;
297 std::queue<CavityBlurVert> queue;
300 const CavityBlurVert initial{vert, 0};
304 const float3 starting_position = positions_eval[vert];
307 while (!queue.empty()) {
308 const CavityBlurVert blurvert = queue.front();
311 const int current_vert = blurvert.vertex;
313 const float3 &blur_vert_position = positions_eval[current_vert];
314 const float3 &blur_vert_normal = normals_eval[current_vert];
316 const float dist_to_start =
math::distance(blur_vert_position, starting_position);
318 all_verts.
position += blur_vert_position;
319 all_verts.
distance += dist_to_start;
322 if (blurvert.depth < num_steps) {
323 verts_in_range.
position += blur_vert_position;
324 verts_in_range.
normal += blur_vert_normal;
325 verts_in_range.
count++;
330 if (blurvert.depth >= num_steps) {
335 faces, corner_verts, vert_to_face_map, hide_poly, current_vert, neighbors))
337 if (visited_verts.
contains(neighbor)) {
341 visited_verts.
add_new(neighbor);
342 queue.push({neighbor, blurvert.depth + 1});
348 if (all_verts.
count == 0) {
349 all_verts.
position = positions_eval[vert];
356 if (verts_in_range.
count == 0) {
357 verts_in_range.
position = positions_eval[vert];
365 verts_in_range.
normal = normals_eval[vert];
374 const Cache &automasking,
379 struct CavityBlurVert {
395 const int num_steps =
steps + 1;
397 std::queue<CavityBlurVert> queue;
400 const CavityBlurVert initial{vert.
to_index(key), 0};
401 visited_verts.
add_new(initial.vert);
407 while (!queue.empty()) {
408 const CavityBlurVert blurvert = queue.front();
411 const int current_vert = blurvert.vert;
413 const float3 &blur_vert_position = positions[current_vert];
416 const float dist_to_start =
math::distance(blur_vert_position, starting_position);
418 all_verts.
position += blur_vert_position;
419 all_verts.
distance += dist_to_start;
422 if (blurvert.depth < num_steps) {
423 verts_in_range.
position += blur_vert_position;
424 verts_in_range.
normal += blur_vert_normal;
425 verts_in_range.
count++;
430 if (blurvert.depth >= num_steps) {
437 const int neighbor_idx = neighbor.
to_index(key);
438 if (visited_verts.
contains(neighbor_idx)) {
442 visited_verts.
add_new(neighbor_idx);
443 queue.push({neighbor_idx, blurvert.depth + 1});
449 if (all_verts.
count == 0) {
457 if (verts_in_range.
count == 0) {
479 struct CavityBlurVert {
490 const int num_steps =
steps + 1;
492 std::queue<CavityBlurVert> queue;
496 visited_verts.
add_new(initial.index);
499 const float3 starting_position = vert->
co;
502 while (!queue.empty()) {
503 const CavityBlurVert blurvert = queue.front();
506 BMVert *current_vert = blurvert.vertex;
508 const float3 blur_vert_position = current_vert->
co;
509 const float3 blur_vert_normal = current_vert->
no;
511 const float dist_to_start =
math::distance(blur_vert_position, starting_position);
513 all_verts.
position += blur_vert_position;
514 all_verts.
distance += dist_to_start;
517 if (blurvert.depth < num_steps) {
518 verts_in_range.
position += blur_vert_position;
519 verts_in_range.
normal += blur_vert_normal;
520 verts_in_range.
count++;
525 if (blurvert.depth >= num_steps) {
531 if (visited_verts.
contains(neighbor_idx)) {
535 visited_verts.
add_new(neighbor_idx);
536 queue.push({neighbor, neighbor_idx, blurvert.depth + 1});
542 if (all_verts.
count == 0) {
550 if (verts_in_range.
count == 0) {
574 factor = inverted ? 1.0f - factor : factor;
576 factor = inverted ? 1.0f - factor : factor;
583 const Cache &automasking,
598 const Cache &automasking,
623 const Cache &automasking,
629 const Mesh &
mesh = *
static_cast<const Mesh *
>(
object.data);
642 orig_normals = orig_data->normals;
646 for (
const int i :
verts.index_range()) {
647 const int vert =
verts[
i];
648 const float3 &normal = orig_normals.is_empty() ? vert_normals[vert] : orig_normals[
i];
662 float cached_factor = automasking.
factor[vert];
669 factors[
i] *= cached_factor;
678 depsgraph,
const_cast<Cache &
>(automasking),
object, vert, vert_positions[vert]);
738 const Cache &automasking,
744 const Mesh &
mesh = *
static_cast<const Mesh *
>(
object.data);
755 for (
const int vert : face_verts) {
771 float cached_factor = automasking.
factor[vert];
778 factor *= cached_factor;
787 depsgraph,
const_cast<Cache &
>(automasking),
object, vert, vert_positions[vert]);
847 const Cache &automasking,
853 const Mesh &base_mesh = *
static_cast<const Mesh *
>(
object.data);
855 const Span<int> corner_verts = base_mesh.corner_verts();
869 orig_normals = orig_data->normals;
874 const int grid_face_set = face_sets.
is_empty() ?
876 face_sets[subdiv_ccg.grid_to_face_map[grids[
i]]];
878 const int grids_start = grids[
i] * key.
grid_area;
880 const int node_vert = node_start + offset;
881 const int vert = grids_start + offset;
882 const float3 &normal = orig_normals.
is_empty() ? subdiv_ccg.normals[vert] :
883 orig_normals[node_vert];
897 float cached_factor = automasking.
factor[vert];
904 factors[node_vert] *= cached_factor;
913 depsgraph,
const_cast<Cache &
>(automasking),
object, vert, subdiv_ccg.positions[vert]);
915 factors[node_vert] = 0.0f;
924 factors[node_vert] = 0.0f;
930 factors[node_vert] = 0.0f;
939 factors[node_vert] = 0.0f;
956 factors[node_vert] = 0.0f;
977 const Cache &automasking,
1012 float cached_factor = automasking.
factor[vert_i];
1019 factors[
i] *= cached_factor;
1028 depsgraph,
const_cast<Cache &
>(automasking),
object, vert_i, vert->co);
1095 const float radius = ss.
cache ? ss.
cache->
radius : std::numeric_limits<float>::max();
1096 const int active_vert = std::get<int>(ss.
active_vert());
1104 float3 location = vert_positions[active_vert];
1107 flood.
execute(ob, vert_to_face_map, [&](
int from_v,
int to_v) {
1108 factors[from_v] = 1.0f;
1109 factors[to_v] = 1.0f;
1111 vert_positions[to_v], location, radius, symm);
1115 flood.
execute(ob, vert_to_face_map, [&](
int from_v,
int to_v) {
1116 factors[from_v] = 1.0f;
1117 factors[to_v] = 1.0f;
1132 const float radius = ss.
cache ? ss.
cache->
radius : std::numeric_limits<float>::max();
1145 float3 location = positions[active_vert];
1150 factors[from_v.
to_index(key)] = 1.0f;
1151 factors[to_v.
to_index(key)] = 1.0f;
1153 positions[to_v.
to_index(key)], location, radius, symm);
1159 factors[from_v.
to_index(key)] = 1.0f;
1160 factors[to_v.
to_index(key)] = 1.0f;
1174 const float radius = ss.
cache ? ss.
cache->
radius : std::numeric_limits<float>::max();
1210 if (std::holds_alternative<std::monostate>(ss.
active_vert())) {
1251 for (const int vert : range) {
1252 if (!face_set::vert_has_face_set(vert_to_face_map, face_sets, vert, active_face_set)) {
1253 factors[vert] = 0.0f;
1260 const Mesh &base_mesh = *
static_cast<const Mesh *
>(ob.
data);
1270 const int grid_area = subdiv_ccg.
grid_area;
1272 for (const int face : range) {
1273 if (face_sets[face] != active_face_set) {
1274 factors.slice(bke::ccg::face_range(faces, grid_area, face)).fill(0.0f);
1286 if (face_set_offset == -1) {
1290 for (const int i : range) {
1291 const BMVert *vert = BM_vert_at_index(&const_cast<BMesh &>(bm), i);
1292 if (!face_set::vert_has_face_set(face_set_offset, *vert, active_face_set)) {
1312 const int propagation_steps,
1332 edge_distance[
i] = 0;
1337 edge_distance[
i] = 0;
1344 for (
const int propagation_it :
IndexRange(propagation_steps)) {
1350 for (
const int neighbor :
1353 if (edge_distance[neighbor] == propagation_it) {
1354 edge_distance[
i] = propagation_it + 1;
1365 const float p = 1.0f - (float(edge_distance[
i]) / float(propagation_steps));
1366 const float edge_boundary_automask =
pow2f(p);
1368 factors[
i] *= (1.0f - edge_boundary_automask);
1374 const int propagation_steps,
1398 edge_distance[
i] = 0;
1403 faces, corner_verts, vert_to_face_map, face_sets, subdiv_ccg, coord))
1405 edge_distance[
i] = 0;
1412 for (
const int propagation_it :
IndexRange(propagation_steps)) {
1422 const int neighbor_idx = neighbor.
to_index(key);
1423 if (edge_distance[neighbor_idx] == propagation_it) {
1424 edge_distance[
i] = propagation_it + 1;
1435 const float p = 1.0f - (float(edge_distance[
i]) / float(propagation_steps));
1436 const float edge_boundary_automask =
pow2f(p);
1438 factors[
i] *= (1.0f - edge_boundary_automask);
1444 const int propagation_steps,
1460 edge_distance[
i] = 0;
1465 edge_distance[
i] = 0;
1471 for (
const int propagation_it :
IndexRange(propagation_steps)) {
1481 if (edge_distance[neighbor_idx] == propagation_it) {
1482 edge_distance[
i] = propagation_it + 1;
1493 const float p = 1.0f - (float(edge_distance[
i]) / float(propagation_steps));
1494 const float edge_boundary_automask =
pow2f(p);
1496 factors[
i] *= (1.0f - edge_boundary_automask);
1503 const int propagation_steps,
1571 for (
const int vert : range) {
1572 float f = factors[vert];
1577 depsgraph, automasking, ob, vert, vert_positions[vert]);
1592 for (
const int vert : range) {
1593 float f = factors[vert];
1613 for (const int i : range) {
1614 const BMVert *vert = BM_vert_at_index(&bm, i);
1615 float f = factors[i];
1617 if (int(mode) & BRUSH_AUTOMASKING_VIEW_NORMAL) {
1618 if (int(mode) & BRUSH_AUTOMASKING_VIEW_OCCLUSION) {
1619 f *= calc_view_occlusion_factor(depsgraph, automasking, ob, i, vert->co);
1622 f *= calc_view_normal_factor(automasking, ob, vert->no);
1644 std::unique_ptr<Cache> automasking = std::make_unique<Cache>();
1671 automasking->cavity_factor =
Array<float>(verts_num, -1.0f);
1683 automasking->factor =
Array<float>(verts_num, initial_value);
1758 switch (pbvh.
type()) {
1763 for (
const int vert :
verts) {
1775 for (
const int grid : grids) {
int CustomData_get_offset_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
#define SCULPT_FACE_SET_NONE
const Brush * BKE_paint_brush_for_read(const Paint *paint)
A BVH for high poly meshes.
CCGKey BKE_subdiv_ccg_key_top_level(const SubdivCCG &subdiv_ccg)
void BKE_subdiv_ccg_neighbor_coords_get(const SubdivCCG &subdiv_ccg, const SubdivCCGCoord &coord, bool include_duplicates, SubdivCCGNeighbors &r_neighbors)
MINLINE float pow2f(float x)
MINLINE float signf(float f)
#define BLI_SCOPED_DEFER(function_to_defer)
@ BRUSH_AUTOMASKING_BRUSH_NORMAL
@ BRUSH_AUTOMASKING_CAVITY_NORMAL
@ BRUSH_AUTOMASKING_VIEW_OCCLUSION
@ BRUSH_AUTOMASKING_BOUNDARY_EDGES
@ BRUSH_AUTOMASKING_CAVITY_USE_CURVE
@ BRUSH_AUTOMASKING_BOUNDARY_FACE_SETS
@ BRUSH_AUTOMASKING_FACE_SETS
@ BRUSH_AUTOMASKING_VIEW_NORMAL
@ BRUSH_AUTOMASKING_TOPOLOGY
@ BRUSH_AUTOMASKING_CAVITY_ALL
@ BRUSH_AUTOMASKING_CAVITY_INVERTED
@ SCULPT_BRUSH_TYPE_THUMB
@ SCULPT_BRUSH_TYPE_DRAW_FACE_SETS
@ SCULPT_BRUSH_TYPE_ROTATE
@ PAINT_FALLOFF_SHAPE_TUBE
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
#define BM_elem_index_get(ele)
int BM_mesh_elem_count(BMesh *bm, const char htype)
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
BPy_StructRNA * depsgraph
static T sum(const btAlignedObjectArray< T > &items)
bool contains(const Key &key) const
void add_new(const Key &key)
constexpr Span slice(int64_t start, int64_t size) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
GAttributeReader lookup(const StringRef attribute_id) const
Span< NodeT > nodes() const
void foreach_index(Fn &&fn) const
static float normals[][3]
IndexRange grid_range(const int grid_area, const int grid)
pbvh::Tree * pbvh_get(Object &object)
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
static void calc_blurred_cavity_mesh(const Depsgraph &depsgraph, const Object &object, const Cache &automasking, const int steps, const int vert, MutableSpan< float > cavity_factors)
static int calc_effective_bits(const Sculpt &sd, const Brush *brush)
static float calc_brush_normal_factor(const Cache &automasking, const Object &object, const float3 &normal)
static float normal_calc(const float3 &compare_normal, const float3 &normal, float limit_lower, float limit_upper)
static void calc_cavity_factor_bmesh(const Cache &automasking, BMVert *vert, const int vert_i)
static bool calc_view_occlusion_factor(const Depsgraph &depsgraph, Cache &automasking, const Object &object, const int vert, const float3 &vert_position)
static void init_face_sets_masking(const Sculpt &sd, Object &ob, MutableSpan< float > factors)
static void calc_cavity_factor_mesh(const Depsgraph &depsgraph, const Cache &automasking, const Object &object, const int vert)
static void init_boundary_masking(Object &object, const Depsgraph &depsgraph, const BoundaryAutomaskMode mode, const int propagation_steps, MutableSpan< float > factors)
const Cache * active_cache_get(const SculptSession &ss)
static float calc_view_normal_factor(const Cache &automasking, const Object &object, const float3 &normal)
static void fill_topology_automasking_factors_grids(const Sculpt &sd, Object &ob, const SubdivCCG &subdiv_ccg, MutableSpan< float > factors)
Cache & stroke_cache_ensure(const Depsgraph &depsgraph, const Sculpt &sd, const Brush *brush, Object &ob)
static void init_boundary_masking_bmesh(Object &object, const BoundaryAutomaskMode mode, const int propagation_steps, MutableSpan< float > factors)
Cache & filter_cache_ensure(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob)
static bool needs_factors_cache(const Sculpt &sd, const Brush *brush)
static void normal_occlusion_automasking_fill(const Depsgraph &depsgraph, Cache &automasking, Object &ob, eAutomasking_flag mode, MutableSpan< float > factors)
static void calc_blurred_cavity_grids(const Object &object, const Cache &automasking, const int steps, const SubdivCCGCoord vert, MutableSpan< float > cavity_factors)
static void fill_topology_automasking_factors_mesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const Span< float3 > vert_positions, MutableSpan< float > factors)
static void init_boundary_masking_mesh(Object &object, const Depsgraph &depsgraph, const BoundaryAutomaskMode mode, const int propagation_steps, MutableSpan< float > factors)
static void fill_topology_automasking_factors_bmesh(const Sculpt &sd, Object &ob, BMesh &bm, MutableSpan< float > factors)
static void cache_settings_update(Cache &automasking, Object &object, const Sculpt &sd, const Brush *brush)
static constexpr int EDGE_DISTANCE_INF
static void init_boundary_masking_grids(Object &object, const BoundaryAutomaskMode mode, const int propagation_steps, MutableSpan< float > factors)
static void calc_blurred_cavity_bmesh(const Cache &automasking, const int steps, BMVert *vert, MutableSpan< float > cavity_factors)
void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &automasking, const bke::pbvh::MeshNode &node, Span< int > verts, MutableSpan< float > factors)
void calc_grids_factors(const Depsgraph &depsgraph, const Object &object, const Cache &automasking, const bke::pbvh::GridsNode &node, Span< int > grids, MutableSpan< float > factors)
bool is_enabled(const Sculpt &sd, const Object &object, const Brush *br)
static void fill_topology_automasking_factors(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, MutableSpan< float > factors)
void calc_face_factors(const Depsgraph &depsgraph, const Object &object, OffsetIndices< int > faces, Span< int > corner_verts, const Cache &automasking, const bke::pbvh::MeshNode &node, Span< int > face_indices, MutableSpan< float > factors)
static int boundary_propagation_steps(const Sculpt &sd, const Brush *brush)
static float calc_cavity_factor(const Cache &automasking, float factor)
static bool is_constrained_by_radius(const Brush *br)
bool mode_enabled(const Sculpt &sd, const Brush *br, eAutomasking_flag mode)
std::unique_ptr< Cache > cache_init(const Depsgraph &depsgraph, const Sculpt &sd, const Brush *brush, Object &ob)
static float process_cavity_factor(const Cache &automasking, float factor)
static void calc_cavity_factor_grids(const CCGKey &key, const Cache &automasking, const Object &object, const int vert)
bool vert_is_boundary(const GroupedSpan< int > vert_to_face_map, const Span< bool > hide_poly, const BitSpan boundary, const int vert)
void ensure_boundary_info(Object &object)
bool stroke_is_dyntopo(const Object &object, const Brush &brush)
int vert_face_set_get(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const int vert)
bool vert_has_unique_face_set(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, int vert)
bool vert_has_face_set(const GroupedSpan< int > vert_to_face_map, const Span< int > face_sets, const int vert, const int face_set)
int active_face_set_get(const Object &object)
void ensure_cache(Object &object)
int vert_id_get(const SculptSession &ss, const int vert)
void vert_random_access_ensure(Object &object)
Vector< int > find_symm_verts_grids(const Object &object, const int original_vert, const float max_distance)
Vector< BMVert *, 64 > BMeshNeighborVerts
std::optional< OrigPositionData > orig_position_data_lookup_grids(const Object &object, const bke::pbvh::GridsNode &node)
void orig_position_data_gather_bmesh(const BMLog &bm_log, const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions, MutableSpan< float3 > normals)
Vector< int > find_symm_verts_mesh(const Depsgraph &depsgraph, const Object &object, const int original_vert, const float max_distance)
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, BMeshNeighborVerts &r_neighbors)
bool vertex_is_occluded(const Depsgraph &depsgraph, const Object &object, const float3 &position, bool original)
std::optional< OrigPositionData > orig_position_data_lookup_mesh(const Object &object, const bke::pbvh::MeshNode &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)
Vector< int > find_symm_verts_bmesh(const Object &object, const int original_vert, const float max_distance)
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)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
VecBase< float, 3 > float3
ePaintSymmetryFlags SCULPT_mesh_symmetry_xyz_get(const Object &object)
int SCULPT_vertex_count_get(const Object &object)
bool SCULPT_is_vertex_inside_brush_radius_symm(const float vertex[3], const float br_co[3], float radius, char symm)
float automasking_cavity_factor
float automasking_view_normal_limit
int automasking_cavity_blur_steps
int automasking_boundary_edges_propagation_steps
struct CurveMapping * automasking_cavity_curve
float automasking_start_normal_limit
float automasking_start_normal_falloff
float automasking_view_normal_falloff
struct SculptSession * sculpt
blender::ed::sculpt_paint::StrokeCache * cache
blender::ed::sculpt_paint::filter::Cache * filter_cache
SculptVertexInfo vertex_info
ActiveVert active_vert() const
int active_vert_index() const
blender::BitVector boundary
float automasking_start_normal_falloff
int automasking_boundary_edges_propagation_steps
float automasking_view_normal_limit
float automasking_cavity_factor
int automasking_cavity_blur_steps
float automasking_start_normal_limit
struct CurveMapping * automasking_cavity_curve
float automasking_view_normal_falloff
int to_index(const CCGKey &key) const
static SubdivCCGCoord from_index(const CCGKey &key, int index)
SubdivCCGNeighborCoords coords
blender::Array< blender::float3 > normals
blender::Array< blender::float3 > positions
float3 initial_normal_symm
std::unique_ptr< auto_mask::Cache > automasking
void calc_cavity_factor(const Depsgraph &depsgraph, const Object &object, const IndexMask &node_mask)
Array< OcclusionValue > occlusion
Array< float > cavity_factor
float start_normal_falloff
CurveMapping * cavity_curve
float view_normal_falloff
bool topology_use_brush_limit
std::unique_ptr< auto_mask::Cache > automasking
void add_initial(BMVert *vertex)
void execute(Object &object, FunctionRef< bool(BMVert *from_v, BMVert *to_v)> func)
void execute(Object &object, const SubdivCCG &subdiv_ccg, FunctionRef< bool(SubdivCCGCoord from_v, SubdivCCGCoord to_v, bool is_duplicate)> func)
void add_initial(SubdivCCGCoord vertex)
void execute(Object &object, GroupedSpan< int > vert_to_face_map, FunctionRef< bool(int from_v, int to_v)> func)
void add_initial(int vertex)