Blender V4.5
plane.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
20
22
23#include "DNA_brush_types.h"
24#include "DNA_mesh_types.h"
25#include "DNA_object_types.h"
26#include "DNA_scene_types.h"
27
28#include "BKE_brush.hh"
29#include "BKE_mesh.hh"
30#include "BKE_paint.hh"
31#include "BKE_paint_bvh.hh"
32#include "BKE_subdiv_ccg.hh"
33
35#include "BLI_math_matrix.hh"
36#include "BLI_task.hh"
37
41
42#include "bmesh.hh"
43
45
46inline namespace plane_cc {
47
55
56static void calc_local_positions(const float4x4 &mat,
57 const Span<int> verts,
58 const Span<float3> positions,
59 const MutableSpan<float3> local_positions)
60{
61 for (const int i : verts.index_range()) {
62 local_positions[i] = math::transform_point(mat, positions[verts[i]]);
63 }
64}
65
66static void calc_local_positions(const float4x4 &mat,
67 const Span<float3> positions,
68 const MutableSpan<float3> local_positions)
69{
70 for (const int i : positions.index_range()) {
71 local_positions[i] = math::transform_point(mat, positions[i]);
72 }
73}
74
87static void calc_local_distances(const float height,
88 const float depth,
89 const MutableSpan<float3> local_positions,
90 const MutableSpan<float> distances)
91{
92 if (height != 0.0f) {
93 const float height_rcp = math::rcp(height);
94
95 for (const int i : local_positions.index_range()) {
96 const float3 &position = local_positions[i];
97 if (position.z >= 0.0f) {
98 distances[i] = math::length(float3(position.x, position.y, position.z * height_rcp));
99 }
100 }
101 }
102 else {
103 for (const int i : local_positions.index_range()) {
104 if (local_positions[i].z >= 0.0f) {
105 distances[i] = 1.0f;
106 }
107 }
108 }
109
110 if (depth != 0.0f) {
111 const float depth_rcp = math::rcp(depth);
112
113 for (const int i : local_positions.index_range()) {
114 const float3 &position = local_positions[i];
115 if (position.z < 0.0f) {
116 distances[i] = math::length(float3(position.x, position.y, position.z * depth_rcp));
117 }
118 }
119 }
120 else {
121 for (const int i : local_positions.index_range()) {
122 if (local_positions[i].z < 0.0f) {
123 distances[i] = 1.0f;
124 }
125 }
126 }
127}
128
129/*
130 * Scales factors by `height` (if local z > 0) or `depth` (if local z < 0).
131 * This is necessary to "normalize" the strength contribute given by the local z distance.
132 *
133 * Note that if `height = 0`, the falloff strength of the vertices
134 * above the plane is 0 (see #calc_local_distances), hence
135 * the factor for such vertices is already 0.
136 *
137 * The same is true for vertices below the plane if `depth` = 0.
138 */
139static void scale_factors_by_height_and_depth(const float height,
140 const float depth,
141 const MutableSpan<float3> local_positions,
142 const MutableSpan<float> factors)
143{
144 if (!ELEM(height, 1.0f, 0.0f)) {
145 for (const int i : factors.index_range()) {
146 if (local_positions[i].z > 0.0f) {
147 factors[i] *= height;
148 }
149 }
150 }
151
152 if (!ELEM(depth, 0.0f, 1.0f)) {
153 for (const int i : factors.index_range()) {
154 if (local_positions[i].z < 0.0f) {
155 factors[i] *= depth;
156 }
157 }
158 }
159}
160
161/*
162 * Computes the translation vectors for the Plane brush.
163 *
164 * The translation of a vertex with index `i`, position `P`, and plane projection `Q`
165 * is determined by the vector `PQ` scaled by `factors[i]` and `strength`.
166 *
167 * In local (brush) space, `PQ` is given by:
168 * `PQ = Q - P = (x, y, 0) - (x, y, z) = (0, 0, -z)`
169 *
170 * Therefore, the translation in object space is:
171 * `T = A * (0, 0, -z) * factors[i] * strength`
172 *
173 * where `A` is the 3x3 local-to-object transformation matrix.
174 *
175 * Given how the local space is defined, `A * (0, 0, -z)` simplifies to:
176 * `-z * radius * plane_normal`
177 *
178 * Substituting this back, the translation becomes:
179 * `T = -z * radius * plane_normal * factors[i] * strength`
180 * which is equal to:
181 * `(factors[i] * z) * (-plane_normal * radius * strength)`
182 */
183static void calc_translations(const float3 &plane_normal,
184 const float radius,
185 const float strength,
186 const MutableSpan<float3> local_positions,
187 const MutableSpan<float> factors,
188 const MutableSpan<float3> r_translations)
189{
190 for (const int i : local_positions.index_range()) {
191 factors[i] *= local_positions[i].z;
192 }
193
194 const float3 &offset = -plane_normal * radius * strength;
195 translations_from_offset_and_factors(offset, factors, r_translations);
196}
197
198static void calc_faces(const Depsgraph &depsgraph,
199 const Sculpt &sd,
200 const Brush &brush,
201 const float4x4 &mat,
202 const float3 &plane_normal,
203 const float strength,
204 const float height,
205 const float depth,
206 const MeshAttributeData &attribute_data,
207 const Span<float3> vert_normals,
208 const bke::pbvh::MeshNode &node,
209 Object &object,
210 LocalData &tls,
211 const PositionDeformData &position_data)
212{
213 const SculptSession &ss = *object.sculpt;
214 const StrokeCache &cache = *ss.cache;
215
216 const Span<int> verts = node.verts();
217
218 tls.factors.resize(verts.size());
219 const MutableSpan<float> factors = tls.factors;
220 fill_factor_from_hide_and_mask(attribute_data.hide_vert, attribute_data.mask, verts, factors);
221 filter_region_clip_factors(ss, position_data.eval, verts, factors);
222
223 if (brush.flag & BRUSH_FRONTFACE) {
224 calc_front_face(cache.view_normal_symm, vert_normals, verts, factors);
225 }
226
227 tls.positions.resize(verts.size());
228 const MutableSpan<float3> local_positions = tls.positions;
229 calc_local_positions(mat, verts, position_data.eval, local_positions);
230
231 tls.distances.resize(verts.size());
232 const MutableSpan<float> distances = tls.distances;
233 calc_local_distances(height, depth, local_positions, distances);
234 filter_distances_with_radius(1.0f, distances, factors);
235
236 apply_hardness_to_distances(1.0f, cache.hardness, distances);
238 eBrushCurvePreset(brush.curve_preset), brush.curve, distances, 1.0f, factors);
239
240 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
241
242 calc_brush_texture_factors(ss, brush, position_data.eval, verts, factors);
243
244 tls.translations.resize(verts.size());
245 const MutableSpan<float3> translations = tls.translations;
246 scale_factors_by_height_and_depth(height, depth, local_positions, factors);
247 calc_translations(plane_normal, cache.radius, strength, local_positions, factors, translations);
248
249 clip_and_lock_translations(sd, ss, position_data.eval, verts, translations);
250 position_data.deform(translations, verts);
251}
252
253static void calc_grids(const Depsgraph &depsgraph,
254 const Sculpt &sd,
255 Object &object,
256 const Brush &brush,
257 const float4x4 &mat,
258 const float3 &plane_normal,
259 const float strength,
260 const float height,
261 const float depth,
263 LocalData &tls)
264{
265 SculptSession &ss = *object.sculpt;
266 const StrokeCache &cache = *ss.cache;
267 SubdivCCG &subdiv_ccg = *ss.subdiv_ccg;
268
269 const Span<int> grids = node.grids();
270 const MutableSpan positions = gather_grids_positions(subdiv_ccg, grids, tls.positions);
271
272 tls.factors.resize(positions.size());
273 const MutableSpan<float> factors = tls.factors;
274 fill_factor_from_hide_and_mask(subdiv_ccg, grids, factors);
275 filter_region_clip_factors(ss, positions, factors);
276
277 if (brush.flag & BRUSH_FRONTFACE) {
278 calc_front_face(cache.view_normal_symm, subdiv_ccg, grids, factors);
279 }
280
281 tls.local_positions.resize(positions.size());
282 const MutableSpan<float3> local_positions = tls.local_positions;
283 calc_local_positions(mat, positions, local_positions);
284
285 tls.distances.resize(positions.size());
286 const MutableSpan<float> distances = tls.distances;
287 calc_local_distances(height, depth, local_positions, distances);
288 filter_distances_with_radius(1.0f, distances, factors);
289
290 apply_hardness_to_distances(1.0f, cache.hardness, distances);
292 eBrushCurvePreset(brush.curve_preset), brush.curve, distances, 1.0f, factors);
293
294 auto_mask::calc_grids_factors(depsgraph, object, cache.automasking.get(), node, grids, factors);
295
296 calc_brush_texture_factors(ss, brush, positions, factors);
297
298 tls.translations.resize(positions.size());
299 const MutableSpan<float3> translations = tls.translations;
300 scale_factors_by_height_and_depth(height, depth, local_positions, factors);
301 calc_translations(plane_normal, cache.radius, strength, local_positions, factors, translations);
302
303 clip_and_lock_translations(sd, ss, positions, translations);
304 apply_translations(translations, grids, subdiv_ccg);
305}
306
307static void calc_bmesh(const Depsgraph &depsgraph,
308 const Sculpt &sd,
309 Object &object,
310 const Brush &brush,
311 const float4x4 &mat,
312 const float3 &plane_normal,
313 const float strength,
314 const float height,
315 const float depth,
317 LocalData &tls)
318{
319 SculptSession &ss = *object.sculpt;
320 const StrokeCache &cache = *ss.cache;
321
323 const MutableSpan positions = gather_bmesh_positions(verts, tls.positions);
324
325 tls.factors.resize(verts.size());
326 const MutableSpan<float> factors = tls.factors;
328 filter_region_clip_factors(ss, positions, factors);
329 if (brush.flag & BRUSH_FRONTFACE) {
330 calc_front_face(cache.view_normal_symm, verts, factors);
331 }
332
333 tls.local_positions.resize(positions.size());
334 const MutableSpan<float3> local_positions = tls.local_positions;
335 calc_local_positions(mat, positions, local_positions);
336
337 tls.distances.resize(positions.size());
338 const MutableSpan<float> distances = tls.distances;
339 calc_local_distances(height, depth, local_positions, distances);
340 filter_distances_with_radius(1.0f, distances, factors);
341
342 apply_hardness_to_distances(1.0f, cache.hardness, distances);
344 eBrushCurvePreset(brush.curve_preset), brush.curve, distances, 1.0f, factors);
345
346 auto_mask::calc_vert_factors(depsgraph, object, cache.automasking.get(), node, verts, factors);
347
348 calc_brush_texture_factors(ss, brush, positions, factors);
349
350 tls.translations.resize(positions.size());
351 const MutableSpan<float3> translations = tls.translations;
352 scale_factors_by_height_and_depth(height, depth, local_positions, factors);
353 calc_translations(plane_normal, cache.radius, strength, local_positions, factors, translations);
354
355 clip_and_lock_translations(sd, ss, positions, translations);
356 apply_translations(translations, verts);
357}
358
359} // namespace plane_cc
360
361void do_plane_brush(const Depsgraph &depsgraph,
362 const Sculpt &sd,
363 Object &object,
364 const IndexMask &node_mask,
365 const float3 &plane_normal,
366 const float3 &plane_center)
367{
368 const SculptSession &ss = *object.sculpt;
369 bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(object);
370 const Brush &brush = *BKE_paint_brush_for_read(&sd.paint);
371
373 return;
374 }
375
376 float3 normal = plane_normal;
377 float3 center = plane_center;
378
379 normal = tilt_apply_to_normal(normal, *ss.cache, brush.tilt_strength_factor);
380
381 const bool flip = ss.cache->initial_direction_flipped;
382 const float offset = brush_plane_offset_get(brush, ss);
383 const float displace = ss.cache->radius * offset * (flip ? -1.0f : 1.0f);
384 center += normal * ss.cache->scale * displace;
385
387 mat.x_axis() = math::cross(normal, ss.cache->grab_delta_symm);
388 mat.y_axis() = math::cross(normal, mat.x_axis());
389 mat.z_axis() = normal;
390 mat.location() = center;
391 mat = math::normalize(mat);
392
394 float4x4 tmat = mat * scale;
395
396 mat = math::invert(tmat);
397
398 float strength = ss.cache->bstrength;
399 float height = brush.plane_height;
400 float depth = brush.plane_depth;
401
402 if (flip) {
403 switch (brush.plane_inversion_mode) {
405 strength *= -1.0f;
406 break;
407 }
409 std::swap(height, depth);
410 break;
411 }
412 }
413 }
414
416 switch (pbvh.type()) {
418 const Mesh &mesh = *static_cast<Mesh *>(object.data);
419 const MeshAttributeData attribute_data(mesh);
420 const PositionDeformData position_data(depsgraph, object);
421 const Span<float3> vert_normals = bke::pbvh::vert_normals_eval(depsgraph, object);
423 node_mask.foreach_index(GrainSize(1), [&](const int i) {
424 LocalData &tls = all_tls.local();
426 sd,
427 brush,
428 mat,
429 normal,
430 strength,
431 height,
432 depth,
433 attribute_data,
434 vert_normals,
435 nodes[i],
436 object,
437 tls,
438 position_data);
440 });
441 break;
442 }
444 SubdivCCG &subdiv_ccg = *object.sculpt->subdiv_ccg;
445 MutableSpan<float3> positions = subdiv_ccg.positions;
447 node_mask.foreach_index(GrainSize(1), [&](const int i) {
448 LocalData &tls = all_tls.local();
450 depsgraph, sd, object, brush, mat, normal, strength, height, depth, nodes[i], tls);
451 bke::pbvh::update_node_bounds_grids(subdiv_ccg.grid_area, positions, nodes[i]);
452 });
453 break;
454 }
457 node_mask.foreach_index(GrainSize(1), [&](const int i) {
458 LocalData &tls = all_tls.local();
460 depsgraph, sd, object, brush, mat, normal, strength, height, depth, nodes[i], tls);
462 });
463 break;
464 }
465 }
466 pbvh.tag_positions_changed(node_mask);
468}
469
470namespace plane {
472 Object &ob,
473 const Brush &brush,
474 IndexMaskMemory &memory)
475{
476 const SculptSession &ss = *ob.sculpt;
477 const bke::pbvh::Tree &pbvh = *bke::object::pbvh_get(ob);
478
479 const bool use_original = !ss.cache->accum;
480 const IndexMask initial_node_mask = gather_nodes(pbvh,
482 use_original,
486 memory);
487
488 float3 plane_center;
489 float3 plane_normal;
490 calc_brush_plane(depsgraph, brush, ob, initial_node_mask, plane_normal, plane_center);
491
492 /* Recompute the node mask using the center of the brush plane as the center.
493 *
494 * The indices of the nodes in `cursor_node_mask` have been calculated based on the cursor
495 * location. However, for the Plane brush, its effective center often deviates from the cursor
496 * location. Calculating the affected nodes using the cursor location as the center can lead to
497 * issues (see, for example, #123768). */
498 const IndexMask plane_mask = bke::pbvh::search_nodes(
499 pbvh, memory, [&](const bke::pbvh::Node &node) {
500 if (node_fully_masked_or_hidden(node)) {
501 return false;
502 }
503 return node_in_sphere(node, plane_center, ss.cache->radius_squared, use_original);
504 });
505
506 return {plane_mask, plane_center, plane_normal};
507}
508} // namespace plane
509
510} // 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 ELEM(...)
@ BRUSH_PLANE_INVERT_DISPLACEMENT
@ BRUSH_PLANE_SWAP_HEIGHT_AND_DEPTH
eBrushCurvePreset
@ BRUSH_FRONTFACE
eBrushFalloffShape
Object is a sort of wrapper for general info.
BPy_StructRNA * depsgraph
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
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 IndexRange index_range() const
Definition BLI_span.hh:401
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:7445
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 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_translations(const float3 &plane_normal, const float radius, const float strength, const MutableSpan< float3 > local_positions, const MutableSpan< float > factors, const MutableSpan< float3 > r_translations)
Definition plane.cc:183
static void scale_factors_by_height_and_depth(const float height, const float depth, const MutableSpan< float3 > local_positions, const MutableSpan< float > factors)
Definition plane.cc:139
static void calc_grids(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float4x4 &mat, const float3 &plane_normal, const float strength, const float height, const float depth, bke::pbvh::GridsNode &node, LocalData &tls)
Definition plane.cc:253
static void calc_local_positions(const float4x4 &mat, const Span< int > verts, const Span< float3 > positions, const MutableSpan< float3 > local_positions)
Definition plane.cc:56
static void calc_local_distances(const float height, const float depth, const MutableSpan< float3 > local_positions, const MutableSpan< float > distances)
Definition plane.cc:87
static void calc_bmesh(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const Brush &brush, const float4x4 &mat, const float3 &plane_normal, const float strength, const float height, const float depth, bke::pbvh::BMeshNode &node, LocalData &tls)
Definition plane.cc:307
static void calc_faces(const Depsgraph &depsgraph, const Sculpt &sd, const Brush &brush, const float4x4 &mat, const float3 &plane_normal, const float strength, const float height, const float depth, const MeshAttributeData &attribute_data, const Span< float3 > vert_normals, const bke::pbvh::MeshNode &node, Object &object, LocalData &tls, const PositionDeformData &position_data)
Definition plane.cc:198
CursorSampleResult calc_node_mask(const Depsgraph &depsgraph, Object &ob, const Brush &brush, IndexMaskMemory &memory)
Definition plane.cc:471
void do_plane_brush(const Depsgraph &depsgraph, const Sculpt &sd, Object &object, const IndexMask &node_mask, const float3 &plane_normal, const float3 &plane_center)
Definition plane.cc:361
MutableSpan< float3 > gather_grids_positions(const SubdivCCG &subdiv_ccg, const Span< int > grids, Vector< float3 > &positions)
bool node_in_sphere(const bke::pbvh::Node &node, const float3 &location, const float radius_sq, const bool original)
Definition sculpt.cc:2410
void gather_bmesh_positions(const Set< BMVert *, 0 > &verts, MutableSpan< float3 > positions)
Definition sculpt.cc:6353
void apply_hardness_to_distances(float radius, float hardness, MutableSpan< float > distances)
Definition sculpt.cc:7142
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:7091
void filter_region_clip_factors(const SculptSession &ss, Span< float3 > vert_positions, Span< int > verts, MutableSpan< float > factors)
Definition sculpt.cc:6958
void clip_and_lock_translations(const Sculpt &sd, const SculptSession &ss, Span< float3 > positions, Span< int > verts, MutableSpan< float3 > translations)
Definition sculpt.cc:7318
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:7251
void calc_brush_texture_factors(const SculptSession &ss, const Brush &brush, Span< float3 > vert_positions, Span< int > vert, MutableSpan< float > factors)
Definition sculpt.cc:7178
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:6900
void translations_from_offset_and_factors(const float3 &offset, Span< float > factors, MutableSpan< float3 > r_translations)
Definition sculpt.cc:7523
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 length(const VecBase< T, Size > &a)
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)
T rcp(const T &a)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
MatBase< float, 4, 4 > float4x4
VecBase< float, 3 > float3
int plane_inversion_mode
int curve_preset
float plane_depth
struct CurveMapping * curve
char falloff_shape
float tilt_strength_factor
float plane_height
struct SculptSession * sculpt
blender::ed::sculpt_paint::StrokeCache * cache
Definition BKE_paint.hh:437
SubdivCCG * subdiv_ccg
Definition BKE_paint.hh:415
blender::Array< blender::float3 > positions
std::unique_ptr< auto_mask::Cache > automasking
i
Definition text_draw.cc:230