Blender V4.3
topology_slide.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_key.hh"
13#include "BKE_mesh.hh"
14#include "BKE_paint.hh"
15#include "BKE_pbvh.hh"
16#include "BKE_subdiv_ccg.hh"
17
18#include "BLI_array.hh"
20#include "BLI_math_matrix.hh"
21#include "BLI_math_vector.hh"
22#include "BLI_task.h"
23#include "BLI_task.hh"
24
28
30
31inline namespace topology_slide_cc {
32
40
42 const StrokeCache &cache,
43 const Span<float3> positions,
44 const MutableSpan<float3> r_translations)
45{
46
47 switch (brush.slide_deform_type) {
49 r_translations.fill(math::normalize(cache.location_symm - cache.last_location_symm));
50 break;
52 for (const int i : positions.index_range()) {
53 r_translations[i] = math::normalize(cache.location_symm - positions[i]);
54 }
55 break;
57 for (const int i : positions.index_range()) {
58 r_translations[i] = math::normalize(positions[i] - cache.location_symm);
59 }
60 break;
61 }
62}
63
64static inline void add_neighbor_influence(const float3 &position,
65 const float3 &dir,
66 const float3 &neighbor_position,
67 float3 &translation)
68{
69 const float3 neighbor_disp = neighbor_position - position;
70 const float3 neighbor_dir = math::normalize(neighbor_disp);
71 if (math::dot(dir, neighbor_dir) > 0.0f) {
72 translation += neighbor_dir * math::dot(dir, neighbor_disp);
73 }
74}
75
76BLI_NOINLINE static void calc_neighbor_influence(const Span<float3> vert_positions,
77 const Span<float3> positions,
78 const Span<Vector<int>> vert_neighbors,
79 const MutableSpan<float3> translations)
80{
81 for (const int i : positions.index_range()) {
82 const float3 &position = positions[i];
83 const float3 &dir = translations[i];
84
85 float3 final_translation(0);
86 for (const int neighbor : vert_neighbors[i]) {
87 add_neighbor_influence(position, dir, vert_positions[neighbor], final_translation);
88 }
89
90 translations[i] = final_translation;
91 }
92}
93
94BLI_NOINLINE static void calc_neighbor_influence(const SubdivCCG &subdiv_ccg,
95 const Span<int> grids,
96 const MutableSpan<float3> translations)
97{
98 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
99 const Span<float3> positions = subdiv_ccg.positions;
100 for (const int i : grids.index_range()) {
101 const int node_start = i * key.grid_area;
102 const int grid = grids[i];
103 const int start = grid * key.grid_area;
104 for (const int y : IndexRange(key.grid_size)) {
105 for (const int x : IndexRange(key.grid_size)) {
106 const int offset = CCG_grid_xy_to_index(key.grid_size, x, y);
107 const int vert = start + offset;
108 const int node_vert = node_start + offset;
109
110 const float3 &position = positions[vert];
111 const float3 &dir = translations[node_vert];
112
113 SubdivCCGCoord coord{};
114 coord.grid_index = grid;
115 coord.x = x;
116 coord.y = y;
117
118 SubdivCCGNeighbors neighbors;
119 BKE_subdiv_ccg_neighbor_coords_get(subdiv_ccg, coord, false, neighbors);
120
121 float3 final_translation(0);
122 for (const SubdivCCGCoord neighbor : neighbors.coords) {
124 position, dir, positions[neighbor.to_index(key)], final_translation);
125 }
126
127 translations[node_vert] = final_translation;
128 }
129 }
130 }
131}
132
134 const Set<BMVert *, 0> &verts,
135 const MutableSpan<float3> translations)
136{
137 Vector<BMVert *, 64> neighbors;
138 int i = 0;
139 for (BMVert *vert : verts) {
140 const float3 &position = positions[i];
141 const float3 &dir = translations[i];
142
143 float3 final_translation(0);
144 for (BMVert *neighbor : vert_neighbors_get_bmesh(*vert, neighbors)) {
145 add_neighbor_influence(position, dir, neighbor->co, final_translation);
146 }
147
148 translations[i] = final_translation;
149 i++;
150 }
151}
152
153static void calc_faces(const Depsgraph &depsgraph,
154 const Sculpt &sd,
155 const Brush &brush,
156 const OffsetIndices<int> faces,
157 const Span<int> corner_verts,
158 const GroupedSpan<int> vert_to_face_map,
159 const MeshAttributeData &attribute_data,
160 const bke::pbvh::MeshNode &node,
161 Object &object,
162 LocalData &tls,
163 const PositionDeformData &position_data)
164{
165 SculptSession &ss = *object.sculpt;
166 const StrokeCache &cache = *ss.cache;
167
168 const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
169 const Span<int> verts = node.verts();
170 const MutableSpan positions = gather_data_mesh(position_data.eval, verts, tls.positions);
171
173 brush,
174 object,
175 attribute_data,
176 orig_data.positions,
177 orig_data.normals,
178 node,
179 tls.factors,
180 tls.distances);
181
182 scale_factors(tls.factors, cache.bstrength);
183
184 tls.vert_neighbors.resize(verts.size());
186 faces, corner_verts, vert_to_face_map, attribute_data.hide_poly, verts, tls.vert_neighbors);
187 const Span<Vector<int>> vert_neighbors = tls.vert_neighbors;
188
189 tls.translations.resize(verts.size());
190 const MutableSpan<float3> translations = tls.translations;
191 calc_translation_directions(brush, cache, positions, translations);
192 calc_neighbor_influence(position_data.eval, positions, vert_neighbors, translations);
193 scale_translations(translations, tls.factors);
194
195 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
196 position_data.deform(translations, verts);
197}
198
199static void calc_grids(const Depsgraph &depsgraph,
200 const Sculpt &sd,
201 Object &object,
202 const Brush &brush,
203 const bke::pbvh::GridsNode &node,
204 LocalData &tls)
205{
206 SculptSession &ss = *object.sculpt;
207 const StrokeCache &cache = *ss.cache;
208 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
209
210 const OrigPositionData orig_data = orig_position_data_get_grids(object, node);
211 const Span<int> grids = node.grids();
212 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
213
215 brush,
216 object,
217 orig_data.positions,
218 orig_data.normals,
219 node,
220 tls.factors,
221 tls.distances);
222
223 scale_factors(tls.factors, cache.bstrength);
224
225 tls.translations.resize(positions.size());
226 const MutableSpan<float3> translations = tls.translations;
227 calc_translation_directions(brush, cache, positions, translations);
228 calc_neighbor_influence(subdiv_ccg, grids, translations);
229 scale_translations(translations, tls.factors);
230
231 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
232 apply_translations(translations, grids, subdiv_ccg);
233}
234
235static void calc_bmesh(const Depsgraph &depsgraph,
236 const Sculpt &sd,
237 Object &object,
238 const Brush &brush,
240 LocalData &tls)
241{
242 SculptSession &ss = *object.sculpt;
243 const StrokeCache &cache = *ss.cache;
244
246 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
247
248 Array<float3> orig_positions(verts.size());
249 Array<float3> orig_normals(verts.size());
250 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
251
253 depsgraph, brush, object, orig_positions, orig_normals, node, tls.factors, tls.distances);
254
255 scale_factors(tls.factors, cache.bstrength);
256
257 tls.translations.resize(verts.size());
258 const MutableSpan<float3> translations = tls.translations;
259 calc_translation_directions(brush, cache, positions, translations);
260 calc_neighbor_influence(positions, verts, translations);
261 scale_translations(translations, tls.factors);
262
263 clip_and_lock_translations(sd, ss, orig_positions, translations);
264 apply_translations(translations, verts);
265}
266
267} // namespace topology_slide_cc
268
269void do_topology_slide_brush(const Depsgraph &depsgraph,
270 const Sculpt &sd,
271 Object &object,
272 const IndexMask &node_mask)
273{
274 const SculptSession &ss = *object.sculpt;
275 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
276 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
277
279 return;
280 }
281
283 switch (pbvh.type()) {
285 Mesh &mesh = *static_cast<Mesh *>(object.data);
286 const PositionDeformData position_data(depsgraph, object);
287 const OffsetIndices faces = mesh.faces();
288 const Span<int> corner_verts = mesh.corner_verts();
289 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
290 const MeshAttributeData attribute_data(mesh.attributes());
292 node_mask.foreach_index(GrainSize(1), [&](const int i) {
293 LocalData &tls = all_tls.local();
295 sd,
296 brush,
297 faces,
298 corner_verts,
299 vert_to_face_map,
300 attribute_data,
301 nodes[i],
302 object,
303 tls,
304 position_data);
305 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
306 });
307 break;
308 }
310 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
311 MutableSpan<float3> positions = subdiv_ccg.positions;
313 node_mask.foreach_index(GrainSize(1), [&](const int i) {
314 LocalData &tls = all_tls.local();
315 calc_grids(depsgraph, sd, object, brush, nodes[i], tls);
316 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
317 });
318 break;
319 }
322 node_mask.foreach_index(GrainSize(1), [&](const int i) {
323 LocalData &tls = all_tls.local();
324 calc_bmesh(depsgraph, sd, object, brush, nodes[i], tls);
326 });
327 break;
328 }
329 }
330 pbvh.tag_positions_changed(node_mask);
332}
333
334} // 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
const blender::Set< BMVert *, 0 > & BKE_pbvh_bmesh_node_unique_verts(blender::bke::pbvh::BMeshNode *node)
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_SLIDE_DEFORM_DRAG
@ BRUSH_SLIDE_DEFORM_EXPAND
@ BRUSH_SLIDE_DEFORM_PINCH
Object is a sort of wrapper for general info.
constexpr void fill(const T &value) const
Definition BLI_span.hh:518
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 deform(MutableSpan< float3 > translations, Span< int > verts) const
Definition sculpt.cc:7139
void foreach_index(Fn &&fn) const
const Depsgraph * depsgraph
static float verts[][3]
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2846
void update_node_bounds_bmesh(BMeshNode &node)
Definition pbvh.cc:1095
void update_node_bounds_mesh(Span< float3 > positions, MeshNode &node)
Definition pbvh.cc:1075
void update_node_bounds_grids(int grid_area, Span< float3 > positions, GridsNode &node)
Definition pbvh.cc:1084
void flush_bounds_to_parents(Tree &pbvh)
Definition pbvh.cc:1132
static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float3 &direction, const float strength, bke::pbvh::BMeshNode &node, LocalData &tls)
static void calc_faces(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const float4 &test_plane, const float strength, const MeshAttributeData &attribute_data, const Span< float3 > vert_normals, const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const PositionDeformData &position_data)
Definition clay.cc:58
static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float4 &test_plane, const float strength, bke::pbvh::GridsNode &node, LocalData &tls)
Definition clay.cc:95
static BLI_NOINLINE void calc_translation_directions(const Brush &brush, const StrokeCache &cache, const Span< float3 > positions, const MutableSpan< float3 > r_translations)
static void calc_faces(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const OffsetIndices< int > faces, const Span< int > corner_verts, const GroupedSpan< int > vert_to_face_map, const MeshAttributeData &attribute_data, const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const PositionDeformData &position_data)
static void add_neighbor_influence(const float3 &position, const float3 &dir, const float3 &neighbor_position, float3 &translation)
static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, bke::pbvh::BMeshNode &node, LocalData &tls)
static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const bke::pbvh::GridsNode &node, LocalData &tls)
static BLI_NOINLINE void calc_neighbor_influence(const Span< float3 > vert_positions, const Span< float3 > positions, const Span< Vector< int > > vert_neighbors, const MutableSpan< float3 > translations)
MutableSpan< float3 > gather_grids_positions(const SubdivCCG &subdiv_ccg, const Span< int > grids, Vector< float3 > &positions)
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
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6054
void orig_position_data_gather_bmesh(const BMLog &bm_log, const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions, MutableSpan< float3 > normals)
void scale_translations(MutableSpan< float3 > translations, Span< float > factors)
Definition sculpt.cc:7210
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
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7022
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6958
OrigPositionData orig_position_data_get_mesh(const Object &object, const bke::pbvh::MeshNode &node)
Span< BMVert * > vert_neighbors_get_bmesh(BMVert &vert, Vector< BMVert *, 64 > &r_neighbors)
Definition sculpt.cc:389
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
OrigPositionData orig_position_data_get_grids(const Object &object, const bke::pbvh::GridsNode &node)
void do_topology_slide_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
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
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
bool SCULPT_stroke_is_first_brush_step_of_symmetry_pass(const blender::ed::sculpt_paint::StrokeCache &cache)
Definition sculpt.cc:513
int slide_deform_type
int grid_size
Definition BKE_ccg.hh:33
int grid_area
Definition BKE_ccg.hh:35
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:427
BMLog * bm_log
Definition BKE_paint.hh:402
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
blender::Vector< SubdivCCGCoord, 256 > coords
blender::Array< blender::float3 > positions