Blender V5.0
elastic_deform.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_kelvinlet.h"
13#include "BKE_mesh.hh"
14#include "BKE_paint.hh"
15#include "BKE_paint_bvh.hh"
16#include "BKE_subdiv_ccg.hh"
17
18#include "BLI_array.hh"
20#include "BLI_math_vector.hh"
21#include "BLI_task.hh"
22
26
27#include "bmesh.hh"
28
30
31inline namespace elastic_deform_cc {
32
37
38BLI_NOINLINE static void calc_translations(const Brush &brush,
39 const StrokeCache &cache,
40 const KelvinletParams &kelvinet_params,
41 const float3 &location,
42 const float3 &offset,
43 const Span<float3> positions,
44 const MutableSpan<float3> translations)
45{
48 for (const int i : positions.index_range()) {
49 BKE_kelvinlet_grab(translations[i], &kelvinet_params, positions[i], location, offset);
50 }
51 scale_translations(translations, cache.bstrength * 20.0f);
52 break;
53 }
55 for (const int i : positions.index_range()) {
57 translations[i], &kelvinet_params, positions[i], location, offset);
58 }
59 scale_translations(translations, cache.bstrength * 20.0f);
60 break;
61 }
63 for (const int i : positions.index_range()) {
65 translations[i], &kelvinet_params, positions[i], location, offset);
66 }
67 scale_translations(translations, cache.bstrength * 20.0f);
68 break;
69 }
71 for (const int i : positions.index_range()) {
73 translations[i], &kelvinet_params, positions[i], location, cache.sculpt_normal_symm);
74 }
75 break;
76 }
78 for (const int i : positions.index_range()) {
80 translations[i], &kelvinet_params, positions[i], location, cache.sculpt_normal_symm);
81 }
82 break;
83 }
84 }
85}
86
87static void calc_faces(const Depsgraph &depsgraph,
88 const Sculpt &sd,
89 const Brush &brush,
90 const KelvinletParams &kelvinet_params,
91 const float3 &offset,
92 const MeshAttributeData &attribute_data,
93 const bke::pbvh::MeshNode &node,
94 Object &object,
95 LocalData &tls,
96 const PositionDeformData &position_data)
97{
98 SculptSession &ss = *object.sculpt;
99 const StrokeCache &cache = *ss.cache;
100
101 const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
102 const Span<int> verts = node.verts();
103
104 tls.factors.resize(verts.size());
105 const MutableSpan<float> factors = tls.factors;
106 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
107 filter_region_clip_factors(ss, orig_data.positions, factors);
108
109 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
110
111 tls.translations.resize(verts.size());
112 const MutableSpan<float3> translations = tls.translations;
113 calc_translations(brush,
114 cache,
115 kelvinet_params,
116 cache.location_symm,
117 offset,
118 orig_data.positions,
119 translations);
120
121 scale_translations(translations, factors);
122
123 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
124 position_data.deform(translations, verts);
125}
126
127static void calc_grids(const Depsgraph &depsgraph,
128 const Sculpt &sd,
129 Object &object,
130 const Brush &brush,
131 const KelvinletParams &kelvinet_params,
132 const float3 &offset,
134 LocalData &tls)
135{
136 SculptSession &ss = *object.sculpt;
137 const StrokeCache &cache = *ss.cache;
138 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
139 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
140
141 const OrigPositionData orig_data = orig_position_data_get_grids(object, node);
142 const Span<int> grids = node.grids();
143 const int grid_verts_num = grids.size() * key.grid_area;
144
145 tls.factors.resize(grid_verts_num);
146 const MutableSpan<float> factors = tls.factors;
147 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
148 filter_region_clip_factors(ss, orig_data.positions, factors);
149
150 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
151
152 tls.translations.resize(grid_verts_num);
153 const MutableSpan<float3> translations = tls.translations;
154 calc_translations(brush,
155 cache,
156 kelvinet_params,
157 cache.location_symm,
158 offset,
159 orig_data.positions,
160 translations);
161
162 scale_translations(translations, factors);
163
164 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
165 apply_translations(translations, grids, subdiv_ccg);
166}
167
168static void calc_bmesh(const Depsgraph &depsgraph,
169 const Sculpt &sd,
170 Object &object,
171 const Brush &brush,
172 const KelvinletParams &kelvinet_params,
173 const float3 &offset,
175 LocalData &tls)
176{
177 SculptSession &ss = *object.sculpt;
178 const StrokeCache &cache = *ss.cache;
179
181
182 Array<float3> orig_positions(verts.size());
183 Array<float3> orig_normals(verts.size());
184 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
185
186 tls.factors.resize(verts.size());
187 const MutableSpan<float> factors = tls.factors;
189 filter_region_clip_factors(ss, orig_positions, factors);
190
191 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
192
193 tls.translations.resize(verts.size());
194 const MutableSpan<float3> translations = tls.translations;
196 brush, cache, kelvinet_params, cache.location_symm, offset, orig_positions, translations);
197
198 scale_translations(translations, factors);
199
200 clip_and_lock_translations(sd, ss, orig_positions, translations);
201 apply_translations(translations, verts);
202}
203
204} // namespace elastic_deform_cc
205
206void do_elastic_deform_brush(const Depsgraph &depsgraph,
207 const Sculpt &sd,
208 Object &object,
209 const IndexMask &node_mask)
210{
211 const SculptSession &ss = *object.sculpt;
212 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
213 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
214 const float strength = ss.cache->bstrength;
215
216 float3 grab_delta = ss.cache->grab_delta_symm;
217 if (ss.cache->normal_weight > 0.0f) {
219 }
220
221 float dir;
222 if (ss.cache->mouse[0] > ss.cache->initial_mouse[0]) {
223 dir = 1.0f;
224 }
225 else {
226 dir = -1.0f;
227 }
228
230 int symm = ss.cache->mirror_symmetry_pass;
231 if (ELEM(symm, 1, 2, 4, 7)) {
232 dir = -dir;
233 }
234 }
235
237 float force = math::length(grab_delta) * dir * strength;
239 &params, ss.cache->radius, force, 1.0f, brush.elastic_deform_volume_preservation);
240
242 switch (pbvh.type()) {
244 Mesh &mesh = *static_cast<Mesh *>(object.data);
245 const MeshAttributeData attribute_data(mesh);
246 const PositionDeformData position_data(depsgraph, object);
248 node_mask.foreach_index(GrainSize(1), [&](const int i) {
249 LocalData &tls = all_tls.local();
251 sd,
252 brush,
253 params,
254 grab_delta,
255 attribute_data,
256 nodes[i],
257 object,
258 tls,
259 position_data);
260 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
261 });
262 break;
263 }
265 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
266 MutableSpan<float3> positions = subdiv_ccg.positions;
268 node_mask.foreach_index(GrainSize(1), [&](const int i) {
269 LocalData &tls = all_tls.local();
270 calc_grids(depsgraph, sd, object, brush, params, grab_delta, nodes[i], tls);
271 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
272 });
273 break;
274 }
277 node_mask.foreach_index(GrainSize(1), [&](const int i) {
278 LocalData &tls = all_tls.local();
279 calc_bmesh(depsgraph, sd, object, brush, params, grab_delta, nodes[i], tls);
281 });
282 } break;
283 }
284 pbvh.tag_positions_changed(node_mask);
286}
287
288} // namespace blender::ed::sculpt_paint::brushes
void BKE_kelvinlet_grab(float radius_elem_disp[3], const KelvinletParams *params, const float elem_orig_co[3], const float brush_location[3], const float brush_delta[3])
Definition kelvinlet.cc:54
void BKE_kelvinlet_grab_triscale(float radius_elem_disp[3], const KelvinletParams *params, const float elem_orig_co[3], const float brush_location[3], const float brush_delta[3])
Definition kelvinlet.cc:90
void BKE_kelvinlet_init_params(KelvinletParams *params, float radius, float force, float shear_modulus, float poisson_ratio)
Definition kelvinlet.cc:16
void BKE_kelvinlet_grab_biscale(float radius_elem_disp[3], const KelvinletParams *params, const float elem_orig_co[3], const float brush_location[3], const float brush_delta[3])
Definition kelvinlet.cc:71
void BKE_kelvinlet_scale(float radius_elem_disp[3], const KelvinletParams *params, const float elem_orig_co[3], const float brush_location[3], const float surface_normal[3])
Definition kelvinlet.cc:166
void BKE_kelvinlet_twist(float radius_elem_disp[3], const KelvinletParams *params, const float elem_orig_co[3], const float brush_location[3], const float surface_normal[3])
Definition kelvinlet.cc:194
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:650
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_NOINLINE
#define ELEM(...)
eBrushElasticDeformType
@ BRUSH_ELASTIC_DEFORM_SCALE
@ BRUSH_ELASTIC_DEFORM_GRAB
@ BRUSH_ELASTIC_DEFORM_TWIST
@ BRUSH_ELASTIC_DEFORM_GRAB_BISCALE
@ BRUSH_ELASTIC_DEFORM_GRAB_TRISCALE
Object is a sort of wrapper for general info.
BPy_StructRNA * depsgraph
void resize(const int64_t new_size)
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
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]
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
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
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)
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 BLI_NOINLINE void fill_factor_from_hide_and_mask(const Mesh &mesh, const Span< int > face_indices, const MutableSpan< float > r_factors)
static BLI_NOINLINE void calc_translations(const Brush &brush, const StrokeCache &cache, const KelvinletParams &kelvinet_params, const float3 &location, const float3 &offset, const Span< float3 > positions, const MutableSpan< float3 > translations)
static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const KelvinletParams &kelvinet_params, const float3 &offset, bke::pbvh::BMeshNode &node, LocalData &tls)
static void calc_faces(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const KelvinletParams &kelvinet_params, const float3 &offset, const MeshAttributeData &attribute_data, const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const PositionDeformData &position_data)
static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const KelvinletParams &kelvinet_params, const float3 &offset, bke::pbvh::GridsNode &node, LocalData &tls)
void do_elastic_deform_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void filter_region_clip_factors(const SculptSession &ss, Span< float3 > vert_positions, Span< int > verts, MutableSpan< float > factors)
Definition sculpt.cc:6972
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:7495
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)
T length(const VecBase< T, Size > &a)
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 elastic_deform_type
float elastic_deform_volume_preservation
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
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:395
blender::Array< blender::float3 > positions
std::unique_ptr< auto_mask::Cache > automasking
i
Definition text_draw.cc:230