Blender V4.3
pinch.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.h"
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 pinch_cc {
33
40
41BLI_NOINLINE static void calc_translations(const Span<float3> positions,
42 const float3 &location,
43 const std::array<float3, 2> &stroke_xz,
44 const MutableSpan<float3> translations)
45{
46 BLI_assert(positions.size() == translations.size());
47
48 for (const int i : positions.index_range()) {
49 /* Calculate displacement from the vertex to the brush center. */
50 const float3 disp_center = location - positions[i];
51
52 /* Project the displacement into the X vector (aligned to the stroke). */
53 const float3 x_disp = stroke_xz[0] * math::dot(disp_center, stroke_xz[0]);
54
55 /* Project the displacement into the Z vector (aligned to the surface normal). */
56 const float3 z_disp = stroke_xz[1] * math::dot(disp_center, stroke_xz[1]);
57
58 /* Add the two projected vectors to calculate the final displacement.
59 * The Y component is removed. */
60 translations[i] = x_disp + z_disp;
61 }
62}
63
64static void calc_faces(const Depsgraph &depsgraph,
65 const Sculpt &sd,
66 const Brush &brush,
67 const std::array<float3, 2> &stroke_xz,
68 const float strength,
69 const MeshAttributeData &attribute_data,
70 const Span<float3> vert_normals,
71 const bke::pbvh::MeshNode &node,
72 Object &object,
73 LocalData &tls,
74 const PositionDeformData &position_data)
75{
76 SculptSession &ss = *object.sculpt;
77 const StrokeCache &cache = *ss.cache;
78
79 const Span<int> verts = node.verts();
80 const MutableSpan positions = gather_data_mesh(position_data.eval, verts, tls.positions);
81
83 brush,
84 object,
85 attribute_data,
86 positions,
87 vert_normals,
88 node,
89 tls.factors,
90 tls.distances);
91
92 scale_factors(tls.factors, strength);
93
94 tls.translations.resize(verts.size());
95 const MutableSpan<float3> translations = tls.translations;
96 calc_translations(positions, cache.location_symm, stroke_xz, translations);
98 project_translations(translations, cache.view_normal_symm);
99 }
100
101 scale_translations(translations, tls.factors);
102
103 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
104 position_data.deform(translations, verts);
105}
106
107static void calc_grids(const Depsgraph &depsgraph,
108 const Sculpt &sd,
109 Object &object,
110 const Brush &brush,
111 const std::array<float3, 2> &stroke_xz,
112 const float strength,
113 const bke::pbvh::GridsNode &node,
114 LocalData &tls)
115{
116 SculptSession &ss = *object.sculpt;
117 const StrokeCache &cache = *ss.cache;
118 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
119
120 const Span<int> grids = node.grids();
121 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
122
123 calc_factors_common_grids(depsgraph, brush, object, positions, node, tls.factors, tls.distances);
124
125 scale_factors(tls.factors, strength);
126
127 tls.translations.resize(positions.size());
128 const MutableSpan<float3> translations = tls.translations;
129 calc_translations(positions, cache.location_symm, stroke_xz, translations);
131 project_translations(translations, cache.view_normal_symm);
132 }
133
134 scale_translations(translations, tls.factors);
135
136 clip_and_lock_translations(sd, ss, positions, translations);
137 apply_translations(translations, grids, subdiv_ccg);
138}
139
140static void calc_bmesh(const Depsgraph &depsgraph,
141 const Sculpt &sd,
142 Object &object,
143 const Brush &brush,
144 const std::array<float3, 2> &stroke_xz,
145 const float strength,
147 LocalData &tls)
148{
149 SculptSession &ss = *object.sculpt;
150 const StrokeCache &cache = *ss.cache;
151
153
154 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
155
156 calc_factors_common_bmesh(depsgraph, brush, object, positions, node, tls.factors, tls.distances);
157
158 scale_factors(tls.factors, strength);
159
160 tls.translations.resize(verts.size());
161 const MutableSpan<float3> translations = tls.translations;
162 calc_translations(positions, cache.location_symm, stroke_xz, translations);
164 project_translations(translations, cache.view_normal_symm);
165 }
166
167 scale_translations(translations, tls.factors);
168
169 clip_and_lock_translations(sd, ss, positions, translations);
170 apply_translations(translations, verts);
171}
172
173} // namespace pinch_cc
174
175void do_pinch_brush(const Depsgraph &depsgraph,
176 const Sculpt &sd,
177 Object &object,
178 const IndexMask &node_mask)
179{
180 const SculptSession &ss = *object.sculpt;
181 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
182 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
183
184 float3 area_no;
185 float3 area_co;
186 calc_brush_plane(depsgraph, brush, object, node_mask, area_no, area_co);
187
188 /* delay the first daub because grab delta is not setup */
190 return;
191 }
192
194 return;
195 }
196
197 /* Initialize `mat`. */
199 mat.x_axis() = math::cross(area_no, ss.cache->grab_delta_symm);
200 mat.y_axis() = math::cross(area_no, mat.x_axis());
201 mat.z_axis() = area_no;
202 mat.location() = ss.cache->location_symm;
203 normalize_m4(mat.ptr());
204
205 const std::array<float3, 2> stroke_xz{math::normalize(mat.x_axis()),
206 math::normalize(mat.z_axis())};
207
209 switch (pbvh.type()) {
211 const Mesh &mesh = *static_cast<Mesh *>(object.data);
212 const MeshAttributeData attribute_data(mesh.attributes());
213 const PositionDeformData position_data(depsgraph, object);
214 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
216 node_mask.foreach_index(GrainSize(1), [&](const int i) {
217 LocalData &tls = all_tls.local();
219 sd,
220 brush,
221 stroke_xz,
222 ss.cache->bstrength,
223 attribute_data,
224 vert_normals,
225 nodes[i],
226 object,
227 tls,
228 position_data);
229 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
230 });
231 break;
232 }
234 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
235 MutableSpan<float3> positions = subdiv_ccg.positions;
237 node_mask.foreach_index(GrainSize(1), [&](const int i) {
238 LocalData &tls = all_tls.local();
239 calc_grids(depsgraph, sd, object, brush, stroke_xz, ss.cache->bstrength, nodes[i], tls);
240 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
241 });
242 break;
243 }
246 node_mask.foreach_index(GrainSize(1), [&](const int i) {
247 LocalData &tls = all_tls.local();
248 calc_bmesh(depsgraph, sd, object, brush, stroke_xz, ss.cache->bstrength, nodes[i], tls);
250 });
251 break;
252 }
253 }
254 pbvh.tag_positions_changed(node_mask);
256}
257
258} // namespace blender::ed::sculpt_paint
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 normalize_m4(float R[4][4]) ATTR_NONNULL()
@ PAINT_FALLOFF_SHAPE_TUBE
Object is a sort of wrapper for general info.
constexpr int64_t size() const
Definition BLI_span.hh:494
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
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 std::array< float3, 2 > &stroke_xz, const float strength, const bke::pbvh::GridsNode &node, LocalData &tls)
Definition pinch.cc:107
static BLI_NOINLINE void calc_translations(const Span< float3 > positions, const float3 &location, const std::array< float3, 2 > &stroke_xz, const MutableSpan< float3 > translations)
Definition pinch.cc:41
static void calc_faces(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const std::array< float3, 2 > &stroke_xz, 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 pinch.cc:64
static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const std::array< float3, 2 > &stroke_xz, const float strength, bke::pbvh::BMeshNode &node, LocalData &tls)
Definition pinch.cc:140
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 calc_factors_common_grids(const Depsgraph &depsgraph, const Brush &brush, const Object &object, Span< float3 > positions, const bke::pbvh::GridsNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6270
void scale_translations(MutableSpan< float3 > translations, Span< float > factors)
Definition sculpt.cc:7210
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 project_translations(MutableSpan< float3 > translations, const float3 &plane)
Definition sculpt.cc:6998
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
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6958
void calc_factors_common_mesh(const Depsgraph &depsgraph, const Brush &brush, const Object &object, const MeshAttributeData &attribute_data, Span< float3 > positions, Span< float3 > vert_normals, const bke::pbvh::MeshNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6235
void gather_data_mesh(Span< T > src, Span< int > indices, MutableSpan< T > dst)
Definition sculpt.cc:6082
void do_pinch_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask)
Definition pinch.cc:175
void calc_factors_common_bmesh(const Depsgraph &depsgraph, const Brush &brush, const Object &object, Span< float3 > positions, bke::pbvh::BMeshNode &node, Vector< float > &r_factors, Vector< float > &r_distances)
Definition sculpt.cc:6304
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
bool is_zero(const T &a)
AxisSigned cross(const AxisSigned a, const AxisSigned b)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
bool SCULPT_stroke_is_first_brush_step_of_symmetry_pass(const blender::ed::sculpt_paint::StrokeCache &cache)
Definition sculpt.cc:513
char falloff_shape
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:427
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:405
blender::Array< blender::float3 > positions
const c_style_mat & ptr() const