Blender V4.3
multires_displacement_smear.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "DNA_brush_types.h"
8#include "DNA_mesh_types.h"
9#include "DNA_object_types.h"
10#include "DNA_scene_types.h"
11
12#include "BKE_paint.hh"
13#include "BKE_pbvh.hh"
14#include "BKE_subdiv_ccg.hh"
15
17#include "BLI_math_matrix.hh"
18#include "BLI_math_vector.h"
19#include "BLI_math_vector.hh"
20#include "BLI_task.h"
21#include "BLI_task.hh"
22
26
28
29inline namespace multires_displacement_smear_cc {
30
36
37static void calc_node(const Depsgraph &depsgraph,
38 Object &object,
39 const Brush &brush,
40 const float strength,
41 const bke::pbvh::GridsNode &node,
42 LocalData &tls)
43{
44 SculptSession &ss = *object.sculpt;
45 const StrokeCache &cache = *ss.cache;
46 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
47 MutableSpan<float3> ccg_positions = subdiv_ccg.positions;
48 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
49
50 const Span<int> grids = node.grids();
51 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
52
53 calc_factors_common_grids(depsgraph, brush, object, positions, node, tls.factors, tls.distances);
54
55 scale_factors(tls.factors, strength);
56
57 for (const int i : grids.index_range()) {
58 const IndexRange node_grid_range = bke::ccg::grid_range(key.grid_area, i);
59 const IndexRange grid_range = bke::ccg::grid_range(key.grid_area, grids[i]);
60 const int grid = grids[i];
61 for (const int y : IndexRange(key.grid_size)) {
62 for (const int x : IndexRange(key.grid_size)) {
63 const int offset = CCG_grid_xy_to_index(key.grid_size, x, y);
64 const int node_vert = node_grid_range[offset];
65 const int vert = grid_range[offset];
66
67 float3 interp_limit_surface_disp = cache.displacement_smear.prev_displacement[vert];
68
69 float3 current_disp;
70 switch (brush.smear_deform_type) {
72 current_disp = cache.location_symm - cache.last_location_symm;
73 break;
75 current_disp = cache.location_symm - ccg_positions[vert];
76 break;
78 current_disp = ccg_positions[vert] - cache.location_symm;
79 break;
80 }
81
82 const float3 current_disp_norm = math::normalize(current_disp);
83 current_disp *= cache.bstrength;
84
85 float weights_accum = 1.0f;
86
87 SubdivCCGCoord coord{};
88 coord.grid_index = grid;
89 coord.x = x;
90 coord.y = y;
91
92 SubdivCCGNeighbors neighbors;
93 BKE_subdiv_ccg_neighbor_coords_get(*ss.subdiv_ccg, coord, false, neighbors);
94
95 for (const SubdivCCGCoord neighbor : neighbors.coords) {
96 const int neighbor_index = neighbor.to_index(key);
97 const float3 vert_disp = cache.displacement_smear.limit_surface_co[neighbor_index] -
99 const float3 &neighbor_limit_surface_disp =
100 cache.displacement_smear.prev_displacement[neighbor_index];
101 const float3 vert_disp_norm = math::normalize(vert_disp);
102
103 if (math::dot(current_disp_norm, vert_disp_norm) >= 0.0f) {
104 continue;
105 }
106
107 const float disp_interp = std::clamp(
108 -math::dot(current_disp_norm, vert_disp_norm), 0.0f, 1.0f);
109 interp_limit_surface_disp += neighbor_limit_surface_disp * disp_interp;
110 weights_accum += disp_interp;
111 }
112
113 interp_limit_surface_disp *= math::rcp(weights_accum);
114
115 float3 new_co = cache.displacement_smear.limit_surface_co[vert] +
116 interp_limit_surface_disp;
117 ccg_positions[vert] = math::interpolate(
118 ccg_positions[vert], new_co, tls.factors[node_vert]);
119 }
120 }
121 }
122}
123
124BLI_NOINLINE static void eval_all_limit_positions(const SubdivCCG &subdiv_ccg,
125 const MutableSpan<float3> limit_positions)
126{
127 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
128 threading::parallel_for(IndexRange(subdiv_ccg.grids_num), 1024, [&](const IndexRange range) {
129 for (const int grid : range) {
130 const MutableSpan grid_limit_positions = limit_positions.slice(
131 bke::ccg::grid_range(key.grid_area, grid));
132 BKE_subdiv_ccg_eval_limit_positions(subdiv_ccg, key, grid, grid_limit_positions);
133 }
134 });
135}
136
138 const Span<float3> positions,
139 const CCGKey &key,
140 const bke::pbvh::GridsNode &node,
141 const MutableSpan<float3> prev_displacement)
142{
143 for (const int grid : node.grids()) {
144 for (const int i : bke::ccg::grid_range(key.grid_area, grid)) {
145 prev_displacement[i] = positions[i] - limit_positions[i];
146 }
147 }
148}
149
150} // namespace multires_displacement_smear_cc
151
153 const Sculpt &sd,
154 Object &ob,
155 const IndexMask &node_mask)
156{
157 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
158 SculptSession &ss = *ob.sculpt;
159 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
161
162 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
163 MutableSpan<float3> positions = subdiv_ccg.positions;
164 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
165
169
171 }
172
173 node_mask.foreach_index(GrainSize(1), [&](const int i) {
175 subdiv_ccg.positions,
176 key,
177 nodes[i],
179 });
180
181 const float strength = std::clamp(ss.cache->bstrength, 0.0f, 1.0f);
182
184 node_mask.foreach_index(GrainSize(1), [&](const int i) {
185 LocalData &tls = all_tls.local();
186 calc_node(depsgraph, ob, brush, strength, nodes[i], tls);
187 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
188 });
189 pbvh.tag_positions_changed(node_mask);
190 bke::pbvh::flush_bounds_to_parents(pbvh);
191}
192
193} // namespace blender::ed::sculpt_paint
int CCG_grid_xy_to_index(const int grid_size, const int x, const int y)
Definition BKE_ccg.hh:77
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:654
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)
#define BLI_NOINLINE
@ BRUSH_SMEAR_DEFORM_PINCH
@ BRUSH_SMEAR_DEFORM_EXPAND
@ BRUSH_SMEAR_DEFORM_DRAG
Object is a sort of wrapper for general info.
bool is_empty() const
Definition BLI_array.hh:253
constexpr IndexRange index_range() const
Definition BLI_span.hh:402
void tag_positions_changed(const IndexMask &node_mask)
Definition pbvh.cc:549
Span< NodeT > nodes() const
void foreach_index(Fn &&fn) const
const Depsgraph * depsgraph
IndexRange grid_range(const int grid_area, const int grid)
static void calc_node(const Depsgraph &depsgraph, Object &object, const Brush &brush, const float strength, const bke::pbvh::GridsNode &node, LocalData &tls)
static BLI_NOINLINE void store_node_prev_displacement(const Span< float3 > limit_positions, const Span< float3 > positions, const CCGKey &key, const bke::pbvh::GridsNode &node, const MutableSpan< float3 > prev_displacement)
static BLI_NOINLINE void eval_all_limit_positions(const SubdivCCG &subdiv_ccg, const MutableSpan< float3 > limit_positions)
MutableSpan< float3 > gather_grids_positions(const SubdivCCG &subdiv_ccg, const Span< int > grids, Vector< float3 > &positions)
void do_displacement_smear_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const IndexMask &node_mask)
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 scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7227
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
T interpolate(const T &a, const T &b, const FactorT &t)
T rcp(const T &a)
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))
Definition BLI_task.hh:95
int smear_deform_type
int grid_size
Definition BKE_ccg.hh:33
int grid_area
Definition BKE_ccg.hh:35
struct SculptSession * sculpt
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:427
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
blender::Vector< SubdivCCGCoord, 256 > coords
blender::Array< blender::float3 > positions
struct blender::ed::sculpt_paint::StrokeCache::@479 displacement_smear