Blender V5.0
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
17
19
20#include "DNA_brush_types.h"
21#include "DNA_mesh_types.h"
22#include "DNA_object_types.h"
23#include "DNA_scene_types.h"
24
25#include "BKE_brush.hh"
26#include "BKE_mesh.hh"
27#include "BKE_paint.hh"
28#include "BKE_paint_bvh.hh"
29#include "BKE_subdiv_ccg.hh"
30
32#include "BLI_math_geom.h"
33#include "BLI_math_matrix.hh"
34#include "BLI_math_vector.hh"
35#include "BLI_task.hh"
36
40
41#include "bmesh.hh"
42
44
45inline namespace clay_strips_cc {
46
55
60static void calc_local_positions(const Span<float3> vert_positions,
61 const Span<int> verts,
62 const float4x4 &mat,
63 const MutableSpan<float2> xy_positions,
64 const MutableSpan<float> z_positions)
65{
66 BLI_assert(xy_positions.size() == verts.size());
67 BLI_assert(z_positions.size() == verts.size());
68
69 for (const int i : verts.index_range()) {
70 const float3 position = math::transform_point(mat, vert_positions[verts[i]]);
71
72 xy_positions[i] = position.xy();
73 z_positions[i] = position.z;
74 }
75}
76
77static void calc_local_positions(const Span<float3> positions,
78 const float4x4 &mat,
79 const MutableSpan<float2> xy_positions,
80 const MutableSpan<float> z_positions)
81{
82 BLI_assert(xy_positions.size() == positions.size());
83 BLI_assert(z_positions.size() == positions.size());
84
85 for (const int i : positions.index_range()) {
86 const float3 position = math::transform_point(mat, positions[i]);
87
88 xy_positions[i] = position.xy();
89 z_positions[i] = position.z;
90 }
91}
92
99static void apply_z_axis_factors(const Span<float> z_positions, const MutableSpan<float> factors)
100{
101 BLI_assert(factors.size() == z_positions.size());
102
103 for (const int i : factors.index_range()) {
104 const float local_z = z_positions[i];
105
106 /* Note: if `local_z > 1`, then `1 - local_z < 0` and the product is negative. */
107 factors[i] *= math::max(0.0f, local_z * (1.0f - local_z));
108 }
109}
110
115static void apply_plane_trim_factors(const Brush &brush,
116 const Span<float> z_positions,
117 const MutableSpan<float> factors)
118{
119 BLI_assert(factors.size() == z_positions.size());
120
121 const bool use_plane_trim = brush.flag & BRUSH_PLANE_TRIM;
122 if (!use_plane_trim) {
123 return;
124 }
125
126 for (const int i : factors.index_range()) {
127 if (z_positions[i] > brush.plane_trim) {
128 factors[i] = 0.0f;
129 }
130 }
131}
132
133static void calc_faces(const Depsgraph &depsgraph,
134 const Sculpt &sd,
135 const Brush &brush,
136 const float4x4 &mat,
137 const float3 &offset,
138 const Span<float3> vert_normals,
139 const MeshAttributeData &attribute_data,
140 const bke::pbvh::MeshNode &node,
141 Object &object,
142 LocalData &tls,
143 const PositionDeformData &position_data)
144{
145 SculptSession &ss = *object.sculpt;
146 const StrokeCache &cache = *ss.cache;
147
148 const Span<int> verts = node.verts();
149
150 tls.factors.resize(verts.size());
151 const MutableSpan<float> factors = tls.factors;
152 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
153 filter_region_clip_factors(ss, position_data.eval, verts, factors);
154 if (brush.flag & BRUSH_FRONTFACE) {
155 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
156 }
157
158 tls.xy_positions.resize(verts.size());
159 tls.z_positions.resize(verts.size());
160 MutableSpan<float2> xy_positions = tls.xy_positions;
161 MutableSpan<float> z_positions = tls.z_positions;
162
163 calc_local_positions(position_data.eval, verts, mat, xy_positions, z_positions);
164 apply_z_axis_factors(z_positions, factors);
165 apply_plane_trim_factors(brush, z_positions, factors);
166
167 tls.distances.resize(verts.size());
168 const MutableSpan<float> distances = tls.distances;
169 calc_brush_cube_distances<float2>(brush, xy_positions, distances);
170 filter_distances_with_radius(1.0f, distances, factors);
171 apply_hardness_to_distances(1.0f, cache.hardness, distances);
174 distances,
175 1.0f,
176 factors);
177
178 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
179
180 calc_brush_texture_factors(ss, brush, position_data.eval, verts, factors);
181
182 tls.translations.resize(verts.size());
184
185 clip_and_lock_translations(sd, ss, position_data.eval, verts, tls.translations);
186 position_data.deform(tls.translations, verts);
187}
188
189static void calc_grids(const Depsgraph &depsgraph,
190 const Sculpt &sd,
191 Object &object,
192 const Brush &brush,
193 const float4x4 &mat,
194 const float3 &offset,
195 const bke::pbvh::GridsNode &node,
196 LocalData &tls)
197{
198 SculptSession &ss = *object.sculpt;
199 const StrokeCache &cache = *ss.cache;
200 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
201
202 const Span<int> grids = node.grids();
203 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
204
205 tls.factors.resize(positions.size());
206 const MutableSpan<float> factors = tls.factors;
207 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
208 filter_region_clip_factors(ss, positions, factors);
209 if (brush.flag & BRUSH_FRONTFACE) {
210 calc_front_face(cache.view_normal_symm, subdiv_ccg, grids, factors);
211 }
212
213 tls.xy_positions.resize(positions.size());
214 tls.z_positions.resize(positions.size());
215 MutableSpan<float2> xy_positions = tls.xy_positions;
216 MutableSpan<float> z_positions = tls.z_positions;
217
218 calc_local_positions(positions, mat, xy_positions, z_positions);
219 apply_z_axis_factors(z_positions, factors);
220 apply_plane_trim_factors(brush, z_positions, factors);
221
222 tls.distances.resize(positions.size());
223 const MutableSpan<float> distances = tls.distances;
224 calc_brush_cube_distances<float2>(brush, xy_positions, distances);
225 filter_distances_with_radius(1.0f, distances, factors);
226 apply_hardness_to_distances(1.0f, cache.hardness, distances);
229 distances,
230 1.0f,
231 factors);
232
233 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
234
235 calc_brush_texture_factors(ss, brush, positions, factors);
236
237 tls.translations.resize(positions.size());
239
240 clip_and_lock_translations(sd, ss, positions, tls.translations);
241 apply_translations(tls.translations, grids, subdiv_ccg);
242}
243
244static void calc_bmesh(const Depsgraph &depsgraph,
245 const Sculpt &sd,
246 Object &object,
247 const Brush &brush,
248 const float4x4 &mat,
249 const float3 &offset,
251 LocalData &tls)
252{
253 SculptSession &ss = *object.sculpt;
254 const StrokeCache &cache = *ss.cache;
255
257 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
258
259 tls.factors.resize(verts.size());
260 const MutableSpan<float> factors = tls.factors;
262 filter_region_clip_factors(ss, positions, factors);
263 if (brush.flag & BRUSH_FRONTFACE) {
264 calc_front_face(cache.view_normal_symm, verts, factors);
265 }
266
267 tls.xy_positions.resize(positions.size());
268 tls.z_positions.resize(positions.size());
269 MutableSpan<float2> xy_positions = tls.xy_positions;
270 MutableSpan<float> z_positions = tls.z_positions;
271
272 calc_local_positions(positions, mat, xy_positions, z_positions);
273 apply_z_axis_factors(z_positions, factors);
274 apply_plane_trim_factors(brush, z_positions, factors);
275
276 tls.distances.resize(positions.size());
277 const MutableSpan<float> distances = tls.distances;
278 calc_brush_cube_distances<float2>(brush, xy_positions, distances);
279 filter_distances_with_radius(1.0f, distances, factors);
280 apply_hardness_to_distances(1.0f, cache.hardness, distances);
283 distances,
284 1.0f,
285 factors);
286
287 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
288
289 calc_brush_texture_factors(ss, brush, positions, factors);
290
291 tls.translations.resize(positions.size());
293
294 clip_and_lock_translations(sd, ss, positions, tls.translations);
296}
297
298} // namespace clay_strips_cc
299
300void do_clay_strips_brush(const Depsgraph &depsgraph,
301 const Sculpt &sd,
302 Object &object,
303 const IndexMask &node_mask,
304 const float3 &plane_normal,
305 const float3 &plane_center)
306{
307 SculptSession &ss = *object.sculpt;
308 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
309 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
310 const bool flip = (ss.cache->bstrength < 0.0f);
311
312 /* Note: This return has to happen *after* the call to calc_brush_plane for now, as
313 * the method is not idempotent and sets variables inside the stroke cache. */
315 return;
316 }
317
319 brush, *ss.cache, plane_normal, plane_center, flip);
320 const float3 offset = plane_normal * ss.cache->bstrength * ss.cache->radius;
321
323 switch (pbvh.type()) {
325 Mesh &mesh = *static_cast<Mesh *>(object.data);
327 const PositionDeformData position_data(depsgraph, object);
328 const MeshAttributeData attribute_data(mesh);
329 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
330 node_mask.foreach_index(GrainSize(1), [&](const int i) {
331 LocalData &tls = all_tls.local();
333 sd,
334 brush,
335 mat,
336 offset,
337 vert_normals,
338 attribute_data,
339 nodes[i],
340 object,
341 tls,
342 position_data);
343 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
344 });
345 break;
346 }
348 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
349 MutableSpan<float3> positions = subdiv_ccg.positions;
351 node_mask.foreach_index(GrainSize(1), [&](const int i) {
352 LocalData &tls = all_tls.local();
353 calc_grids(depsgraph, sd, object, brush, mat, offset, nodes[i], tls);
354 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
355 });
356 break;
357 }
360 node_mask.foreach_index(GrainSize(1), [&](const int i) {
361 LocalData &tls = all_tls.local();
362 calc_bmesh(depsgraph, sd, object, brush, mat, offset, nodes[i], tls);
364 });
365 break;
366 }
367 }
368 pbvh.tag_positions_changed(node_mask);
370}
371
372namespace clay_strips {
373
381static bool node_in_box(const float4x4 &mat, const Bounds<float3> &bounds)
382{
383 const float3 brush_center = float3(0.0f, 0.0f, 0.5f);
384 const float3 node_center = math::transform_point(mat, (bounds.max + bounds.min) * 0.5f);
385 const float3 center_diff = brush_center - node_center;
386
387 const float3 brush_half_lengths = float3(1.0f, 1.0f, 0.5f);
388 const float3 node_half_lengths = (bounds.max - bounds.min) * 0.5f;
389
390 const float3 &node_x_axis = mat.x_axis();
391 const float3 &node_y_axis = mat.y_axis();
392 const float3 &node_z_axis = mat.z_axis();
393
394 /* Tests if `axis` separates the boxes. */
395 auto axis_separates_boxes = [&](const float3 &axis) {
396 const float radius1 = math::dot(math::abs(axis), brush_half_lengths);
397 const float radius2 = math::abs(math::dot(axis, node_x_axis)) * node_half_lengths.x +
398 math::abs(math::dot(axis, node_y_axis)) * node_half_lengths.y +
399 math::abs(math::dot(axis, node_z_axis)) * node_half_lengths.z;
400
401 const float projection = math::abs(math::dot(center_diff, axis));
402
403 return projection > radius1 + radius2;
404 };
405
406 const std::array<float3, 3> brush_axes = {
407 float3{1.0f, 0.0f, 0.0f}, float3{0.0f, 1.0f, 0.0f}, float3{0.0f, 0.0f, 1.0f}};
408 const std::array<float3, 3> node_axes = {node_x_axis, node_y_axis, node_z_axis};
409
415
416 /* 1. Test axes aligned with the region affected by the brush. */
417 for (const float3 &axis : brush_axes) {
418 if (axis_separates_boxes(axis)) {
419 return false;
420 }
421 }
422
423 /* 2. Test axes aligned with the node bounds. */
424 for (const float3 &axis : node_axes) {
425 if (axis_separates_boxes(axis)) {
426 return false;
427 }
428 }
429
430 /* 3. Test all their cross products. */
431 for (const float3 &brush_axis : brush_axes) {
432 for (const float3 &node_axis : node_axes) {
433 if (axis_separates_boxes(math::cross(brush_axis, node_axis))) {
434 return false;
435 }
436 }
437 }
438
439 /* None of the axes separates the boxes: they intersect. */
440 return true;
441}
442
444 const StrokeCache &cache,
445 const float3 &plane_normal,
446 const float3 &plane_center,
447 const bool flip)
448{
450 mat.x_axis() = math::cross(plane_normal, cache.grab_delta_symm);
451 mat.y_axis() = math::cross(plane_normal, mat.x_axis());
452 mat.z_axis() = plane_normal;
453
454 /* Flip the z-axis so that the vertices below the plane have positive z-coordinates. When the
455 * brush is inverted, the affected z-coordinates are already positive. */
456 if (!flip) {
457 mat.z_axis() *= -1.0f;
458 }
459
460 mat.location() = plane_center;
461 mat = math::normalize(mat);
462
463 /* Scale brush local space matrix. */
464 const float4x4 scale = math::from_scale<float4x4>(float3(cache.radius));
465 float4x4 tmat = mat * scale;
466 tmat.y_axis() *= brush.tip_scale_x;
467 mat = math::invert(tmat);
468 return mat;
469}
470
472 Object &object,
473 const Brush &brush,
474 IndexMaskMemory &memory)
475{
476 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
477 const SculptSession &ss = *object.sculpt;
478
479 const bool flip = (ss.cache->bstrength < 0.0f);
480 const float displace = ss.cache->radius * brush_plane_offset_get(brush, ss) *
481 (flip ? -1.0f : 1.0f);
482
483 /* TODO: Test to see if the sqrt2 extra factor can be removed */
484 const float initial_radius_squared = math::square(ss.cache->radius * math::numbers::sqrt2);
485
486 const bool use_original = !ss.cache->accum;
487 const IndexMask initial_node_mask = gather_nodes(pbvh,
489 use_original,
491 initial_radius_squared,
493 memory);
494
495 float3 plane_center;
496 float3 plane_normal;
497 calc_brush_plane(depsgraph, brush, object, initial_node_mask, plane_normal, plane_center);
498 plane_normal = tilt_apply_to_normal(plane_normal, *ss.cache, brush.tilt_strength_factor);
499 plane_center += plane_normal * ss.cache->scale * displace;
500
501 if (math::is_zero(ss.cache->grab_delta_symm) || math::is_zero(plane_normal)) {
502 /* The brush local matrix is degenerate: return an empty index mask. */
503 return {IndexMask(), plane_center, plane_normal};
504 }
505
506 const float4x4 mat = calc_local_matrix(brush, *ss.cache, plane_normal, plane_center, flip);
507
508 const IndexMask plane_mask = bke::pbvh::search_nodes(
509 pbvh, memory, [&](const bke::pbvh::Node &node) {
510 if (node_fully_masked_or_hidden(node)) {
511 return false;
512 }
513 return node_in_box(mat, node.bounds());
514 });
515
516 return {plane_mask, plane_center, plane_normal};
517}
518} // namespace clay_strips
519
520} // namespace blender::ed::sculpt_paint::brushes
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:1448
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)
#define BLI_assert(a)
Definition BLI_assert.h:46
eBrushCurvePreset
@ BRUSH_FRONTFACE
@ BRUSH_PLANE_TRIM
eBrushFalloffShape
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:493
constexpr IndexRange index_range() const
Definition BLI_span.hh:670
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
const Bounds< float3 > & bounds() 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]
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
IndexMask search_nodes(const Tree &pbvh, IndexMaskMemory &memory, FunctionRef< bool(const Node &)> filter_fn)
Definition pbvh.cc:2663
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
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:1059
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 void apply_z_axis_factors(const Span< float > z_positions, const MutableSpan< float > factors)
static void calc_faces(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const float4x4 &mat, const float3 &offset, 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_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float4x4 &mat, const float3 &offset, bke::pbvh::BMeshNode &node, LocalData &tls)
static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float4x4 &mat, const float3 &offset, const bke::pbvh::GridsNode &node, LocalData &tls)
static void calc_local_positions(const Span< float3 > vert_positions, const Span< int > verts, const float4x4 &mat, const MutableSpan< float2 > xy_positions, const MutableSpan< float > z_positions)
static void apply_plane_trim_factors(const Brush &brush, const Span< float > z_positions, const MutableSpan< float > factors)
float4x4 calc_local_matrix(const Brush &brush, const StrokeCache &cache, const float3 &plane_normal, const float3 &plane_center, const bool flip)
CursorSampleResult calc_node_mask(const Depsgraph &depsgraph, Object &ob, const Brush &brush, IndexMaskMemory &memory)
static bool node_in_box(const float4x4 &mat, const Bounds< float3 > &bounds)
static BLI_NOINLINE void fill_factor_from_hide_and_mask(const Mesh &mesh, const Span< int > face_indices, const MutableSpan< float > r_factors)
void do_clay_strips_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &ob, const IndexMask &node_mask, const float3 &plane_normal, const float3 &plane_center)
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:6367
template void calc_brush_cube_distances< float2 >(const Brush &brush, const Span< float2 > positions, MutableSpan< float > r_distances)
void apply_hardness_to_distances(float radius, float hardness, MutableSpan< float > distances)
Definition sculpt.cc:7156
bool node_fully_masked_or_hidden(const bke::pbvh::Node &node)
Definition sculpt.cc:2418
void filter_distances_with_radius(float radius, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:7105
void filter_region_clip_factors(const SculptSession &ss, Span< float3 > vert_positions, Span< int > verts, MutableSpan< float > factors)
Definition sculpt.cc:6972
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7335
IndexMask gather_nodes(const bke::pbvh::Tree &pbvh, const eBrushFalloffShape falloff_shape, const bool use_original, const float3 &location, const float radius_sq, const std::optional< float3 > &ray_direction, IndexMaskMemory &memory)
Definition sculpt.cc:2502
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:2910
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:7268
void calc_brush_texture_factors(const SculptSession &ss, const Brush &brush, Span< float3 > vert_positions, Span< int > vert, MutableSpan< float > factors)
Definition sculpt.cc:7195
float brush_plane_offset_get(const Brush &brush, const SculptSession &ss)
Definition sculpt.cc:2993
void calc_front_face(const float3 &view_normal, Span< float3 > normals, MutableSpan< float > factors)
Definition sculpt.cc:6914
void translations_from_offset_and_factors(const float3 &offset, Span< float > factors, MutableSpan< float3 > r_translations)
Definition sculpt.cc:7531
float3 tilt_apply_to_normal(const Object &object, const float4x4 &view_inverse, const float3 &normal, const float2 &tilt, const float tilt_strength)
Definition sculpt.cc:2690
T dot(const QuaternionBase< T > &a, const QuaternionBase< T > &b)
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 square(const T &a)
T max(const T &a, const T &b)
T abs(const T &a)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
MatBase< float, 4, 4 > float4x4
VecBase< float, 3 > float3
float tip_scale_x
float plane_trim
char falloff_shape
float tilt_strength_factor
struct CurveMapping * curve_distance_falloff
int curve_distance_falloff_preset
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:417
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:395
blender::Array< blender::float3 > positions
VecBase< T, 2 > xy() const
std::unique_ptr< auto_mask::Cache > automasking
i
Definition text_draw.cc:230