Blender V4.3
grab.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 grab_cc {
32
38
40 const float3 &offset,
41 const Span<float3> normals,
42 const MutableSpan<float> factors)
43{
44 BLI_assert(normals.size() == factors.size());
45
46 const float sign = math::sign(math::dot(cache.initial_normal_symm, cache.grab_delta_symm));
47 const float3 test_dir = math::normalize(offset) * sign;
48 for (const int i : factors.index_range()) {
49 factors[i] *= std::max(math::dot(test_dir, normals[i]), 0.0f);
50 }
51}
52
53static void calc_faces(const Depsgraph &depsgraph,
54 const Sculpt &sd,
55 const Brush &brush,
56 const float3 &offset,
57 const MeshAttributeData &attribute_data,
58 const bke::pbvh::MeshNode &node,
59 Object &object,
60 LocalData &tls,
61 const PositionDeformData &position_data)
62{
63 SculptSession &ss = *object.sculpt;
64 const StrokeCache &cache = *ss.cache;
65
66 const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
67 const Span<int> verts = node.verts();
68
70 brush,
71 object,
72 attribute_data,
73 orig_data.positions,
74 orig_data.normals,
75 node,
76 tls.factors,
77 tls.distances);
78
79 if (brush.flag2 & BRUSH_GRAB_SILHOUETTE) {
80 calc_silhouette_factors(cache, offset, orig_data.normals, tls.factors);
81 }
82
83 tls.translations.resize(verts.size());
84 const MutableSpan<float3> translations = tls.translations;
85 translations_from_offset_and_factors(offset, tls.factors, translations);
86
87 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
88 position_data.deform(translations, verts);
89}
90
91static void calc_grids(const Depsgraph &depsgraph,
92 const Sculpt &sd,
93 Object &object,
94 const Brush &brush,
95 const float3 &offset,
97 LocalData &tls)
98{
99 SculptSession &ss = *object.sculpt;
100 const StrokeCache &cache = *ss.cache;
101 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
102 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
103
104 const OrigPositionData orig_data = orig_position_data_get_grids(object, node);
105 const Span<int> grids = node.grids();
106 const int grid_verts_num = grids.size() * key.grid_area;
107
109 brush,
110 object,
111 orig_data.positions,
112 orig_data.normals,
113 node,
114 tls.factors,
115 tls.distances);
116
117 if (brush.flag2 & BRUSH_GRAB_SILHOUETTE) {
118 calc_silhouette_factors(cache, offset, orig_data.normals, tls.factors);
119 }
120
121 tls.translations.resize(grid_verts_num);
122 const MutableSpan<float3> translations = tls.translations;
123 translations_from_offset_and_factors(offset, tls.factors, translations);
124
125 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
126 apply_translations(translations, grids, subdiv_ccg);
127}
128
129static void calc_bmesh(const Depsgraph &depsgraph,
130 const Sculpt &sd,
131 Object &object,
132 const Brush &brush,
133 const float3 &offset,
135 LocalData &tls)
136{
137 SculptSession &ss = *object.sculpt;
138 const StrokeCache &cache = *ss.cache;
139
141
142 Array<float3> orig_positions(verts.size());
143 Array<float3> orig_normals(verts.size());
144 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
145
147 depsgraph, brush, object, orig_positions, orig_normals, node, tls.factors, tls.distances);
148
149 if (brush.flag2 & BRUSH_GRAB_SILHOUETTE) {
150 calc_silhouette_factors(cache, offset, orig_normals, tls.factors);
151 }
152
153 tls.translations.resize(verts.size());
154 const MutableSpan<float3> translations = tls.translations;
155 translations_from_offset_and_factors(offset, tls.factors, translations);
156
157 clip_and_lock_translations(sd, ss, orig_positions, translations);
158 apply_translations(translations, verts);
159}
160
161} // namespace grab_cc
162
163void do_grab_brush(const Depsgraph &depsgraph,
164 const Sculpt &sd,
165 Object &object,
166 const IndexMask &node_mask)
167{
168 const SculptSession &ss = *object.sculpt;
169 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
170 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
171
172 float3 grab_delta = ss.cache->grab_delta_symm;
173
174 if (ss.cache->normal_weight > 0.0f) {
176 }
177
178 grab_delta *= ss.cache->bstrength;
179
181 switch (pbvh.type()) {
183 const Mesh &mesh = *static_cast<Mesh *>(object.data);
184 const MeshAttributeData attribute_data(mesh.attributes());
185 const PositionDeformData position_data(depsgraph, object);
187 node_mask.foreach_index(GrainSize(1), [&](const int i) {
188 LocalData &tls = all_tls.local();
190 sd,
191 brush,
192 grab_delta,
193 attribute_data,
194 nodes[i],
195 object,
196 tls,
197 position_data);
198 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
199 });
200 break;
201 }
203 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
204 MutableSpan<float3> positions = subdiv_ccg.positions;
206 node_mask.foreach_index(GrainSize(1), [&](const int i) {
207 LocalData &tls = all_tls.local();
208 calc_grids(depsgraph, sd, object, brush, grab_delta, nodes[i], tls);
209 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
210 });
211 break;
212 }
215 node_mask.foreach_index(GrainSize(1), [&](const int i) {
216 LocalData &tls = all_tls.local();
217 calc_bmesh(depsgraph, sd, object, brush, grab_delta, nodes[i], tls);
219 });
220 break;
221 }
222 }
223 pbvh.tag_positions_changed(node_mask);
225}
226
228 Object &object,
229 SculptSession &ss,
230 float radius)
231{
232 ss.preview_verts = {};
233
234 /* This function is called from the cursor drawing code, so the tree may not be built yet. */
235 const bke::pbvh::Tree *pbvh = bke::object::pbvh_get(object);
236 if (!pbvh) {
237 return;
238 }
239
240 if (!ss.deform_modifiers_active) {
241 return;
242 }
243
244 if (pbvh->type() != bke::pbvh::Type::Mesh) {
245 return;
246 }
247
249
250 const Mesh &mesh = *static_cast<const Mesh *>(object.data);
251 /* Always grab active shape key if the sculpt happens on shapekey. */
252 const Span<float3> positions = ss.shapekey_active ?
254 mesh.vert_positions();
255 const OffsetIndices faces = mesh.faces();
256 const Span<int> corner_verts = mesh.corner_verts();
257 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
258 const bke::AttributeAccessor attributes = mesh.attributes();
259 const VArraySpan<bool> hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
260
261 const int active_vert = std::get<int>(ss.active_vert());
262 const float3 brush_co = positions[active_vert];
263 const float radius_sq = radius * radius;
264
265 Vector<int> preview_verts;
266 Vector<int> neighbors;
267 BitVector<> visited_verts(positions.size());
268 std::queue<int> queue;
269 queue.push(active_vert);
270 while (!queue.empty()) {
271 const int from_vert = queue.front();
272 queue.pop();
273
274 neighbors.clear();
275 for (const int neighbor : vert_neighbors_get_mesh(
276 faces, corner_verts, vert_to_face_map, hide_poly, from_vert, neighbors))
277 {
278 preview_verts.append(from_vert);
279 preview_verts.append(neighbor);
280 if (visited_verts[neighbor]) {
281 continue;
282 }
283 visited_verts[neighbor].set();
284 if (math::distance_squared(brush_co, positions[neighbor]) < radius_sq) {
285 queue.push(neighbor);
286 }
287 }
288 }
289
290 ss.preview_verts = preview_verts.as_span();
291}
292
293} // namespace blender::ed::sculpt_paint
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:654
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
Definition paint.cc:2601
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)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_NOINLINE
@ BRUSH_GRAB_SILHOUETTE
Object is a sort of wrapper for general info.
constexpr int64_t size() const
Definition BLI_span.hh:494
constexpr IndexRange index_range() const
Definition BLI_span.hh:671
constexpr int64_t size() const
Definition BLI_span.hh:253
void append(const T &value)
Span< T > as_span() const
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
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2482
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 void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float3 &offset, bke::pbvh::GridsNode &node, LocalData &tls)
Definition grab.cc:91
static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float3 &offset, bke::pbvh::BMeshNode &node, LocalData &tls)
Definition grab.cc:129
static BLI_NOINLINE void calc_silhouette_factors(const StrokeCache &cache, const float3 &offset, const Span< float3 > normals, const MutableSpan< float > factors)
Definition grab.cc:39
static void calc_faces(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const float3 &offset, const MeshAttributeData &attribute_data, const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const PositionDeformData &position_data)
Definition grab.cc:53
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 orig_position_data_gather_bmesh(const BMLog &bm_log, const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions, MutableSpan< float3 > normals)
void do_grab_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition grab.cc:163
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)
OrigPositionData orig_position_data_get_grids(const Object &object, const bke::pbvh::GridsNode &node)
void translations_from_offset_and_factors(const float3 &offset, Span< float > factors, MutableSpan< float3 > r_translations)
Definition sculpt.cc:7246
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_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
void geometry_preview_lines_update(Depsgraph &depsgraph, Object &object, SculptSession &ss, float radius)
Definition grab.cc:227
T sign(const T &a)
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
void sculpt_project_v3_normal_align(const SculptSession &ss, const float normal_weight, float grab_delta[3])
Definition sculpt.cc:538
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
KeyBlock * shapekey_active
Definition BKE_paint.hh:387
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
blender::Array< int > preview_verts
Definition BKE_paint.hh:450
ActiveVert active_vert() const
Definition paint.cc:2180
bool deform_modifiers_active
Definition BKE_paint.hh:411
blender::Array< blender::float3 > positions