Blender V5.0
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
5#include <queue>
6
8
9#include "DNA_brush_types.h"
10#include "DNA_mesh_types.h"
11#include "DNA_object_types.h"
12#include "DNA_scene_types.h"
13
14#include "BKE_attribute.hh"
15#include "BKE_mesh.hh"
16#include "BKE_paint.hh"
17#include "BKE_paint_bvh.hh"
18#include "BKE_subdiv_ccg.hh"
19
20#include "BLI_array.hh"
22#include "BLI_math_vector.hh"
23#include "BLI_task.hh"
24
28
29#include "bmesh.hh"
30
32inline namespace grab_cc {
33
39
41 const float3 &offset,
43 const MutableSpan<float> factors)
44{
45 BLI_assert(normals.size() == factors.size());
46
47 const float sign = math::sign(math::dot(cache.initial_normal_symm, cache.grab_delta_symm));
48 const float3 test_dir = math::normalize(offset) * sign;
49 for (const int i : factors.index_range()) {
50 factors[i] *= std::max(math::dot(test_dir, normals[i]), 0.0f);
51 }
52}
53
54static void calc_faces(const Depsgraph &depsgraph,
55 const Sculpt &sd,
56 const Brush &brush,
57 const float3 &offset,
58 const MeshAttributeData &attribute_data,
59 const bke::pbvh::MeshNode &node,
60 Object &object,
61 LocalData &tls,
62 const PositionDeformData &position_data)
63{
64 SculptSession &ss = *object.sculpt;
65 const StrokeCache &cache = *ss.cache;
66
67 const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
68 const Span<int> verts = node.verts();
69
71 brush,
72 object,
73 attribute_data,
74 orig_data.positions,
75 orig_data.normals,
76 node,
77 tls.factors,
78 tls.distances);
79
80 if (brush.flag2 & BRUSH_GRAB_SILHOUETTE) {
81 calc_silhouette_factors(cache, offset, orig_data.normals, tls.factors);
82 }
83
84 tls.translations.resize(verts.size());
85 const MutableSpan<float3> translations = tls.translations;
86 translations_from_offset_and_factors(offset, tls.factors, translations);
87
88 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
89 position_data.deform(translations, verts);
90}
91
92static void calc_grids(const Depsgraph &depsgraph,
93 const Sculpt &sd,
94 Object &object,
95 const Brush &brush,
96 const float3 &offset,
98 LocalData &tls)
99{
100 SculptSession &ss = *object.sculpt;
101 const StrokeCache &cache = *ss.cache;
102 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
103 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
104
105 const OrigPositionData orig_data = orig_position_data_get_grids(object, node);
106 const Span<int> grids = node.grids();
107 const int grid_verts_num = grids.size() * key.grid_area;
108
110 brush,
111 object,
112 orig_data.positions,
113 orig_data.normals,
114 node,
115 tls.factors,
116 tls.distances);
117
118 if (brush.flag2 & BRUSH_GRAB_SILHOUETTE) {
119 calc_silhouette_factors(cache, offset, orig_data.normals, tls.factors);
120 }
121
122 tls.translations.resize(grid_verts_num);
123 const MutableSpan<float3> translations = tls.translations;
124 translations_from_offset_and_factors(offset, tls.factors, translations);
125
126 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
127 apply_translations(translations, grids, subdiv_ccg);
128}
129
130static void calc_bmesh(const Depsgraph &depsgraph,
131 const Sculpt &sd,
132 Object &object,
133 const Brush &brush,
134 const float3 &offset,
136 LocalData &tls)
137{
138 SculptSession &ss = *object.sculpt;
139 const StrokeCache &cache = *ss.cache;
140
142
143 Array<float3> orig_positions(verts.size());
144 Array<float3> orig_normals(verts.size());
145 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
146
148 depsgraph, brush, object, orig_positions, orig_normals, node, tls.factors, tls.distances);
149
150 if (brush.flag2 & BRUSH_GRAB_SILHOUETTE) {
151 calc_silhouette_factors(cache, offset, orig_normals, tls.factors);
152 }
153
154 tls.translations.resize(verts.size());
155 const MutableSpan<float3> translations = tls.translations;
156 translations_from_offset_and_factors(offset, tls.factors, translations);
157
158 clip_and_lock_translations(sd, ss, orig_positions, translations);
159 apply_translations(translations, verts);
160}
161
162} // namespace grab_cc
163
164void do_grab_brush(const Depsgraph &depsgraph,
165 const Sculpt &sd,
166 Object &object,
167 const IndexMask &node_mask)
168{
169 const SculptSession &ss = *object.sculpt;
170 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
171 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
172
173 float3 grab_delta = ss.cache->grab_delta_symm;
174
175 if (ss.cache->normal_weight > 0.0f) {
177 }
178
179 grab_delta *= ss.cache->bstrength;
180
182 switch (pbvh.type()) {
184 const Mesh &mesh = *static_cast<Mesh *>(object.data);
185 const MeshAttributeData attribute_data(mesh);
186 const PositionDeformData position_data(depsgraph, object);
188 node_mask.foreach_index(GrainSize(1), [&](const int i) {
189 LocalData &tls = all_tls.local();
191 sd,
192 brush,
193 grab_delta,
194 attribute_data,
195 nodes[i],
196 object,
197 tls,
198 position_data);
199 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
200 });
201 break;
202 }
204 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
205 MutableSpan<float3> positions = subdiv_ccg.positions;
207 node_mask.foreach_index(GrainSize(1), [&](const int i) {
208 LocalData &tls = all_tls.local();
209 calc_grids(depsgraph, sd, object, brush, grab_delta, nodes[i], tls);
210 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
211 });
212 break;
213 }
216 node_mask.foreach_index(GrainSize(1), [&](const int i) {
217 LocalData &tls = all_tls.local();
218 calc_bmesh(depsgraph, sd, object, brush, grab_delta, nodes[i], tls);
220 });
221 break;
222 }
223 }
224 pbvh.tag_positions_changed(node_mask);
226}
227} // namespace blender::ed::sculpt_paint::brushes
228
230
232 Object &object,
233 SculptSession &ss,
234 float radius)
235{
236 ss.preview_verts = {};
237
238 /* This function is called from the cursor drawing code, so the tree may not be built yet. */
239 const bke::pbvh::Tree *pbvh = bke::object::pbvh_get(object);
240 if (!pbvh) {
241 return;
242 }
243
244 if (!ss.deform_modifiers_active) {
245 return;
246 }
247
248 if (pbvh->type() != bke::pbvh::Type::Mesh) {
249 return;
250 }
251
253
254 const Mesh &mesh = *static_cast<const Mesh *>(object.data);
255 /* Always grab active shape key if the sculpt happens on shapekey. */
256 const Span<float3> positions = ss.shapekey_active ?
258 mesh.vert_positions();
259 const OffsetIndices faces = mesh.faces();
260 const Span<int> corner_verts = mesh.corner_verts();
261 const GroupedSpan<int> vert_to_face_map = mesh.vert_to_face_map();
262 const bke::AttributeAccessor attributes = mesh.attributes();
263 const VArraySpan<bool> hide_poly = *attributes.lookup<bool>(".hide_poly", bke::AttrDomain::Face);
264
265 const int active_vert = std::get<int>(ss.active_vert());
266 const float3 brush_co = positions[active_vert];
267 const float radius_sq = radius * radius;
268
269 Vector<int> preview_verts;
270 Vector<int> neighbors;
271 BitVector<> visited_verts(positions.size());
272 std::queue<int> queue;
273 queue.push(active_vert);
274 while (!queue.empty()) {
275 const int from_vert = queue.front();
276 queue.pop();
277
278 neighbors.clear();
279 for (const int neighbor : vert_neighbors_get_mesh(
280 faces, corner_verts, vert_to_face_map, hide_poly, from_vert, neighbors))
281 {
282 preview_verts.append(from_vert);
283 preview_verts.append(neighbor);
284 if (visited_verts[neighbor]) {
285 continue;
286 }
287 visited_verts[neighbor].set();
288 if (math::distance_squared(brush_co, positions[neighbor]) < radius_sq) {
289 queue.push(neighbor);
290 }
291 }
292 }
293
294 ss.preview_verts = preview_verts.as_span();
295}
296
297} // namespace blender::ed::sculpt_paint
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:650
void BKE_sculpt_update_object_for_edit(Depsgraph *depsgraph, Object *ob_orig, bool is_paint_tool)
Definition paint.cc:2797
A BVH for high poly meshes.
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:46
#define BLI_NOINLINE
@ BRUSH_GRAB_SILHOUETTE
Object is a sort of wrapper for general info.
BPy_StructRNA * depsgraph
constexpr int64_t size() const
Definition BLI_span.hh:493
constexpr IndexRange index_range() const
Definition BLI_span.hh:670
constexpr int64_t size() const
Definition BLI_span.hh:252
void append(const T &value)
Span< T > as_span() const
GAttributeReader lookup(const StringRef attribute_id) const
void tag_positions_changed(const IndexMask &node_mask)
Definition pbvh.cc:635
Span< NodeT > nodes() const
void flush_bounds_to_parents()
Definition pbvh.cc:1306
void foreach_index(Fn &&fn) const
static float verts[][3]
static float normals[][3]
constexpr T sign(T) RET
static char faces[256]
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
void update_node_bounds_bmesh(BMeshNode &node)
Definition pbvh.cc:1294
void update_node_bounds_mesh(Span< float3 > positions, MeshNode &node)
Definition pbvh.cc:1274
void update_node_bounds_grids(int grid_area, Span< float3 > positions, GridsNode &node)
Definition pbvh.cc:1283
Span< float3 > vert_positions_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:1040
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:56
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:93
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:54
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:92
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:130
static BLI_NOINLINE void calc_silhouette_factors(const StrokeCache &cache, const float3 &offset, const Span< float3 > normals, const MutableSpan< float > factors)
Definition grab.cc:40
void do_grab_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const IndexMask &node_mask)
Definition grab.cc:164
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:6706
void orig_position_data_gather_bmesh(const BMLog &bm_log, const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions, MutableSpan< float3 > normals)
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:6670
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7335
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:7268
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:7531
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:429
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:6741
void geometry_preview_lines_update(Depsgraph &depsgraph, Object &object, SculptSession &ss, float radius)
Definition grab.cc:231
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)
VecBase< float, 3 > float3
void sculpt_project_v3_normal_align(const SculptSession &ss, const float normal_weight, float grab_delta[3])
Definition sculpt.cc:567
int grid_area
Definition BKE_ccg.hh:35
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:417
BMLog * bm_log
Definition BKE_paint.hh:392
KeyBlock * shapekey_active
Definition BKE_paint.hh:377
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:395
blender::Array< int > preview_verts
Definition BKE_paint.hh:440
ActiveVert active_vert() const
Definition paint.cc:2367
bool deform_modifiers_active
Definition BKE_paint.hh:401
blender::Array< blender::float3 > positions
i
Definition text_draw.cc:230