126 if (
angle > limit_lower &&
angle < limit_upper) {
127 float t = 1.0f - (
angle - limit_lower) / (limit_upper - limit_lower);
130 t = t * t * (3.0 - 2.0 * t);
134 if (
angle > limit_upper) {
181 if (automasking_flags &
236 const float3 &vert_position)
252 factor = factor *
sign * 0.5f + 0.5f;
253 CLAMP(factor, 0.0f, 1.0f);
267 const Cache &automasking,
272 struct CavityBlurVert {
294 const int num_steps = steps + 1;
296 std::queue<CavityBlurVert> queue;
299 const CavityBlurVert initial{vert, 0};
303 const float3 starting_position = positions_eval[vert];
306 while (!queue.empty()) {
307 const CavityBlurVert blurvert = queue.front();
310 const int current_vert = blurvert.vertex;
312 const float3 &blur_vert_position = positions_eval[current_vert];
313 const float3 &blur_vert_normal = normals_eval[current_vert];
315 const float dist_to_start =
math::distance(blur_vert_position, starting_position);
317 all_verts.
position += blur_vert_position;
318 all_verts.
distance += dist_to_start;
321 if (blurvert.depth < num_steps) {
322 verts_in_range.
position += blur_vert_position;
323 verts_in_range.
normal += blur_vert_normal;
324 verts_in_range.
count++;
329 if (blurvert.depth >= num_steps) {
334 faces, corner_verts, vert_to_face_map, hide_poly, current_vert, neighbors))
336 if (visited_verts.
contains(neighbor)) {
340 visited_verts.
add_new(neighbor);
341 queue.push({neighbor, blurvert.depth + 1});
347 if (all_verts.
count == 0) {
348 all_verts.
position = positions_eval[vert];
355 if (verts_in_range.
count == 0) {
356 verts_in_range.
position = positions_eval[vert];
364 verts_in_range.
normal = normals_eval[vert];
373 const Cache &automasking,
378 struct CavityBlurVert {
394 const int num_steps = steps + 1;
396 std::queue<CavityBlurVert> queue;
399 const CavityBlurVert initial{vert.
to_index(key), 0};
400 visited_verts.
add_new(initial.vert);
406 while (!queue.empty()) {
407 const CavityBlurVert blurvert = queue.front();
410 const int current_vert = blurvert.vert;
412 const float3 &blur_vert_position = positions[current_vert];
415 const float dist_to_start =
math::distance(blur_vert_position, starting_position);
417 all_verts.
position += blur_vert_position;
418 all_verts.
distance += dist_to_start;
421 if (blurvert.depth < num_steps) {
422 verts_in_range.
position += blur_vert_position;
423 verts_in_range.
normal += blur_vert_normal;
424 verts_in_range.
count++;
429 if (blurvert.depth >= num_steps) {
436 const int neighbor_idx = neighbor.
to_index(key);
437 if (visited_verts.
contains(neighbor_idx)) {
441 visited_verts.
add_new(neighbor_idx);
442 queue.push({neighbor_idx, blurvert.depth + 1});
448 if (all_verts.
count == 0) {
456 if (verts_in_range.
count == 0) {
478 struct CavityBlurVert {
489 const int num_steps = steps + 1;
491 std::queue<CavityBlurVert> queue;
495 visited_verts.
add_new(initial.index);
498 const float3 starting_position = vert->
co;
501 while (!queue.empty()) {
502 const CavityBlurVert blurvert = queue.front();
505 BMVert *current_vert = blurvert.vertex;
507 const float3 blur_vert_position = current_vert->
co;
508 const float3 blur_vert_normal = current_vert->
no;
510 const float dist_to_start =
math::distance(blur_vert_position, starting_position);
512 all_verts.
position += blur_vert_position;
513 all_verts.
distance += dist_to_start;
516 if (blurvert.depth < num_steps) {
517 verts_in_range.
position += blur_vert_position;
518 verts_in_range.
normal += blur_vert_normal;
519 verts_in_range.
count++;
524 if (blurvert.depth >= num_steps) {
530 if (visited_verts.
contains(neighbor_idx)) {
534 visited_verts.
add_new(neighbor_idx);
535 queue.push({neighbor, neighbor_idx, blurvert.depth + 1});
541 if (all_verts.
count == 0) {
549 if (verts_in_range.
count == 0) {
573 factor = inverted ? 1.0f - factor : factor;
575 factor = inverted ? 1.0f - factor : factor;
582 const Cache &automasking,
597 const Cache &automasking,
622 const Cache &automasking,
628 const Mesh &
mesh = *
static_cast<const Mesh *
>(
object.data);
641 orig_normals = orig_data->normals;
645 for (
const int i :
verts.index_range()) {
646 const int vert =
verts[
i];
647 const float3 &normal = orig_normals.is_empty() ? vert_normals[vert] : orig_normals[
i];
661 float cached_factor = automasking.
factor[vert];
668 factors[
i] *= cached_factor;
677 depsgraph,
const_cast<Cache &
>(automasking),
object, vert, vert_positions[vert]);
737 const Cache &automasking,
743 const Mesh &
mesh = *
static_cast<const Mesh *
>(
object.data);
754 for (
const int vert : face_verts) {
770 float cached_factor = automasking.
factor[vert];
777 factor *= cached_factor;
786 depsgraph,
const_cast<Cache &
>(automasking),
object, vert, vert_positions[vert]);
846 const Cache &automasking,
852 const Mesh &base_mesh = *
static_cast<const Mesh *
>(
object.data);
854 const Span<int> corner_verts = base_mesh.corner_verts();
868 orig_normals = orig_data->normals;
873 const int grid_face_set = face_sets.
is_empty() ?
875 face_sets[subdiv_ccg.grid_to_face_map[grids[
i]]];
877 const int grids_start = grids[
i] * key.
grid_area;
879 const int node_vert = node_start + offset;
880 const int vert = grids_start + offset;
881 const float3 &normal = orig_normals.
is_empty() ? subdiv_ccg.normals[vert] :
882 orig_normals[node_vert];
896 float cached_factor = automasking.
factor[vert];
903 factors[node_vert] *= cached_factor;
912 depsgraph,
const_cast<Cache &
>(automasking),
object, vert, subdiv_ccg.positions[vert]);
914 factors[node_vert] = 0.0f;
923 factors[node_vert] = 0.0f;
929 factors[node_vert] = 0.0f;
938 factors[node_vert] = 0.0f;
955 factors[node_vert] = 0.0f;
976 const Cache &automasking,
1011 float cached_factor = automasking.
factor[vert_i];
1018 factors[
i] *= cached_factor;
1027 depsgraph,
const_cast<Cache &
>(automasking),
object, vert_i, vert->co);
1094 const float radius = ss.
cache ? ss.
cache->
radius : std::numeric_limits<float>::max();
1095 const int active_vert = std::get<int>(ss.
active_vert());
1103 float3 location = vert_positions[active_vert];
1106 flood.
execute(ob, vert_to_face_map, [&](
int from_v,
int to_v) {
1107 factors[from_v] = 1.0f;
1108 factors[to_v] = 1.0f;
1110 vert_positions[to_v], location, radius, symm);
1114 flood.
execute(ob, vert_to_face_map, [&](
int from_v,
int to_v) {
1115 factors[from_v] = 1.0f;
1116 factors[to_v] = 1.0f;
1131 const float radius = ss.
cache ? ss.
cache->
radius : std::numeric_limits<float>::max();
1144 float3 location = positions[active_vert];
1149 factors[from_v.
to_index(key)] = 1.0f;
1150 factors[to_v.
to_index(key)] = 1.0f;
1152 positions[to_v.
to_index(key)], location, radius, symm);
1158 factors[from_v.
to_index(key)] = 1.0f;
1159 factors[to_v.
to_index(key)] = 1.0f;
1173 const float radius = ss.
cache ? ss.
cache->
radius : std::numeric_limits<float>::max();
1209 if (std::holds_alternative<std::monostate>(ss.
active_vert())) {
1250 for (const int vert : range) {
1251 if (!face_set::vert_has_face_set(vert_to_face_map, face_sets, vert, active_face_set)) {
1252 factors[vert] = 0.0f;
1259 const Mesh &base_mesh = *
static_cast<const Mesh *
>(ob.
data);
1269 const int grid_area = subdiv_ccg.
grid_area;
1271 for (const int face : range) {
1272 if (face_sets[face] != active_face_set) {
1273 factors.slice(bke::ccg::face_range(faces, grid_area, face)).fill(0.0f);
1285 if (face_set_offset == -1) {
1289 for (const int i : range) {
1290 const BMVert *vert = BM_vert_at_index(&const_cast<BMesh &>(bm), i);
1291 if (!face_set::vert_has_face_set(face_set_offset, *vert, active_face_set)) {
1311 const int propagation_steps,
1331 edge_distance[
i] = 0;
1336 edge_distance[
i] = 0;
1343 for (
const int propagation_it :
IndexRange(propagation_steps)) {
1349 for (
const int neighbor :
1352 if (edge_distance[neighbor] == propagation_it) {
1353 edge_distance[
i] = propagation_it + 1;
1364 const float p = 1.0f - (
float(edge_distance[
i]) /
float(propagation_steps));
1365 const float edge_boundary_automask =
pow2f(p);
1367 factors[
i] *= (1.0f - edge_boundary_automask);
1373 const int propagation_steps,
1397 edge_distance[
i] = 0;
1402 faces, corner_verts, vert_to_face_map, face_sets, subdiv_ccg, coord))
1404 edge_distance[
i] = 0;
1411 for (
const int propagation_it :
IndexRange(propagation_steps)) {
1421 const int neighbor_idx = neighbor.
to_index(key);
1422 if (edge_distance[neighbor_idx] == propagation_it) {
1423 edge_distance[
i] = propagation_it + 1;
1434 const float p = 1.0f - (
float(edge_distance[
i]) /
float(propagation_steps));
1435 const float edge_boundary_automask =
pow2f(p);
1437 factors[
i] *= (1.0f - edge_boundary_automask);
1443 const int propagation_steps,
1459 edge_distance[
i] = 0;
1464 edge_distance[
i] = 0;
1470 for (
const int propagation_it :
IndexRange(propagation_steps)) {
1480 if (edge_distance[neighbor_idx] == propagation_it) {
1481 edge_distance[
i] = propagation_it + 1;
1492 const float p = 1.0f - (
float(edge_distance[
i]) /
float(propagation_steps));
1493 const float edge_boundary_automask =
pow2f(p);
1495 factors[
i] *= (1.0f - edge_boundary_automask);
1502 const int propagation_steps,
1570 for (
const int vert : range) {
1571 float f = factors[vert];
1576 depsgraph, automasking, ob, vert, vert_positions[vert]);
1591 for (
const int vert : range) {
1592 float f = factors[vert];
1612 for (const int i : range) {
1613 const BMVert *vert = BM_vert_at_index(&bm, i);
1614 float f = factors[i];
1616 if (int(mode) & BRUSH_AUTOMASKING_VIEW_NORMAL) {
1617 if (int(mode) & BRUSH_AUTOMASKING_VIEW_OCCLUSION) {
1618 f *= calc_view_occlusion_factor(depsgraph, automasking, ob, i, vert->co);
1621 f *= calc_view_normal_factor(automasking, ob, vert->no);
1643 std::unique_ptr<Cache> automasking = std::make_unique<Cache>();
1670 automasking->cavity_factor =
Array<float>(verts_num, -1.0f);
1682 automasking->factor =
Array<float>(verts_num, initial_value);
1757 switch (pbvh.
type()) {
1762 for (
const int vert :
verts) {
1774 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)