Blender V4.5
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);
173 eBrushCurvePreset(brush.curve_preset), brush.curve, distances, 1.0f, factors);
174
175 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
176
177 calc_brush_texture_factors(ss, brush, position_data.eval, verts, factors);
178
179 tls.translations.resize(verts.size());
181
182 clip_and_lock_translations(sd, ss, position_data.eval, verts, tls.translations);
183 position_data.deform(tls.translations, verts);
184}
185
186static void calc_grids(const Depsgraph &depsgraph,
187 const Sculpt &sd,
188 Object &object,
189 const Brush &brush,
190 const float4x4 &mat,
191 const float3 &offset,
192 const bke::pbvh::GridsNode &node,
193 LocalData &tls)
194{
195 SculptSession &ss = *object.sculpt;
196 const StrokeCache &cache = *ss.cache;
197 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
198
199 const Span<int> grids = node.grids();
200 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
201
202 tls.factors.resize(positions.size());
203 const MutableSpan<float> factors = tls.factors;
204 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
205 filter_region_clip_factors(ss, positions, factors);
206 if (brush.flag & BRUSH_FRONTFACE) {
207 calc_front_face(cache.view_normal_symm, subdiv_ccg, grids, factors);
208 }
209
210 tls.xy_positions.resize(positions.size());
211 tls.z_positions.resize(positions.size());
212 MutableSpan<float2> xy_positions = tls.xy_positions;
213 MutableSpan<float> z_positions = tls.z_positions;
214
215 calc_local_positions(positions, mat, xy_positions, z_positions);
216 apply_z_axis_factors(z_positions, factors);
217 apply_plane_trim_factors(brush, z_positions, factors);
218
219 tls.distances.resize(positions.size());
220 const MutableSpan<float> distances = tls.distances;
221 calc_brush_cube_distances<float2>(brush, xy_positions, distances);
222 filter_distances_with_radius(1.0f, distances, factors);
223 apply_hardness_to_distances(1.0f, cache.hardness, distances);
225 eBrushCurvePreset(brush.curve_preset), brush.curve, distances, 1.0f, factors);
226
227 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
228
229 calc_brush_texture_factors(ss, brush, positions, factors);
230
231 tls.translations.resize(positions.size());
233
234 clip_and_lock_translations(sd, ss, positions, tls.translations);
235 apply_translations(tls.translations, grids, subdiv_ccg);
236}
237
238static void calc_bmesh(const Depsgraph &depsgraph,
239 const Sculpt &sd,
240 Object &object,
241 const Brush &brush,
242 const float4x4 &mat,
243 const float3 &offset,
245 LocalData &tls)
246{
247 SculptSession &ss = *object.sculpt;
248 const StrokeCache &cache = *ss.cache;
249
251 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
252
253 tls.factors.resize(verts.size());
254 const MutableSpan<float> factors = tls.factors;
256 filter_region_clip_factors(ss, positions, factors);
257 if (brush.flag & BRUSH_FRONTFACE) {
258 calc_front_face(cache.view_normal_symm, verts, factors);
259 }
260
261 tls.xy_positions.resize(positions.size());
262 tls.z_positions.resize(positions.size());
263 MutableSpan<float2> xy_positions = tls.xy_positions;
264 MutableSpan<float> z_positions = tls.z_positions;
265
266 calc_local_positions(positions, mat, xy_positions, z_positions);
267 apply_z_axis_factors(z_positions, factors);
268 apply_plane_trim_factors(brush, z_positions, factors);
269
270 tls.distances.resize(positions.size());
271 const MutableSpan<float> distances = tls.distances;
272 calc_brush_cube_distances<float2>(brush, xy_positions, distances);
273 filter_distances_with_radius(1.0f, distances, factors);
274 apply_hardness_to_distances(1.0f, cache.hardness, distances);
276 eBrushCurvePreset(brush.curve_preset), brush.curve, distances, 1.0f, factors);
277
278 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
279
280 calc_brush_texture_factors(ss, brush, positions, factors);
281
282 tls.translations.resize(positions.size());
284
285 clip_and_lock_translations(sd, ss, positions, tls.translations);
287}
288
289} // namespace clay_strips_cc
290
291void do_clay_strips_brush(const Depsgraph &depsgraph,
292 const Sculpt &sd,
293 Object &object,
294 const IndexMask &node_mask,
295 const float3 &plane_normal,
296 const float3 &plane_center)
297{
298 SculptSession &ss = *object.sculpt;
299 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
300 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
301 const bool flip = (ss.cache->bstrength < 0.0f);
302
303 /* Note: This return has to happen *after* the call to calc_brush_plane for now, as
304 * the method is not idempotent and sets variables inside the stroke cache. */
306 return;
307 }
308
310 brush, *ss.cache, plane_normal, plane_center, flip);
311 const float3 offset = plane_normal * ss.cache->bstrength * ss.cache->radius;
312
314 switch (pbvh.type()) {
316 Mesh &mesh = *static_cast<Mesh *>(object.data);
318 const PositionDeformData position_data(depsgraph, object);
319 const MeshAttributeData attribute_data(mesh);
320 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
321 node_mask.foreach_index(GrainSize(1), [&](const int i) {
322 LocalData &tls = all_tls.local();
324 sd,
325 brush,
326 mat,
327 offset,
328 vert_normals,
329 attribute_data,
330 nodes[i],
331 object,
332 tls,
333 position_data);
334 bke::pbvh::update_node_bounds_mesh(position_data.eval, nodes[i]);
335 });
336 break;
337 }
339 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
340 MutableSpan<float3> positions = subdiv_ccg.positions;
342 node_mask.foreach_index(GrainSize(1), [&](const int i) {
343 LocalData &tls = all_tls.local();
344 calc_grids(depsgraph, sd, object, brush, mat, offset, nodes[i], tls);
345 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
346 });
347 break;
348 }
351 node_mask.foreach_index(GrainSize(1), [&](const int i) {
352 LocalData &tls = all_tls.local();
353 calc_bmesh(depsgraph, sd, object, brush, mat, offset, nodes[i], tls);
355 });
356 break;
357 }
358 }
359 pbvh.tag_positions_changed(node_mask);
361}
362
363namespace clay_strips {
364
372static bool node_in_box(const float4x4 &mat, const Bounds<float3> &bounds)
373{
374 const float3 brush_center = float3(0.0f, 0.0f, 0.5f);
375 const float3 node_center = math::transform_point(mat, (bounds.max + bounds.min) * 0.5f);
376 const float3 center_diff = brush_center - node_center;
377
378 const float3 brush_half_lengths = float3(1.0f, 1.0f, 0.5f);
379 const float3 node_half_lengths = (bounds.max - bounds.min) * 0.5f;
380
381 const float3 &node_x_axis = mat.x_axis();
382 const float3 &node_y_axis = mat.y_axis();
383 const float3 &node_z_axis = mat.z_axis();
384
385 /* Tests if `axis` separates the boxes. */
386 auto axis_separates_boxes = [&](const float3 &axis) {
387 const float radius1 = math::dot(math::abs(axis), brush_half_lengths);
388 const float radius2 = math::abs(math::dot(axis, node_x_axis)) * node_half_lengths.x +
389 math::abs(math::dot(axis, node_y_axis)) * node_half_lengths.y +
390 math::abs(math::dot(axis, node_z_axis)) * node_half_lengths.z;
391
392 const float projection = math::abs(math::dot(center_diff, axis));
393
394 return projection > radius1 + radius2;
395 };
396
397 const std::array<float3, 3> brush_axes = {
398 float3{1.0f, 0.0f, 0.0f}, float3{0.0f, 1.0f, 0.0f}, float3{0.0f, 0.0f, 1.0f}};
399 const std::array<float3, 3> node_axes = {node_x_axis, node_y_axis, node_z_axis};
400
406
407 /* 1. Test axes aligned with the region affected by the brush. */
408 for (const float3 &axis : brush_axes) {
409 if (axis_separates_boxes(axis)) {
410 return false;
411 }
412 }
413
414 /* 2. Test axes aligned with the node bounds. */
415 for (const float3 &axis : node_axes) {
416 if (axis_separates_boxes(axis)) {
417 return false;
418 }
419 }
420
421 /* 3. Test all their cross products. */
422 for (const float3 &brush_axis : brush_axes) {
423 for (const float3 &node_axis : node_axes) {
424 if (axis_separates_boxes(math::cross(brush_axis, node_axis))) {
425 return false;
426 }
427 }
428 }
429
430 /* None of the axes separates the boxes: they intersect. */
431 return true;
432}
433
435 const StrokeCache &cache,
436 const float3 &plane_normal,
437 const float3 &plane_center,
438 const bool flip)
439{
441 mat.x_axis() = math::cross(plane_normal, cache.grab_delta_symm);
442 mat.y_axis() = math::cross(plane_normal, mat.x_axis());
443 mat.z_axis() = plane_normal;
444
445 /* Flip the z-axis so that the vertices below the plane have positive z-coordinates. When the
446 * brush is inverted, the affected z-coordinates are already positive. */
447 if (!flip) {
448 mat.z_axis() *= -1.0f;
449 }
450
451 mat.location() = plane_center;
452 mat = math::normalize(mat);
453
454 /* Scale brush local space matrix. */
455 const float4x4 scale = math::from_scale<float4x4>(float3(cache.radius));
456 float4x4 tmat = mat * scale;
457 tmat.y_axis() *= brush.tip_scale_x;
458 mat = math::invert(tmat);
459 return mat;
460}
461
463 Object &object,
464 const Brush &brush,
465 IndexMaskMemory &memory)
466{
467 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
468 const SculptSession &ss = *object.sculpt;
469
470 const bool flip = (ss.cache->bstrength < 0.0f);
471 const float offset = brush_plane_offset_get(brush, ss);
472 const float displace = ss.cache->radius * (0.18f + offset) * (flip ? -1.0f : 1.0f);
473
474 /* TODO: Test to see if the sqrt2 extra factor can be removed */
475 const float initial_radius_squared = math::square(ss.cache->radius * math::numbers::sqrt2);
476
477 const bool use_original = !ss.cache->accum;
478 const IndexMask initial_node_mask = gather_nodes(pbvh,
480 use_original,
482 initial_radius_squared,
484 memory);
485
486 float3 plane_center;
487 float3 plane_normal;
488 calc_brush_plane(depsgraph, brush, object, initial_node_mask, plane_normal, plane_center);
489 plane_normal = tilt_apply_to_normal(plane_normal, *ss.cache, brush.tilt_strength_factor);
490 plane_center += plane_normal * ss.cache->scale * displace;
491
492 if (math::is_zero(ss.cache->grab_delta_symm) || math::is_zero(plane_normal)) {
493 /* The brush local matrix is degenerate: return an empty index mask. */
494 return {IndexMask(), plane_center, plane_normal};
495 }
496
497 const float4x4 mat = calc_local_matrix(brush, *ss.cache, plane_normal, plane_center, flip);
498
499 const IndexMask plane_mask = bke::pbvh::search_nodes(
500 pbvh, memory, [&](const bke::pbvh::Node &node) {
501 if (node_fully_masked_or_hidden(node)) {
502 return false;
503 }
504 return node_in_box(mat, node.bounds());
505 });
506
507 return {plane_mask, plane_center, plane_normal};
508}
509} // namespace clay_strips
510
511} // 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:1381
const Brush * BKE_paint_brush_for_read(const Paint *paint)
Definition paint.cc:641
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:559
Span< NodeT > nodes() const
void flush_bounds_to_parents()
Definition pbvh.cc:1122
void deform(MutableSpan< float3 > translations, Span< int > verts) const
Definition sculpt.cc:7443
void foreach_index(Fn &&fn) const
static float verts[][3]
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:2912
IndexMask search_nodes(const Tree &pbvh, IndexMaskMemory &memory, FunctionRef< bool(const Node &)> filter_fn)
Definition pbvh.cc:2579
void update_node_bounds_bmesh(BMeshNode &node)
Definition pbvh.cc:1110
void update_node_bounds_mesh(Span< float3 > positions, MeshNode &node)
Definition pbvh.cc:1090
Span< float3 > vert_normals_eval(const Depsgraph &depsgraph, const Object &object_orig)
Definition pbvh.cc:2435
void update_node_bounds_grids(int grid_area, Span< float3 > positions, GridsNode &node)
Definition pbvh.cc:1099
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:6351
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:7140
bool node_fully_masked_or_hidden(const bke::pbvh::Node &node)
Definition sculpt.cc:2399
void filter_distances_with_radius(float radius, Span< float > distances, MutableSpan< float > factors)
Definition sculpt.cc:7089
void filter_region_clip_factors(const SculptSession &ss, Span< float3 > vert_positions, Span< int > verts, MutableSpan< float > factors)
Definition sculpt.cc:6956
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7316
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:2483
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:2891
void apply_translations(Span< float3 > translations, Span< int > verts, MutableSpan< float3 > positions)
Definition sculpt.cc:7249
void calc_brush_texture_factors(const SculptSession &ss, const Brush &brush, Span< float3 > vert_positions, Span< int > vert, MutableSpan< float > factors)
Definition sculpt.cc:7176
float brush_plane_offset_get(const Brush &brush, const SculptSession &ss)
Definition sculpt.cc:2974
void calc_front_face(const float3 &view_normal, Span< float3 > normals, MutableSpan< float > factors)
Definition sculpt.cc:6898
void translations_from_offset_and_factors(const float3 &offset, Span< float > factors, MutableSpan< float3 > r_translations)
Definition sculpt.cc:7512
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:2671
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
int curve_preset
struct CurveMapping * curve
float tip_scale_x
float plane_trim
char falloff_shape
float tilt_strength_factor
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:437
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:415
blender::Array< blender::float3 > positions
VecBase< T, 2 > xy() const
std::unique_ptr< auto_mask::Cache > automasking
i
Definition text_draw.cc:230