Blender V4.3
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_key.hh"
14#include "BKE_mesh.hh"
15#include "BKE_paint.hh"
16#include "BKE_pbvh.hh"
17#include "BKE_subdiv_ccg.hh"
18
19#include "BLI_array.hh"
21#include "BLI_math_matrix.hh"
22#include "BLI_math_vector.hh"
23#include "BLI_task.h"
24#include "BLI_task.hh"
25
29
31
32inline namespace elastic_deform_cc {
33
38
39BLI_NOINLINE static void calc_translations(const Brush &brush,
40 const StrokeCache &cache,
41 const KelvinletParams &kelvinet_params,
42 const float3 &location,
43 const float3 &offset,
44 const Span<float3> positions,
45 const MutableSpan<float3> translations)
46{
49 for (const int i : positions.index_range()) {
50 BKE_kelvinlet_grab(translations[i], &kelvinet_params, positions[i], location, offset);
51 }
52 scale_translations(translations, cache.bstrength * 20.0f);
53 break;
54 }
56 for (const int i : positions.index_range()) {
58 translations[i], &kelvinet_params, positions[i], location, offset);
59 }
60 scale_translations(translations, cache.bstrength * 20.0f);
61 break;
62 }
64 for (const int i : positions.index_range()) {
66 translations[i], &kelvinet_params, positions[i], location, offset);
67 }
68 scale_translations(translations, cache.bstrength * 20.0f);
69 break;
70 }
72 for (const int i : positions.index_range()) {
74 translations[i], &kelvinet_params, positions[i], location, cache.sculpt_normal_symm);
75 }
76 break;
77 }
79 for (const int i : positions.index_range()) {
81 translations[i], &kelvinet_params, positions[i], location, cache.sculpt_normal_symm);
82 }
83 break;
84 }
85 }
86}
87
88static void calc_faces(const Depsgraph &depsgraph,
89 const Sculpt &sd,
90 const Brush &brush,
91 const KelvinletParams &kelvinet_params,
92 const float3 &offset,
93 const MeshAttributeData &attribute_data,
94 const bke::pbvh::MeshNode &node,
95 Object &object,
96 LocalData &tls,
97 const PositionDeformData &position_data)
98{
99 SculptSession &ss = *object.sculpt;
100 const StrokeCache &cache = *ss.cache;
101
102 const OrigPositionData orig_data = orig_position_data_get_mesh(object, node);
103 const Span<int> verts = node.verts();
104
105 tls.factors.resize(verts.size());
106 const MutableSpan<float> factors = tls.factors;
107 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
108 filter_region_clip_factors(ss, orig_data.positions, factors);
109
110 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
111
112 tls.translations.resize(verts.size());
113 const MutableSpan<float3> translations = tls.translations;
114 calc_translations(brush,
115 cache,
116 kelvinet_params,
117 cache.location_symm,
118 offset,
119 orig_data.positions,
120 translations);
121
122 scale_translations(translations, factors);
123
124 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
125 position_data.deform(translations, verts);
126}
127
128static void calc_grids(const Depsgraph &depsgraph,
129 const Sculpt &sd,
130 Object &object,
131 const Brush &brush,
132 const KelvinletParams &kelvinet_params,
133 const float3 &offset,
135 LocalData &tls)
136{
137 SculptSession &ss = *object.sculpt;
138 const StrokeCache &cache = *ss.cache;
139 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
140 const CCGKey key = BKE_subdiv_ccg_key_top_level(subdiv_ccg);
141
142 const OrigPositionData orig_data = orig_position_data_get_grids(object, node);
143 const Span<int> grids = node.grids();
144 const int grid_verts_num = grids.size() * key.grid_area;
145
146 tls.factors.resize(grid_verts_num);
147 const MutableSpan<float> factors = tls.factors;
148 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
149 filter_region_clip_factors(ss, orig_data.positions, factors);
150
151 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
152
153 tls.translations.resize(grid_verts_num);
154 const MutableSpan<float3> translations = tls.translations;
155 calc_translations(brush,
156 cache,
157 kelvinet_params,
158 cache.location_symm,
159 offset,
160 orig_data.positions,
161 translations);
162
163 scale_translations(translations, factors);
164
165 clip_and_lock_translations(sd, ss, orig_data.positions, translations);
166 apply_translations(translations, grids, subdiv_ccg);
167}
168
169static void calc_bmesh(const Depsgraph &depsgraph,
170 const Sculpt &sd,
171 Object &object,
172 const Brush &brush,
173 const KelvinletParams &kelvinet_params,
174 const float3 &offset,
176 LocalData &tls)
177{
178 SculptSession &ss = *object.sculpt;
179 const StrokeCache &cache = *ss.cache;
180
182
183 Array<float3> orig_positions(verts.size());
184 Array<float3> orig_normals(verts.size());
185 orig_position_data_gather_bmesh(*ss.bm_log, verts, orig_positions, orig_normals);
186
187 tls.factors.resize(verts.size());
188 const MutableSpan<float> factors = tls.factors;
190 filter_region_clip_factors(ss, orig_positions, factors);
191
192 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
193
194 tls.translations.resize(verts.size());
195 const MutableSpan<float3> translations = tls.translations;
197 brush, cache, kelvinet_params, cache.location_symm, offset, orig_positions, translations);
198
199 scale_translations(translations, factors);
200
201 clip_and_lock_translations(sd, ss, orig_positions, translations);
202 apply_translations(translations, verts);
203}
204
205} // namespace elastic_deform_cc
206
207void do_elastic_deform_brush(const Depsgraph &depsgraph,
208 const Sculpt &sd,
209 Object &object,
210 const IndexMask &node_mask)
211{
212 const SculptSession &ss = *object.sculpt;
213 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
214 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
215 const float strength = ss.cache->bstrength;
216
217 float3 grab_delta = ss.cache->grab_delta_symm;
218 if (ss.cache->normal_weight > 0.0f) {
220 }
221
222 float dir;
223 if (ss.cache->mouse[0] > ss.cache->initial_mouse[0]) {
224 dir = 1.0f;
225 }
226 else {
227 dir = -1.0f;
228 }
229
231 int symm = ss.cache->mirror_symmetry_pass;
232 if (ELEM(symm, 1, 2, 4, 7)) {
233 dir = -dir;
234 }
235 }
236
238 float force = math::length(grab_delta) * dir * strength;
240 &params, ss.cache->radius, force, 1.0f, brush.elastic_deform_volume_preservation);
241
243 switch (pbvh.type()) {
245 Mesh &mesh = *static_cast<Mesh *>(object.data);
246 const MeshAttributeData attribute_data(mesh.attributes());
247 const PositionDeformData position_data(depsgraph, object);
249 node_mask.foreach_index(GrainSize(1), [&](const int i) {
250 LocalData &tls = all_tls.local();
252 sd,
253 brush,
254 params,
255 grab_delta,
256 attribute_data,
257 nodes[i],
258 object,
259 tls,
260 position_data);
261 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
262 });
263 break;
264 }
266 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
267 MutableSpan<float3> positions = subdiv_ccg.positions;
269 node_mask.foreach_index(GrainSize(1), [&](const int i) {
270 LocalData &tls = all_tls.local();
271 calc_grids(depsgraph, sd, object, brush, params, grab_delta, nodes[i], tls);
272 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
273 });
274 break;
275 }
278 node_mask.foreach_index(GrainSize(1), [&](const int i) {
279 LocalData &tls = all_tls.local();
280 calc_bmesh(depsgraph, sd, object, brush, params, grab_delta, nodes[i], tls);
282 });
283 } break;
284 }
285 pbvh.tag_positions_changed(node_mask);
287}
288
289} // namespace blender::ed::sculpt_paint
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: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)
#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.
constexpr int64_t size() const
Definition BLI_span.hh:253
void resize(const int64_t new_size)
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]
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
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
void calc_grids_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, const bke::pbvh::GridsNode &node, Span< int > grids, MutableSpan< float > factors)
void calc_vert_factors(const Depsgraph &depsgraph, const Object &object, const Cache &cache, const bke::pbvh::MeshNode &node, Span< int > verts, 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: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 fill_factor_from_hide_and_mask(const Mesh &mesh, const Span< int > face_indices, const MutableSpan< float > r_factors)
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)
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)
void filter_region_clip_factors(const SculptSession &ss, Span< float3 > vert_positions, Span< int > verts, MutableSpan< float > factors)
Definition sculpt.cc:6639
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 do_elastic_deform_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
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)
T length(const VecBase< T, Size > &a)
void sculpt_project_v3_normal_align(const SculptSession &ss, const float normal_weight, float grab_delta[3])
Definition sculpt.cc:538
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:427
BMLog * bm_log
Definition BKE_paint.hh:402
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
blender::Array< blender::float3 > positions
std::unique_ptr< auto_mask::Cache > automasking