Blender V4.3
geometry_component_curves.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_task.hh"
6
7#include "DNA_ID_enums.h"
8#include "DNA_curve_types.h"
9
10#include "BKE_attribute_math.hh"
11#include "BKE_curves.hh"
12#include "BKE_deform.hh"
14#include "BKE_geometry_set.hh"
15#include "BKE_lib_id.hh"
16
18
20
21namespace blender::bke {
22
23/* -------------------------------------------------------------------- */
28
30 : GeometryComponent(Type::Curve), curves_(curve), ownership_(ownership)
31{
32}
33
38
40{
41 CurveComponent *new_component = new CurveComponent();
42 if (curves_ != nullptr) {
43 new_component->curves_ = BKE_curves_copy_for_eval(curves_);
44 new_component->ownership_ = GeometryOwnershipType::Owned;
45 }
46 return GeometryComponentPtr(new_component);
47}
48
50{
51 BLI_assert(this->is_mutable() || this->is_expired());
52 if (curves_ != nullptr) {
53 if (ownership_ == GeometryOwnershipType::Owned) {
54 BKE_id_free(nullptr, curves_);
55 }
56 if (curve_for_render_ != nullptr) {
57 /* The curve created by this component should not have any edit mode data. */
58 BLI_assert(curve_for_render_->editfont == nullptr && curve_for_render_->editnurb == nullptr);
59 BKE_id_free(nullptr, curve_for_render_);
60 curve_for_render_ = nullptr;
61 }
62
63 curves_ = nullptr;
64 }
65}
66
68{
69 return curves_ != nullptr;
70}
71
73{
74 BLI_assert(this->is_mutable());
75 this->clear();
76 curves_ = curves;
77 ownership_ = ownership;
78}
79
81{
82 BLI_assert(this->is_mutable());
83 Curves *curves = curves_;
84 curves_ = nullptr;
85 return curves;
86}
87
89{
90 return curves_;
91}
92
94{
95 BLI_assert(this->is_mutable());
96 if (ownership_ == GeometryOwnershipType::ReadOnly) {
97 curves_ = BKE_curves_copy_for_eval(curves_);
99 }
100 return curves_;
101}
102
104{
105 return curves_ == nullptr;
106}
107
109{
110 return ownership_ == GeometryOwnershipType::Owned;
111}
112
114{
115 BLI_assert(this->is_mutable());
116 if (ownership_ != GeometryOwnershipType::Owned) {
117 if (curves_) {
118 curves_ = BKE_curves_copy_for_eval(curves_);
119 }
120 ownership_ = GeometryOwnershipType::Owned;
121 }
122}
123
125{
126 if (curves_) {
127 curves_->geometry.wrap().count_memory(memory);
128 }
129}
130
132{
133 if (curves_ == nullptr) {
134 return nullptr;
135 }
136 if (curve_for_render_ != nullptr) {
137 return curve_for_render_;
138 }
139 std::lock_guard lock{curve_for_render_mutex_};
140 if (curve_for_render_ != nullptr) {
141 return curve_for_render_;
142 }
143
144 curve_for_render_ = (Curve *)BKE_id_new_nomain(ID_CU_LEGACY, nullptr);
145 curve_for_render_->curve_eval = curves_;
146
147 return curve_for_render_;
148}
149
152/* -------------------------------------------------------------------- */
157{
158 const OffsetIndices points_by_curve = curves.points_by_curve();
159 const OffsetIndices evaluated_points_by_curve = curves.evaluated_points_by_curve();
160 const VArray<int8_t> types = curves.curve_types();
161 const VArray<int> resolutions = curves.resolution();
162 const VArray<bool> curves_cyclic = curves.cyclic();
163 const AttributeAccessor attributes = curves.attributes();
164 const VArray<float3> custom_normals = *attributes.lookup_or_default<float3>(
165 "custom_normal", AttrDomain::Point, float3(0, 0, 1));
166
167 const Span<float3> positions = curves.positions();
168 const VArray<int8_t> normal_modes = curves.normal_mode();
169
170 const Span<float3> evaluated_normals = curves.evaluated_normals();
171
172 Array<float3> results(curves.points_num());
173
174 threading::parallel_for(curves.curves_range(), 128, [&](IndexRange range) {
175 Vector<float3> nurbs_tangents;
176
177 for (const int i_curve : range) {
178 const IndexRange points = points_by_curve[i_curve];
179 const IndexRange evaluated_points = evaluated_points_by_curve[i_curve];
180
181 MutableSpan<float3> curve_normals = results.as_mutable_span().slice(points);
182
183 switch (types[i_curve]) {
184 case CURVE_TYPE_CATMULL_ROM: {
185 const Span<float3> normals = evaluated_normals.slice(evaluated_points);
186 const int resolution = resolutions[i_curve];
187 for (const int i : IndexRange(points.size())) {
188 curve_normals[i] = normals[resolution * i];
189 }
190 break;
191 }
192 case CURVE_TYPE_POLY:
193 curve_normals.copy_from(evaluated_normals.slice(evaluated_points));
194 break;
195 case CURVE_TYPE_BEZIER: {
196 const Span<float3> normals = evaluated_normals.slice(evaluated_points);
197 curve_normals.first() = normals.first();
198 const Span<int> offsets = curves.bezier_evaluated_offsets_for_curve(i_curve);
199 for (const int i : IndexRange(points.size()).drop_front(1)) {
200 curve_normals[i] = normals[offsets[i]];
201 }
202 break;
203 }
204 case CURVE_TYPE_NURBS: {
205 /* For NURBS curves there is no obvious correspondence between specific evaluated points
206 * and control points, so normals are determined by treating them as poly curves. */
207 nurbs_tangents.clear();
208 nurbs_tangents.resize(points.size());
209 const bool cyclic = curves_cyclic[i_curve];
210 const Span<float3> curve_positions = positions.slice(points);
211 curves::poly::calculate_tangents(curve_positions, cyclic, nurbs_tangents);
212 switch (NormalMode(normal_modes[i_curve])) {
213 case NORMAL_MODE_Z_UP:
214 curves::poly::calculate_normals_z_up(nurbs_tangents, curve_normals);
215 break;
216 case NORMAL_MODE_MINIMUM_TWIST:
217 curves::poly::calculate_normals_minimum(nurbs_tangents, cyclic, curve_normals);
218 break;
219 case NORMAL_MODE_FREE:
220 custom_normals.materialize(points, curve_normals);
221 break;
222 }
223 break;
224 }
225 }
226 }
227 });
228 return results;
229}
230
232{
233 const VArray<int8_t> types = curves.curve_types();
234 if (curves.is_single_type(CURVE_TYPE_POLY)) {
235 return curves.adapt_domain<float3>(
236 VArray<float3>::ForSpan(curves.evaluated_normals()), AttrDomain::Point, domain);
237 }
238
240
241 if (domain == AttrDomain::Point) {
242 return VArray<float3>::ForContainer(std::move(normals));
243 }
244
245 if (domain == AttrDomain::Curve) {
246 return curves.adapt_domain<float3>(
247 VArray<float3>::ForContainer(std::move(normals)), AttrDomain::Point, AttrDomain::Curve);
248 }
249
250 return nullptr;
251}
252
255/* -------------------------------------------------------------------- */
260 const AttrDomain domain)
261{
262 curves.ensure_evaluated_lengths();
263
264 VArray<bool> cyclic = curves.cyclic();
266 curves.curves_num(), [&curves, cyclic = std::move(cyclic)](int64_t index) {
267 return curves.evaluated_length_total_for_curve(index, cyclic[index]);
268 });
269
270 if (domain == AttrDomain::Curve) {
271 return lengths;
272 }
273
274 if (domain == AttrDomain::Point) {
275 return curves.adapt_domain<float>(std::move(lengths), AttrDomain::Curve, AttrDomain::Point);
276 }
277
278 return {};
279}
280
281CurveLengthFieldInput::CurveLengthFieldInput()
282 : CurvesFieldInput(CPPType::get<float>(), "Spline Length node")
283{
285}
286
288 const AttrDomain domain,
289 const IndexMask & /*mask*/) const
290{
291 return construct_curve_length_gvarray(curves, domain);
292}
293
295{
296 /* Some random constant hash. */
297 return 3549623580;
298}
299
301{
302 return dynamic_cast<const CurveLengthFieldInput *>(&other) != nullptr;
303}
304
306 const CurvesGeometry & /*curves*/) const
307{
308 return AttrDomain::Curve;
309}
310
313/* -------------------------------------------------------------------- */
317static void tag_component_topology_changed(void *owner)
318{
319 CurvesGeometry &curves = *static_cast<CurvesGeometry *>(owner);
320 curves.tag_topology_changed();
321}
322
323static void tag_component_curve_types_changed(void *owner)
324{
325 CurvesGeometry &curves = *static_cast<CurvesGeometry *>(owner);
326 curves.update_curve_types();
327 curves.tag_topology_changed();
328}
329
330static void tag_component_positions_changed(void *owner)
331{
332 CurvesGeometry &curves = *static_cast<CurvesGeometry *>(owner);
333 curves.tag_positions_changed();
334}
335
336static void tag_component_radii_changed(void *owner)
337{
338 CurvesGeometry &curves = *static_cast<CurvesGeometry *>(owner);
339 curves.tag_radii_changed();
340}
341
342static void tag_component_normals_changed(void *owner)
343{
344 CurvesGeometry &curves = *static_cast<CurvesGeometry *>(owner);
345 curves.tag_normals_changed();
346}
347
350/* -------------------------------------------------------------------- */
358 public:
359 GAttributeReader try_get_for_read(const void *owner, const StringRef attribute_id) const final
360 {
361 if (bke::attribute_name_is_anonymous(attribute_id)) {
362 return {};
363 }
364 const CurvesGeometry *curves = static_cast<const CurvesGeometry *>(owner);
365 if (curves == nullptr) {
366 return {};
367 }
368 const int vertex_group_index = BKE_defgroup_name_index(&curves->vertex_group_names,
369 attribute_id);
370 if (vertex_group_index < 0) {
371 return {};
372 }
373 const Span<MDeformVert> dverts = curves->deform_verts();
374 return this->get_for_vertex_group_index(*curves, dverts, vertex_group_index);
375 }
376
378 const Span<MDeformVert> dverts,
379 const int vertex_group_index) const
380 {
381 BLI_assert(vertex_group_index >= 0);
382 if (dverts.is_empty()) {
383 return {VArray<float>::ForSingle(0.0f, curves.points_num()), AttrDomain::Point};
384 }
385 return {varray_for_deform_verts(dverts, vertex_group_index), AttrDomain::Point};
386 }
387
388 GAttributeWriter try_get_for_write(void *owner, const StringRef attribute_id) const final
389 {
390 if (bke::attribute_name_is_anonymous(attribute_id)) {
391 return {};
392 }
393 CurvesGeometry *curves = static_cast<CurvesGeometry *>(owner);
394 if (curves == nullptr) {
395 return {};
396 }
397 const int vertex_group_index = BKE_defgroup_name_index(&curves->vertex_group_names,
398 attribute_id);
399 if (vertex_group_index < 0) {
400 return {};
401 }
402 MutableSpan<MDeformVert> dverts = curves->deform_verts_for_write();
403 return {varray_for_mutable_deform_verts(dverts, vertex_group_index), AttrDomain::Point};
404 }
405
406 bool try_delete(void *owner, const StringRef attribute_id) const final
407 {
408 if (bke::attribute_name_is_anonymous(attribute_id)) {
409 return false;
410 }
411 CurvesGeometry *curves = static_cast<CurvesGeometry *>(owner);
412 if (curves == nullptr) {
413 return true;
414 }
415 const std::string name = attribute_id;
416
417 int index;
418 bDeformGroup *group;
420 &curves->vertex_group_names, name.c_str(), &index, &group))
421 {
422 return false;
423 }
424 BLI_remlink(&curves->vertex_group_names, group);
425 MEM_freeN(group);
426 if (curves->deform_verts().is_empty()) {
427 return true;
428 }
429
430 MutableSpan<MDeformVert> dverts = curves->deform_verts_for_write();
431 remove_defgroup_index(dverts, index);
432 return true;
433 }
434
435 bool foreach_attribute(const void *owner,
436 FunctionRef<void(const AttributeIter &)> fn) const final
437 {
438 const CurvesGeometry *curves = static_cast<const CurvesGeometry *>(owner);
439 if (curves == nullptr) {
440 return true;
441 }
442 const Span<MDeformVert> dverts = curves->deform_verts();
443
444 int group_index = 0;
445 LISTBASE_FOREACH_INDEX (const bDeformGroup *, group, &curves->vertex_group_names, group_index)
446 {
447 const auto get_fn = [&]() {
448 return this->get_for_vertex_group_index(*curves, dverts, group_index);
449 };
450 AttributeIter iter{group->name, AttrDomain::Point, CD_PROP_FLOAT, get_fn};
451 fn(iter);
452 if (iter.is_stopped()) {
453 return false;
454 }
455 }
456 return true;
457 }
458
459 void foreach_domain(const FunctionRef<void(AttrDomain)> callback) const final
460 {
462 }
463};
464
470{
471 static CustomDataAccessInfo curve_access = {
472 [](void *owner) -> CustomData * {
473 CurvesGeometry &curves = *static_cast<CurvesGeometry *>(owner);
474 return &curves.curve_data;
475 },
476 [](const void *owner) -> const CustomData * {
477 const CurvesGeometry &curves = *static_cast<const CurvesGeometry *>(owner);
478 return &curves.curve_data;
479 },
480 [](const void *owner) -> int {
481 const CurvesGeometry &curves = *static_cast<const CurvesGeometry *>(owner);
482 return curves.curves_num();
483 }};
484 static CustomDataAccessInfo point_access = {
485 [](void *owner) -> CustomData * {
486 CurvesGeometry &curves = *static_cast<CurvesGeometry *>(owner);
487 return &curves.point_data;
488 },
489 [](const void *owner) -> const CustomData * {
490 const CurvesGeometry &curves = *static_cast<const CurvesGeometry *>(owner);
491 return &curves.point_data;
492 },
493 [](const void *owner) -> int {
494 const CurvesGeometry &curves = *static_cast<const CurvesGeometry *>(owner);
495 return curves.points_num();
496 }};
497
498 static BuiltinCustomDataLayerProvider position("position",
502 point_access,
504
505 static BuiltinCustomDataLayerProvider radius("radius",
509 point_access,
511
512 static BuiltinCustomDataLayerProvider id("id",
516 point_access,
517 nullptr);
518
519 static BuiltinCustomDataLayerProvider tilt("tilt",
523 point_access,
525
526 static BuiltinCustomDataLayerProvider handle_right("handle_right",
530 point_access,
532
533 static BuiltinCustomDataLayerProvider handle_left("handle_left",
537 point_access,
539
540 static auto handle_type_clamp = mf::build::SI1_SO<int8_t, int8_t>(
541 "Handle Type Validate",
542 [](int8_t value) {
543 return std::clamp<int8_t>(value, BEZIER_HANDLE_FREE, BEZIER_HANDLE_ALIGN);
544 },
545 mf::build::exec_presets::AllSpanOrSingle());
546 static BuiltinCustomDataLayerProvider handle_type_right("handle_type_right",
550 point_access,
552 AttributeValidator{&handle_type_clamp});
553
554 static BuiltinCustomDataLayerProvider handle_type_left("handle_type_left",
558 point_access,
560 AttributeValidator{&handle_type_clamp});
561
562 static BuiltinCustomDataLayerProvider nurbs_weight("nurbs_weight",
566 point_access,
568
569 static const auto nurbs_order_clamp = mf::build::SI1_SO<int8_t, int8_t>(
570 "NURBS Order Validate",
571 [](int8_t value) { return std::max<int8_t>(value, 1); },
572 mf::build::exec_presets::AllSpanOrSingle());
573 static int nurbs_order_default = 4;
574 static BuiltinCustomDataLayerProvider nurbs_order("nurbs_order",
578 curve_access,
580 AttributeValidator{&nurbs_order_clamp},
581 &nurbs_order_default);
582
583 static const auto normal_mode_clamp = mf::build::SI1_SO<int8_t, int8_t>(
584 "Normal Mode Validate",
585 [](int8_t value) {
586 return std::clamp<int8_t>(value, NORMAL_MODE_MINIMUM_TWIST, NORMAL_MODE_FREE);
587 },
588 mf::build::exec_presets::AllSpanOrSingle());
589 static BuiltinCustomDataLayerProvider normal_mode("normal_mode",
593 curve_access,
595 AttributeValidator{&normal_mode_clamp});
596
597 static BuiltinCustomDataLayerProvider custom_normal("custom_normal",
601 point_access,
603
604 static const auto knots_mode_clamp = mf::build::SI1_SO<int8_t, int8_t>(
605 "Knots Mode Validate",
606 [](int8_t value) {
607 return std::clamp<int8_t>(value, NURBS_KNOT_MODE_NORMAL, NURBS_KNOT_MODE_ENDPOINT_BEZIER);
608 },
609 mf::build::exec_presets::AllSpanOrSingle());
610 static BuiltinCustomDataLayerProvider nurbs_knots_mode("knots_mode",
614 curve_access,
616 AttributeValidator{&knots_mode_clamp});
617
618 static const auto curve_type_clamp = mf::build::SI1_SO<int8_t, int8_t>(
619 "Curve Type Validate",
620 [](int8_t value) {
621 return std::clamp<int8_t>(value, CURVE_TYPE_CATMULL_ROM, CURVE_TYPES_NUM);
622 },
623 mf::build::exec_presets::AllSpanOrSingle());
624 static BuiltinCustomDataLayerProvider curve_type("curve_type",
628 curve_access,
630 AttributeValidator{&curve_type_clamp});
631
632 static const auto resolution_clamp = mf::build::SI1_SO<int, int>(
633 "Resolution Validate",
634 [](int value) { return std::max<int>(value, 1); },
635 mf::build::exec_presets::AllSpanOrSingle());
636 static int resolution_default = 12;
637 static BuiltinCustomDataLayerProvider resolution("resolution",
641 curve_access,
643 AttributeValidator{&resolution_clamp},
644 &resolution_default);
645
646 static BuiltinCustomDataLayerProvider cyclic("cyclic",
650 curve_access,
652
653 static CurvesVertexGroupsAttributeProvider vertex_groups;
654 static CustomDataAttributeProvider curve_custom_data(AttrDomain::Curve, curve_access);
655 static CustomDataAttributeProvider point_custom_data(AttrDomain::Point, point_access);
656
657 return ComponentAttributeProviders({&position,
658 &radius,
659 &id,
660 &tilt,
661 &handle_right,
662 &handle_left,
663 &handle_type_right,
664 &handle_type_left,
665 &normal_mode,
666 &custom_normal,
667 &nurbs_order,
668 &nurbs_knots_mode,
669 &nurbs_weight,
670 &curve_type,
671 &resolution,
672 &cyclic},
673 {&vertex_groups, &curve_custom_data, &point_custom_data});
674}
675
679{
683 fn.domain_size = [](const void *owner, const AttrDomain domain) {
684 if (owner == nullptr) {
685 return 0;
686 }
687 const CurvesGeometry &curves = *static_cast<const CurvesGeometry *>(owner);
688 switch (domain) {
690 return curves.points_num();
692 return curves.curves_num();
693 default:
694 return 0;
695 }
696 };
697 fn.domain_supported = [](const void * /*owner*/, const AttrDomain domain) {
699 };
700 fn.adapt_domain = [](const void *owner,
701 const GVArray &varray,
702 const AttrDomain from_domain,
703 const AttrDomain to_domain) -> GVArray {
704 if (owner == nullptr) {
705 return {};
706 }
707 const CurvesGeometry &curves = *static_cast<const CurvesGeometry *>(owner);
708 return curves.adapt_domain(varray, from_domain, to_domain);
709 };
710 return fn;
711}
712
718
719AttributeAccessor CurvesGeometry::attributes() const
720{
722}
723
724MutableAttributeAccessor CurvesGeometry::attributes_for_write()
725{
727}
728
729std::optional<AttributeAccessor> CurveComponent::attributes() const
730{
731 return AttributeAccessor(curves_ ? &curves_->geometry : nullptr,
733}
734
735std::optional<MutableAttributeAccessor> CurveComponent::attributes_for_write()
736{
737 Curves *curves = this->get_for_write();
738 return MutableAttributeAccessor(curves ? &curves->geometry : nullptr,
740}
741
742} // namespace blender::bke
struct Curves * BKE_curves_copy_for_eval(const struct Curves *curves_src)
Low-level operations for curves.
support for deformation groups and hooks.
bool BKE_defgroup_listbase_name_find(const ListBase *defbase, blender::StringRef name, int *r_index, bDeformGroup **r_group)
Definition deform.cc:548
int BKE_defgroup_name_index(const ListBase *defbase, blender::StringRef name)
Definition deform.cc:534
void BKE_id_free(Main *bmain, void *idv)
void * BKE_id_new_nomain(short type, const char *name)
Definition lib_id.cc:1487
#define BLI_assert(a)
Definition BLI_assert.h:50
#define LISTBASE_FOREACH_INDEX(type, var, list, index_var)
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
#define ELEM(...)
Enumerations for DNA_ID.h.
@ ID_CU_LEGACY
@ CURVE_TYPE_POLY
@ CURVE_TYPE_CATMULL_ROM
@ NORMAL_MODE_MINIMUM_TWIST
@ NORMAL_MODE_FREE
#define CURVE_TYPES_NUM
@ BEZIER_HANDLE_FREE
@ BEZIER_HANDLE_ALIGN
@ NURBS_KNOT_MODE_NORMAL
@ NURBS_KNOT_MODE_ENDPOINT_BEZIER
@ CD_PROP_FLOAT
@ CD_PROP_FLOAT3
@ CD_PROP_INT32
volatile int lock
constexpr bool is_empty() const
Definition BLI_span.hh:261
static VArray ForContainer(ContainerT container)
static VArray ForSingle(T value, const int64_t size)
static VArray ForSpan(Span< T > values)
static VArray ForFunc(const int64_t size, GetFunc get_func)
void count_memory(MemoryCounter &memory) const override
void replace(Curves *curve, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
GeometryComponentPtr copy() const override
std::optional< AttributeAccessor > attributes() const final
std::optional< MutableAttributeAccessor > attributes_for_write() final
GVArray get_varray_for_context(const CurvesGeometry &curves, AttrDomain domain, const IndexMask &mask) const final
bool is_equal_to(const fn::FieldNode &other) const override
std::optional< AttrDomain > preferred_domain(const bke::CurvesGeometry &curves) const final
GVArray adapt_domain(const GVArray &varray, AttrDomain from, AttrDomain to) const
GAttributeWriter try_get_for_write(void *owner, const StringRef attribute_id) const final
void foreach_domain(const FunctionRef< void(AttrDomain)> callback) const final
GAttributeReader get_for_vertex_group_index(const CurvesGeometry &curves, const Span< MDeformVert > dverts, const int vertex_group_index) const
GAttributeReader try_get_for_read(const void *owner, const StringRef attribute_id) const final
bool foreach_attribute(const void *owner, FunctionRef< void(const AttributeIter &)> fn) const final
bool try_delete(void *owner, const StringRef attribute_id) const final
DEGForeachIDComponentCallback callback
draw_view in_light_buf[] float
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
AttributeAccessorFunctions accessor_functions_for_providers()
bool attribute_name_is_anonymous(const StringRef name)
static const AttributeAccessorFunctions & get_curves_accessor_functions_ref()
ImplicitSharingPtr< GeometryComponent > GeometryComponentPtr
static void tag_component_topology_changed(void *owner)
static void tag_component_normals_changed(void *owner)
static Array< float3 > curve_normal_point_domain(const CurvesGeometry &curves)
static void tag_component_positions_changed(void *owner)
void remove_defgroup_index(MutableSpan< MDeformVert > dverts, int defgroup_index)
Definition deform.cc:1796
static AttributeAccessorFunctions get_curves_accessor_functions()
VArray< float3 > curve_normals_varray(const CurvesGeometry &curves, AttrDomain domain)
static void tag_component_radii_changed(void *owner)
static void tag_component_curve_types_changed(void *owner)
static VArray< float > construct_curve_length_gvarray(const CurvesGeometry &curves, const AttrDomain domain)
static ComponentAttributeProviders create_attribute_providers_for_curve()
VMutableArray< float > varray_for_mutable_deform_verts(MutableSpan< MDeformVert > dverts, int defgroup_index)
Definition deform.cc:1790
VArray< float > varray_for_deform_verts(Span< MDeformVert > dverts, int defgroup_index)
Definition deform.cc:1786
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:95
VecBase< float, 3 > float3
__int64 int64_t
Definition stdint.h:89
unsigned __int64 uint64_t
Definition stdint.h:90
signed char int8_t
Definition stdint.h:75
const struct Curves * curve_eval
struct EditFont * editfont
EditNurb * editnurb
CustomData point_data
CustomData curve_data
CurvesGeometry geometry
GVArray(* adapt_domain)(const void *owner, const GVArray &varray, AttrDomain from_domain, AttrDomain to_domain)
bool(* domain_supported)(const void *owner, AttrDomain domain)
int(* domain_size)(const void *owner, AttrDomain domain)