Blender V4.3
clay_strips.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_brush.hh"
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_geom.h"
22#include "BLI_math_matrix.h"
23#include "BLI_math_matrix.hh"
24#include "BLI_math_vector.hh"
25#include "BLI_task.h"
26#include "BLI_task.hh"
27
31
33
34inline namespace clay_strips_cc {
35
42
54BLI_NOINLINE static void apply_z_axis_falloff(const Span<float3> vert_positions,
55 const Span<int> verts,
56 const float4x4 &mat,
57 const MutableSpan<float> factors)
58{
59 BLI_assert(factors.size() == verts.size());
60 for (const int i : factors.index_range()) {
61 const float local_z_distance = math::abs(
62 math::transform_point(mat, vert_positions[verts[i]]).z);
63 factors[i] *= 1 - local_z_distance;
64 }
65}
66
68 const float4x4 &mat,
69 const MutableSpan<float> factors)
70{
71 BLI_assert(factors.size() == positions.size());
72 for (const int i : factors.index_range()) {
73 const float local_z_distance = math::abs(math::transform_point(mat, positions[i]).z);
74 factors[i] *= 1 - local_z_distance;
75 }
76}
77
78static void calc_faces(const Depsgraph &depsgraph,
79 const Sculpt &sd,
80 const Brush &brush,
81 const float4x4 &mat,
82 const float4 &plane,
83 const float strength,
84 const bool flip,
85 const Span<float3> vert_normals,
86 const MeshAttributeData &attribute_data,
87 const bke::pbvh::MeshNode &node,
88 Object &object,
89 LocalData &tls,
90 const PositionDeformData &position_data)
91{
92 SculptSession &ss = *object.sculpt;
93 const StrokeCache &cache = *ss.cache;
94
95 const Span<int> verts = node.verts();
96
97 tls.factors.resize(verts.size());
98 const MutableSpan<float> factors = tls.factors;
99 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
100 filter_region_clip_factors(ss, position_data.eval, verts, factors);
101 if (brush.flag & BRUSH_FRONTFACE) {
102 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
103 }
104
105 tls.distances.resize(verts.size());
106 const MutableSpan<float> distances = tls.distances;
107 calc_brush_cube_distances(brush, mat, position_data.eval, verts, distances, factors);
108 apply_z_axis_falloff(position_data.eval, verts, mat, factors);
109 filter_distances_with_radius(1.0f, distances, factors);
110 apply_hardness_to_distances(1.0f, cache.hardness, distances);
112 eBrushCurvePreset(brush.curve_preset), brush.curve, distances, 1.0f, factors);
113
114 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
115
116 calc_brush_texture_factors(ss, brush, position_data.eval, verts, factors);
117
118 scale_factors(factors, strength);
119
120 if (flip) {
121 filter_below_plane_factors(position_data.eval, verts, plane, factors);
122 }
123 else {
124 filter_above_plane_factors(position_data.eval, verts, plane, factors);
125 }
126
127 tls.translations.resize(verts.size());
128 const MutableSpan<float3> translations = tls.translations;
129 calc_translations_to_plane(position_data.eval, verts, plane, translations);
130 filter_plane_trim_limit_factors(brush, cache, translations, factors);
131 scale_translations(translations, factors);
132
133 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
134 position_data.deform(translations, verts);
135}
136
137static void calc_grids(const Depsgraph &depsgraph,
138 const Sculpt &sd,
139 Object &object,
140 const Brush &brush,
141 const float4x4 &mat,
142 const float4 &plane,
143 const float strength,
144 const bool flip,
145 const bke::pbvh::GridsNode &node,
146 LocalData &tls)
147{
148 SculptSession &ss = *object.sculpt;
149 const StrokeCache &cache = *ss.cache;
150 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
151
152 const Span<int> grids = node.grids();
153 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
154
155 tls.factors.resize(positions.size());
156 const MutableSpan<float> factors = tls.factors;
157 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
158 filter_region_clip_factors(ss, positions, factors);
159 if (brush.flag & BRUSH_FRONTFACE) {
160 calc_front_face(cache.view_normal_symm, subdiv_ccg, grids, factors);
161 }
162
163 tls.distances.resize(positions.size());
164 const MutableSpan<float> distances = tls.distances;
165 calc_brush_cube_distances(brush, mat, positions, distances, factors);
166 apply_z_axis_falloff(positions, mat, factors);
167 filter_distances_with_radius(1.0f, distances, factors);
168 apply_hardness_to_distances(1.0f, cache.hardness, distances);
170 eBrushCurvePreset(brush.curve_preset), brush.curve, distances, 1.0f, factors);
171
172 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
173
174 calc_brush_texture_factors(ss, brush, positions, factors);
175
176 scale_factors(factors, strength);
177
178 if (flip) {
179 filter_below_plane_factors(positions, plane, factors);
180 }
181 else {
182 filter_above_plane_factors(positions, plane, factors);
183 }
184
185 tls.translations.resize(positions.size());
186 const MutableSpan<float3> translations = tls.translations;
187 calc_translations_to_plane(positions, plane, translations);
188 filter_plane_trim_limit_factors(brush, cache, translations, factors);
189 scale_translations(translations, factors);
190
191 clip_and_lock_translations(sd, ss, positions, translations);
192 apply_translations(translations, grids, subdiv_ccg);
193}
194
195static void calc_bmesh(const Depsgraph &depsgraph,
196 const Sculpt &sd,
197 Object &object,
198 const Brush &brush,
199 const float4x4 &mat,
200 const float4 &plane,
201 const float strength,
202 const bool flip,
204 LocalData &tls)
205{
206 SculptSession &ss = *object.sculpt;
207 const StrokeCache &cache = *ss.cache;
208
210 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
211
212 tls.factors.resize(verts.size());
213 const MutableSpan<float> factors = tls.factors;
215 filter_region_clip_factors(ss, positions, factors);
216 if (brush.flag & BRUSH_FRONTFACE) {
217 calc_front_face(cache.view_normal_symm, verts, factors);
218 }
219
220 tls.distances.resize(verts.size());
221 const MutableSpan<float> distances = tls.distances;
222 calc_brush_cube_distances(brush, mat, positions, distances, factors);
223 apply_z_axis_falloff(positions, mat, factors);
224 filter_distances_with_radius(1.0f, distances, factors);
225 apply_hardness_to_distances(1.0f, cache.hardness, distances);
227 eBrushCurvePreset(brush.curve_preset), brush.curve, distances, 1.0f, factors);
228
229 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
230
231 calc_brush_texture_factors(ss, brush, positions, factors);
232
233 scale_factors(factors, strength);
234
235 if (flip) {
236 filter_below_plane_factors(positions, plane, factors);
237 }
238 else {
239 filter_above_plane_factors(positions, plane, factors);
240 }
241
242 tls.translations.resize(verts.size());
243 const MutableSpan<float3> translations = tls.translations;
244 calc_translations_to_plane(positions, plane, translations);
245 filter_plane_trim_limit_factors(brush, cache, translations, factors);
246 scale_translations(translations, factors);
247
248 clip_and_lock_translations(sd, ss, positions, translations);
249 apply_translations(translations, verts);
250}
251
252} // namespace clay_strips_cc
253
254void do_clay_strips_brush(const Depsgraph &depsgraph,
255 const Sculpt &sd,
256 Object &object,
257 const IndexMask &node_mask)
258{
259 SculptSession &ss = *object.sculpt;
260 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
262 return;
263 }
264
265 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
266 const bool flip = (ss.cache->bstrength < 0.0f);
267 const float radius = flip ? -ss.cache->radius : ss.cache->radius;
268 const float offset = SCULPT_brush_plane_offset_get(sd, ss);
269 const float displace = radius * (0.18f + offset);
270
271 float3 area_position;
272 float3 plane_normal;
273 calc_brush_plane(depsgraph, brush, object, node_mask, plane_normal, area_position);
275 area_position += plane_normal * ss.cache->scale * displace;
276
277 float3 area_normal;
279 area_normal = calc_area_normal(depsgraph, brush, object, node_mask).value_or(float3(0));
280 }
281 else {
282 area_normal = plane_normal;
283 }
284
286 mat.x_axis() = math::cross(area_normal, ss.cache->grab_delta_symm);
287 mat.y_axis() = math::cross(area_normal, float3(mat[0]));
288 mat.z_axis() = area_normal;
289 mat.location() = area_position;
290 mat = math::normalize(mat);
291
292 /* Scale brush local space matrix. */
294 float4x4 tmat = mat * scale;
295
296 tmat.y_axis() *= brush.tip_scale_x;
297
298 mat = math::invert(tmat);
299
300 float4 plane;
301 plane_from_point_normal_v3(plane, area_position, plane_normal);
302
303 const float strength = std::abs(ss.cache->bstrength);
304
306 switch (pbvh.type()) {
308 Mesh &mesh = *static_cast<Mesh *>(object.data);
310 const PositionDeformData position_data(depsgraph, object);
311 const MeshAttributeData attribute_data(mesh.attributes());
312 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
313 node_mask.foreach_index(GrainSize(1), [&](const int i) {
314 LocalData &tls = all_tls.local();
316 sd,
317 brush,
318 mat,
319 plane,
320 strength,
321 flip,
322 vert_normals,
323 attribute_data,
324 nodes[i],
325 object,
326 tls,
327 position_data);
328 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
329 });
330 break;
331 }
333 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
334 MutableSpan<float3> positions = subdiv_ccg.positions;
336 node_mask.foreach_index(GrainSize(1), [&](const int i) {
337 LocalData &tls = all_tls.local();
338 calc_grids(depsgraph, sd, object, brush, mat, plane, strength, flip, nodes[i], tls);
339 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
340 });
341 break;
342 }
345 node_mask.foreach_index(GrainSize(1), [&](const int i) {
346 LocalData &tls = all_tls.local();
347 calc_bmesh(depsgraph, sd, object, brush, mat, plane, strength, flip, nodes[i], tls);
349 });
350 break;
351 }
352 }
353 pbvh.tag_positions_changed(node_mask);
355}
356
357} // namespace blender::ed::sculpt_paint
void BKE_brush_calc_curve_factors(eBrushCurvePreset preset, const CurveMapping *cumap, blender::Span< float > distances, float brush_radius, blender::MutableSpan< float > factors)
Definition brush.cc:1265
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)
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_NOINLINE
void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3])
Definition math_geom.cc:215
eBrushCurvePreset
@ BRUSH_ORIGINAL_NORMAL
@ BRUSH_FRONTFACE
@ SCULPT_DISP_DIR_AREA
Object is a sort of wrapper for general info.
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
constexpr int64_t size() const
Definition BLI_span.hh:494
constexpr IndexRange index_range() const
Definition BLI_span.hh:671
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]
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
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2502
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 void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float4x4 &mat, const float4 &plane, const float strength, const bool flip, bke::pbvh::BMeshNode &node, LocalData &tls)
static void calc_faces(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const float4x4 &mat, const float4 &plane, const float strength, const bool flip, const Span< float3 > vert_normals, 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 float4x4 &mat, const float4 &plane, const float strength, const bool flip, const bke::pbvh::GridsNode &node, LocalData &tls)
static BLI_NOINLINE void apply_z_axis_falloff(const Span< float3 > vert_positions, const Span< int > verts, const float4x4 &mat, const MutableSpan< float > factors)
static BLI_NOINLINE void fill_factor_from_hide_and_mask(const Mesh &mesh, const Span< int > face_indices, const MutableSpan< float > r_factors)
MutableSpan< float3 > gather_grids_positions(const SubdivCCG &subdiv_ccg, const Span< int > grids, Vector< float3 > &positions)
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6054
void filter_below_plane_factors(Span< float3 > vert_positions, Span< int > verts, const float4 &plane, MutableSpan< float > factors)
Definition sculpt.cc:7534
void apply_hardness_to_distances(float radius, float hardness, MutableSpan< float > distances)
Definition sculpt.cc:6862
void filter_distances_with_radius(float radius, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:6772
void filter_region_clip_factors(const SculptSession &ss, Span< float3 > vert_positions, Span< int > verts, MutableSpan< float > factors)
Definition sculpt.cc:6639
void scale_translations(MutableSpan< float3 > translations, Span< float > factors)
Definition sculpt.cc:7210
void calc_translations_to_plane(Span< float3 > vert_positions, Span< int > verts, const float4 &plane, MutableSpan< float3 > translations)
Definition sculpt.cc:7479
void scale_factors(MutableSpan< float > factors, float strength)
Definition sculpt.cc:7227
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 calc_brush_plane(const Depsgraph &depsgraph, const Brush &brush, Object &ob, const IndexMask &node_mask, float3 &r_area_no, float3 &r_area_co)
Definition sculpt.cc:2789
std::optional< float3 > calc_area_normal(const Depsgraph &depsgraph, const Brush &brush, const Object &ob, const IndexMask &node_mask)
Definition sculpt.cc:1848
void filter_plane_trim_limit_factors(const Brush &brush, const StrokeCache &cache, Span< float3 > translations, MutableSpan< float > factors)
Definition sculpt.cc:7518
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6958
void filter_above_plane_factors(Span< float3 > vert_positions, Span< int > verts, const float4 &plane, MutableSpan< float > factors)
Definition sculpt.cc:7557
void calc_brush_cube_distances(const Brush &brush, const float4x4 &mat, Span< float3 > positions, Span< int > verts, MutableSpan< float > r_distances, MutableSpan< float > factors)
Definition sculpt.cc:6783
void calc_front_face(const float3 &view_normal, Span< float3 > normals, MutableSpan< float > factors)
Definition sculpt.cc:6581
void do_clay_strips_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
void calc_brush_texture_factors(const SculptSession &ss, const Brush &brush, Span< float3 > vert_positions, Span< int > vert_indices, MutableSpan< float > factors)
Definition sculpt.cc:6898
bool is_zero(const T &a)
CartesianBasis invert(const CartesianBasis &basis)
AxisSigned cross(const AxisSigned a, const AxisSigned b)
MatT from_scale(const VecBase< typename MatT::base_type, ScaleDim > &scale)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
T abs(const T &a)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
VecBase< float, 3 > float3
void SCULPT_tilt_apply_to_normal(float r_normal[3], blender::ed::sculpt_paint::StrokeCache *cache, const float tilt_strength)
Definition sculpt.cc:2550
float SCULPT_brush_plane_offset_get(const Sculpt &sd, const SculptSession &ss)
Definition sculpt.cc:2883
int sculpt_plane
int curve_preset
struct CurveMapping * curve
float tip_scale_x
float tilt_strength_factor
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:427
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
blender::Array< blender::float3 > positions
std::unique_ptr< auto_mask::Cache > automasking