66 this->
runtime = MEM_new<CurvesGeometryRuntime>(__func__);
103 if (other.
runtime->curve_offsets_sharing_info) {
104 other.
runtime->curve_offsets_sharing_info->add_user();
109 if (other.
runtime->custom_knots_sharing_info) {
110 other.
runtime->custom_knots_sharing_info->add_user();
126 this->
runtime = MEM_new<CurvesGeometryRuntime>(
129 other.
runtime->custom_knots_sharing_info,
131 other.
runtime->evaluated_offsets_cache,
132 other.
runtime->nurbs_basis_cache,
133 other.
runtime->evaluated_position_cache,
135 other.
runtime->bounds_with_radius_cache,
136 other.
runtime->evaluated_length_cache,
137 other.
runtime->evaluated_tangent_cache,
138 other.
runtime->evaluated_normal_cache,
139 other.
runtime->max_material_index_cache,
140 other.
runtime->custom_knot_offsets_cache,
144 if (other.
runtime->bake_materials) {
145 this->
runtime->bake_materials = std::make_unique<bake::BakeMaterialsList>(
146 *other.
runtime->bake_materials);
152 if (
this == &other) {
155 std::destroy_at(
this);
163 other.curve_offsets =
nullptr;
166 other.custom_knots =
nullptr;
169 other.custom_knot_num = 0;
190 other.vertex_group_active_index = 0;
193 other.attributes_active_index = 0;
196 other.runtime =
nullptr;
201 if (
this == &other) {
204 std::destroy_at(
this);
209CurvesGeometry::~CurvesGeometry()
217 &this->
runtime->curve_offsets_sharing_info);
219 &this->
runtime->custom_knots_sharing_info);
249 const T default_value)
256 if (
data !=
nullptr) {
272 if (
data ==
nullptr) {
282 const T default_value =
T())
292 if (
data !=
nullptr) {
297 if (
num > 0 && span.
first() != default_value) {
298 span.
fill(default_value);
314void CurvesGeometry::fill_curve_types(
const CurveType type)
324 this->
runtime->type_counts.fill(0);
331 if (selection.
size() ==
this->curves_num()) {
335 if (std::optional<int8_t> single_type = this->
curve_types().get_if_single()) {
336 if (single_type == type) {
349 using CountsType = std::array<int, CURVE_TYPES_NUM>;
353 if (
types.is_single()) {
354 counts[
types.get_internal_single()] =
types.size();
364 CountsType result = init;
365 for (const int curve_index : curves_range) {
366 result[types_span[curve_index]]++;
370 [](
const CountsType &a,
const CountsType &
b) {
379void CurvesGeometry::update_curve_types()
575 r_data[curve + 1] = knot_count;
581void CurvesGeometry::nurbs_custom_knots_update_size()
583 this->
runtime->custom_knot_offsets_cache.tag_dirty();
585 const int knots_num = knots_by_curve.
total_size();
588 &this->
runtime->custom_knots_sharing_info,
589 this->custom_knot_num,
595void CurvesGeometry::nurbs_custom_knots_resize(
int knots_num)
598 &this->
runtime->custom_knots_sharing_info,
599 this->custom_knot_num,
602 this->
runtime->custom_knot_offsets_cache.tag_dirty();
609 if (dverts ==
nullptr) {
619 if (dvert !=
nullptr) {
638 offset += count_fn(
i);
640 offsets.
last() = offset;
655 handle_types_left =
curves.handle_types_left();
656 handle_types_right =
curves.handle_types_right();
663 const IndexRange points = points_by_curve[curve_index];
664 switch (
types[curve_index]) {
667 points.
size(), cyclic[curve_index], resolution[curve_index]);
669 return points.
size();
673 handle_types_right.
slice(points),
675 resolution[curve_index],
676 all_bezier_offsets.
slice(offsets));
677 return all_bezier_offsets[offsets.
last()];
681 nurbs_orders[curve_index],
683 resolution[curve_index],
684 KnotsMode(nurbs_knots_modes[curve_index]));
741void CurvesGeometry::ensure_nurbs_basis_cache()
const
752 r_data.
resize(this->curves_num());
755 const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
760 const Span<float> custom_knots = this->nurbs_custom_knots();
764 for (
const int curve_index : segment) {
765 const IndexRange points = points_by_curve[curve_index];
766 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
768 const int8_t order = orders[curve_index];
769 const bool is_cyclic = cyclic[curve_index];
772 if (!curves::nurbs::check_valid_num_and_order(points.
size(), order,
is_cyclic, mode)) {
773 r_data[curve_index].invalid =
true;
776 const int knots_num = curves::nurbs::knots_num(points.
size(), order,
is_cyclic);
778 curves::nurbs::load_curve_knots(mode,
782 custom_knots_by_curve[curve_index],
786 curves::nurbs::calculate_basis_cache(
787 points.
size(), evaluated_points.
size(), order,
is_cyclic, knots, r_data[curve_index]);
797 runtime.evaluated_position_cache.ensure(
801 this->ensure_nurbs_basis_cache();
810 auto evaluate_catmull = [&](
const IndexMask &selection) {
813 selection.foreach_index(
GrainSize(128), [&](
const int curve_index) {
822 auto evaluate_poly = [&](
const IndexMask &selection) {
826 auto evaluate_bezier = [&](
const IndexMask &selection) {
834 runtime.evaluated_offsets_cache.data().all_bezier_offsets;
835 selection.foreach_index(
GrainSize(128), [&](
const int curve_index) {
846 auto evaluate_nurbs = [&](
const IndexMask &selection) {
847 this->ensure_nurbs_basis_cache();
851 selection.foreach_index(
GrainSize(128), [&](
const int curve_index) {
869 return runtime.evaluated_position_cache.data();
888 tangents.
slice(evaluated_points));
904 if (
cyclic[curve_index]) {
910 const float epsilon = 1e-6f;
921 handles_left[points.
last()]);
926 return runtime.evaluated_tangent_cache.data();
944 for (
const int i :
data.index_range()) {
962 const int curve_index,
967 switch (eval_data.
types[curve_index]) {
970 src, eval_data.
cyclic[curve_index], eval_data.
resolution[curve_index], dst);
994 this->ensure_nurbs_basis_cache();
1008 runtime.evaluated_offsets_cache.data().all_bezier_offsets,
1009 runtime.nurbs_basis_cache.data(),
1015 const bool use_tilt = !(
tilt.is_single() &&
tilt.get_internal_single() == 0.0f);
1023 custom_normal_span = custom_normal;
1046 if (custom_normal_span.
is_empty()) {
1067 tilt_span.
slice(points));
1073 tilt_span.
slice(points),
1086void CurvesGeometry::interpolate_to_evaluated(
const int curve_index,
1092 this->points_by_curve(),
1096 runtime.evaluated_offsets_cache.data().all_bezier_offsets,
1097 runtime.nurbs_basis_cache.data(),
1115 runtime.evaluated_offsets_cache.data().all_bezier_offsets,
1116 runtime.nurbs_basis_cache.data(),
1127 eval_data, curve_index, src.
slice(points), dst.
slice(evaluated_points));
1132void CurvesGeometry::ensure_evaluated_lengths()
const
1139 r_data.
resize(total_num);
1148 const bool cyclic = curves_cyclic[curve_index];
1150 const IndexRange lengths_range = this->lengths_range_for_curve(curve_index,
cyclic);
1153 evaluated_lengths.
slice(lengths_range));
1159void CurvesGeometry::ensure_can_interpolate_to_evaluated()
const
1161 this->evaluated_points_by_curve();
1162 this->ensure_nurbs_basis_cache();
1182 this->curve_num == 0 ? 0 : (
this->curve_num + 1),
1194void CurvesGeometry::tag_positions_changed()
1203void CurvesGeometry::tag_topology_changed()
1212void CurvesGeometry::tag_normals_changed()
1216void CurvesGeometry::tag_radii_changed()
1220void CurvesGeometry::tag_material_index_changed()
1228 for (float3 &position : positions.slice(range)) {
1229 position += translation;
1237 for (float3 &position : positions.slice(range)) {
1238 position = math::transform_point(matrix, position);
1243void CurvesGeometry::calculate_bezier_auto_handles()
1261 for (
const int i_curve : range) {
1265 types_left.
slice(points),
1266 types_right.
slice(points),
1268 positions_left.
slice(points),
1269 positions_right.
slice(points));
1275void CurvesGeometry::translate(
const float3 &translation)
1281 std::optional<Bounds<float3>>
bounds;
1296 bounds->min += translation;
1297 bounds->max += translation;
1316std::optional<Bounds<float3>> CurvesGeometry::bounds_min_max(
const bool use_radius)
const
1319 return std::nullopt;
1324 if (
const std::optional radius_single =
radius.get_if_single()) {
1326 r_bounds.
pad(*radius_single);
1329 const Span radius_span =
radius.get_internal_span();
1349std::optional<int> CurvesGeometry::material_index_max()
const
1356 if (r_max_material_index.has_value()) {
1357 r_max_material_index = std::clamp(*r_max_material_index, 0,
MAXMAT);
1367 this->nurbs_custom_knots().size_in_bytes());
1382 const IndexMask custom_knot_curves =
curves.nurbs_custom_knot_curves(memory);
1384 points_by_curve, custom_knot_curves, memory);
1386 points_to_copy, custom_knot_points, memory);
1388 int dst_knot_count = 0;
1391 curve_point_counts[curve], orders[curve], cyclic[curve]);
1397 new_knots.
reserve(dst_knot_count);
1400 custom_knot_points_to_copy,
1403 const IndexRange src_range = src_knots_by_curve[curve];
1404 const int order = orders[curve];
1405 const int leading_spans = order / 2;
1406 const int point_to_knot = -points.
start() + src_range.
start();
1407 const int point_to_span = point_to_knot + leading_spans;
1409 const int first_knot = ranges_to_copy.
first().start() + point_to_knot;
1412 float last_knot = new_knots.
last();
1414 for (
const int spans_left_knot : range.shift(point_to_span)) {
1415 last_knot += src_knots[spans_left_knot + 1] - src_knots[spans_left_knot];
1416 new_knots.
append(last_knot);
1419 const int last_spans_left_knot = ranges_to_copy.last().last() + point_to_span + 1;
1420 last_knot += src_knots[last_spans_left_knot + 1] - src_knots[last_spans_left_knot];
1421 new_knots.
append(last_knot);
1434 [&](
const int64_t point_i) { curve_point_counts[point_to_curve_map[point_i]]++; });
1439 return curve_point_counts[
i] > 0;
1447 dst_curves.curves_num() > 1024,
1449 if (curves_to_copy.is_empty()) {
1454 curve_point_counts.
as_span(), curves_to_copy, new_curve_offsets.drop_back(1));
1463 dst_curves.attributes_for_write());
1469 dst_curves.attributes_for_write());
1473 copy_point_selection_custom_knots(curves, points_to_copy, curve_point_counts, dst_curves);
1476 if (dst_curves.curves_num() == curves.
curves_num()) {
1477 dst_curves.runtime->type_counts = curves.
runtime->type_counts;
1480 dst_curves.remove_attributes_based_on_types();
1486void CurvesGeometry::remove_points(
const IndexMask &points_to_delete,
1492 if (points_to_delete.
size() ==
this->points_num()) {
1507 const IndexMask custom_knot_curves =
curves.nurbs_custom_knot_curves(memory);
1509 curves_to_copy, custom_knot_curves, memory);
1511 Array<int> dst_knot_offsets_data(custom_knot_curves_to_copy.
size() + 1, 0);
1515 src_knots_by_curve, custom_knot_curves_to_copy, dst_knot_offsets_data);
1520 custom_knot_curves_to_copy,
1521 curves.nurbs_custom_knots(),
1545 dst_points_by_curve,
1556 if (
curves.nurbs_has_custom_knots()) {
1566void CurvesGeometry::remove_curves(
const IndexMask &curves_to_delete,
1572 if (curves_to_delete.
size() ==
this->curves_num()) {
1584 const float last = custom_knots.
last();
1586 for (
float &knot_value : custom_knots) {
1587 knot_value = last - knot_value;
1598 GrainSize(256), [&](
const int curve_i) {
data.slice(points_by_curve[curve_i]).reverse(); });
1609 const IndexRange points = points_by_curve[curve_i];
1613 const int end_index = points.
size() - 1 -
i;
1614 std::swap(a[end_index],
b[
i]);
1615 std::swap(
b[end_index], a[
i]);
1617 if (points.
size() % 2) {
1619 std::swap(a[middle_index],
b[middle_index]);
1624void CurvesGeometry::reverse_curves(
const IndexMask &curves_to_reverse)
1646 using T = decltype(dummy);
1647 reverse_curve_point_data<T>(*this, curves_to_reverse, attribute.span.typed<T>());
1657 const IndexRange curve_knots = custom_knots_by_curve[curve];
1687void CurvesGeometry::remove_attributes_based_on_types()
1709 curves.point_num = point_num;
1736 for (const int i_curve : range) {
1737 for (const int i_point : points_by_curve[i_curve]) {
1738 mixer.mix_in(i_curve, old_values[i_point]);
1741 mixer.finalize(range);
1758 r_values.
fill(
true);
1760 for (
const int i_point : points_by_curve[i_curve]) {
1761 if (!old_values[i_point]) {
1762 r_values[i_curve] =
false;
1774 using T = decltype(dummy);
1775 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
1776 Array<T> values(curves.curves_num());
1777 adapt_curve_domain_point_to_curve_impl<T>(curves, varray.typed<T>(), values);
1778 new_varray = VArray<T>::ForContainer(std::move(values));
1798 r_values.
slice(points_by_curve[i_curve]).
fill(old_values[i_curve]);
1807 using T = decltype(dummy);
1808 Array<T> values(curves.points_num());
1809 adapt_curve_domain_curve_to_point_impl<T>(curves, varray.typed<T>(), values);
1810 new_varray = VArray<T>::ForContainer(std::move(values));
1863 this->runtime = MEM_new<blender::bke::CurvesGeometryRuntime>(__func__);
1884 &reader, &this->custom_knots, [&]() {
1902void CurvesGeometry::blend_write_prepare(CurvesGeometry::BlendWriteData &write_data)
1905 {{AttrDomain::Point, &write_data.point_layers},
1906 {AttrDomain::Curve, &write_data.curve_layers}},
1907 write_data.attribute_data);
1911 write_data.point_layers,
1912 write_data.attribute_data);
1916 write_data.curve_layers,
1917 write_data.attribute_data);
1918 if (write_data.attribute_data.attributes.is_empty()) {
1930 const CurvesGeometry::BlendWriteData &write_data)
1944 [&]() { BLO_write_int32_array(&writer, this->curve_num + 1, this->curve_offsets); });
1955 [&]() { BLO_write_float_array(&writer, this->custom_knot_num, this->custom_knots); });
Low-level operations for curves.
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
void CustomData_blend_write_prepare(CustomData &data, blender::bke::AttrDomain domain, int domain_size, blender::Vector< CustomDataLayer, 16 > &layers_to_write, blender::bke::AttributeStorage::BlendWriteData &write_data)
void CustomData_count_memory(const CustomData &data, int totelem, blender::MemoryCounter &memory)
void CustomData_realloc(CustomData *data, int old_size, int new_size, eCDAllocType alloctype=CD_CONSTRUCT)
void * CustomData_get_layer_named_for_write(CustomData *data, eCustomDataType type, blender::StringRef name, int totelem)
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
const void * CustomData_get_layer_named(const CustomData *data, eCustomDataType type, blender::StringRef name)
void * CustomData_add_layer_named(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem, blender::StringRef name)
void CustomData_reset(CustomData *data)
void CustomData_blend_write(BlendWriter *writer, CustomData *data, blender::Span< CustomDataLayer > layers_to_write, int count, eCustomDataMask cddata_mask, ID *id)
void CustomData_free(CustomData *data)
void CustomData_init_from(const CustomData *source, CustomData *dest, eCustomDataMask mask, int totelem)
void CustomData_blend_read(BlendDataReader *reader, CustomData *data, int count)
void * CustomData_get_layer_for_write(CustomData *data, eCustomDataType type, int totelem)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
bool CustomData_free_layer_named(CustomData *data, blender::StringRef name)
#define BLI_assert_unreachable()
#define BUFFER_FOR_CPP_TYPE_VALUE(type, variable_name)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
ATTR_WARN_UNUSED_RESULT const size_t num
void BLO_read_float_array(BlendDataReader *reader, int64_t array_size, float **ptr_p)
void BLO_read_int32_array(BlendDataReader *reader, int64_t array_size, int32_t **ptr_p)
#define BLO_read_struct_list(reader, struct_name, list)
void BLO_write_shared(BlendWriter *writer, const void *data, size_t approximate_size_in_bytes, const blender::ImplicitSharingInfo *sharing_info, blender::FunctionRef< void()> write_fn)
const blender::ImplicitSharingInfo * BLO_read_shared(BlendDataReader *reader, T **data_ptr, blender::FunctionRef< const blender::ImplicitSharingInfo *()> read_fn)
@ NORMAL_MODE_MINIMUM_TWIST
Read Guarded memory(de)allocation.
BMesh const char void * data
constexpr void fill(const T &value) const
constexpr void copy_from(Span< T > values) const
constexpr Span slice_safe(const int64_t start, const int64_t size) const
constexpr Span slice(int64_t start, int64_t size) const
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
static const CPPType & get()
void copy_from(GSpan values)
GMutableSpan slice(const int64_t start, int64_t size) const
const CPPType & type() const
GSpan slice(const int64_t start, int64_t size) const
const CPPType & type() const
void get_internal_single(void *r_value) const
static GVArray ForSingle(const CPPType &type, int64_t size, const void *value)
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
static IndexMask from_intersection(const IndexMask &mask_a, const IndexMask &mask_b, IndexMaskMemory &memory)
constexpr int64_t first() const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
static constexpr IndexRange from_begin_size(const int64_t begin, const int64_t size)
constexpr int64_t start() const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr MutableSpan drop_back(const int64_t n) const
constexpr void fill(const T &value) const
constexpr void reverse() const
constexpr T & first() const
constexpr IndexRange index_range() const
constexpr T & last(const int64_t n=0) const
bool contains(const Key &key) const
void ensure(FunctionRef< void(T &data)> compute_cache)
constexpr Span slice(int64_t start, int64_t size) const
constexpr const T & first() const
constexpr bool is_empty() const
static VArray ForSingle(T value, const int64_t size)
static VArray ForSpan(Span< T > values)
void append(const T &value)
const T & last(const int64_t n=0) const
void resize(const int64_t new_size)
MutableSpan< T > as_mutable_span()
void reserve(const int64_t min_capacity)
void extend(Span< T > array)
void reinitialize(const int64_t new_size)
Span< T > as_span() const
eCustomDataType data_type
SharedCache< Vector< curves::nurbs::BasisCache > > nurbs_basis_cache
SharedCache< Vector< float > > evaluated_length_cache
SharedCache< Bounds< float3 > > bounds_with_radius_cache
SharedCache< Vector< int > > custom_knot_offsets_cache
SharedCache< Vector< float3 > > evaluated_tangent_cache
SharedCache< EvaluatedOffsets > evaluated_offsets_cache
SharedCache< Vector< float3 > > evaluated_normal_cache
const ImplicitSharingInfo * custom_knots_sharing_info
SharedCache< std::optional< int > > max_material_index_cache
SharedCache< Bounds< float3 > > bounds_cache
SharedCache< Vector< float3 > > evaluated_position_cache
const ImplicitSharingInfo * curve_offsets_sharing_info
VArray< int8_t > handle_types_left() const
void remove_attributes_based_on_types()
MutableSpan< float3 > positions_for_write()
MutableSpan< float > nurbs_custom_knots_for_write()
OffsetIndices< int > points_by_curve() const
VArray< int8_t > normal_mode() const
MutableSpan< int8_t > handle_types_right_for_write()
VArray< int8_t > handle_types_right() const
void ensure_can_interpolate_to_evaluated() const
IndexRange curves_range() const
void update_curve_types()
MutableSpan< int8_t > curve_types_for_write()
const std::array< int, CURVE_TYPES_NUM > & curve_type_counts() const
MutableSpan< float3 > handle_positions_left_for_write()
MutableAttributeAccessor attributes_for_write()
MutableSpan< float3 > handle_positions_right_for_write()
VArray< float > radius() const
VArray< float > tilt() const
Span< float3 > evaluated_tangents() const
void nurbs_custom_knots_update_size()
Span< float > nurbs_weights() const
Span< float3 > handle_positions_left() const
VArray< int > resolution() const
int evaluated_points_num() const
void interpolate_to_evaluated(int curve_index, GSpan src, GMutableSpan dst) const
IndexRange points_range() const
Span< int > offsets() const
VArray< int8_t > nurbs_knots_modes() const
Span< float3 > evaluated_normals() const
Span< float3 > positions() const
OffsetIndices< int > evaluated_points_by_curve() const
bool has_curve_with_type(CurveType type) const
void tag_topology_changed()
void resize(int points_num, int curves_num)
Span< float3 > handle_positions_right() const
void tag_positions_changed()
void fill_curve_types(CurveType type)
AttributeAccessor attributes() const
IndexMask indices_for_curve_type(CurveType type, IndexMaskMemory &memory) const
bool is_single_type(CurveType type) const
MutableSpan< int > offsets_for_write()
std::optional< Bounds< float3 > > bounds_min_max(bool use_radius=true) const
bool nurbs_has_custom_knots() const
OffsetIndices< int > nurbs_custom_knots_by_curve() const
Span< float3 > evaluated_positions() const
VArray< int8_t > curve_types() const
VArray< bool > cyclic() const
VArray< int8_t > nurbs_orders() const
MutableSpan< int8_t > handle_types_left_for_write()
bool remove(const StringRef attribute_id)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
IndexMask complement(const IndexMask &universe, IndexMaskMemory &memory) const
void foreach_index(Fn &&fn) const
void foreach_segment(Fn &&fn) const
void add_shared(const ImplicitSharingInfo *sharing_info, const FunctionRef< void(MemoryCounter &shared_memory)> count_fn)
static bool is_cyclic(const Nurb *nu)
static void transform_positions(const Span< blender::float3 > src, const blender::float4x4 &transform, blender::MutableSpan< blender::float3 > dst)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void copy_group_to_group(OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, GSpan src, GMutableSpan dst)
void gather_group_to_group(const OffsetIndices< int > src_offsets, const OffsetIndices< int > dst_offsets, const IndexMask &selection, const Span< T > src, MutableSpan< T > dst)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
typename DefaultMixerStruct< T >::type DefaultMixer
void calculate_auto_handles(bool cyclic, Span< int8_t > types_left, Span< int8_t > types_right, Span< float3 > positions, MutableSpan< float3 > positions_left, MutableSpan< float3 > positions_right)
void calculate_evaluated_offsets(Span< int8_t > handle_types_left, Span< int8_t > handle_types_right, bool cyclic, int resolution, MutableSpan< int > evaluated_offsets)
void calculate_evaluated_positions(Span< float3 > positions, Span< float3 > handles_left, Span< float3 > handles_right, OffsetIndices< int > evaluated_offsets, MutableSpan< float3 > evaluated_positions)
void interpolate_to_evaluated(GSpan src, OffsetIndices< int > evaluated_offsets, GMutableSpan dst)
int calculate_evaluated_num(int points_num, bool cyclic, int resolution)
void interpolate_to_evaluated(GSpan src, bool cyclic, int resolution, GMutableSpan dst)
int calculate_evaluated_num(int points_num, int8_t order, bool cyclic, int resolution, KnotsMode knots_mode)
int knots_num(int points_num, int8_t order, bool cyclic)
void interpolate_to_evaluated(const BasisCache &basis_cache, int8_t order, Span< float > control_weights, GSpan src, GMutableSpan dst)
void calculate_normals_z_up(Span< float3 > tangents, MutableSpan< float3 > normals)
void calculate_normals_minimum(Span< float3 > tangents, bool cyclic, MutableSpan< float3 > normals)
void calculate_tangents(Span< float3 > positions, bool is_cyclic, MutableSpan< float3 > tangents)
IndexRange per_curve_point_offsets_range(const IndexRange points, const int curve_index)
IndexMask indices_for_type(const VArray< int8_t > &types, const std::array< int, CURVE_TYPES_NUM > &type_counts, const CurveType type, const IndexMask &selection, IndexMaskMemory &memory)
void foreach_selected_point_ranges_per_curve(const IndexMask &mask, const OffsetIndices< int > points_by_curve, SelectedCallback selected_fn)
const AttributeAccessorFunctions & get_attribute_accessor_functions()
IndexMask curve_to_point_selection(OffsetIndices< int > points_by_curve, const IndexMask &curve_selection, IndexMaskMemory &memory)
void fill_points(OffsetIndices< int > points_by_curve, const IndexMask &curve_selection, GPointer value, GMutableSpan dst)
void foreach_curve_by_type(const VArray< int8_t > &types, const std::array< int, CURVE_TYPES_NUM > &type_counts, const IndexMask &selection, FunctionRef< void(IndexMask)> catmull_rom_fn, FunctionRef< void(IndexMask)> poly_fn, FunctionRef< void(IndexMask)> bezier_fn, FunctionRef< void(IndexMask)> nurbs_fn)
static void normalize_span(MutableSpan< float3 > data)
static CustomData & domain_custom_data(CurvesGeometry &curves, const AttrDomain domain)
static void translate_positions(MutableSpan< float3 > positions, const float3 &translation)
CurvesGeometry curves_copy_curve_selection(const CurvesGeometry &curves, const IndexMask &curves_to_copy, const AttributeFilter &attribute_filter)
CurvesGeometry curves_copy_point_selection(const CurvesGeometry &curves, const IndexMask &points_to_copy, const AttributeFilter &attribute_filter)
constexpr StringRef ATTR_RADIUS
constexpr StringRef ATTR_RESOLUTION
static MutableSpan< T > get_mutable_attribute(CurvesGeometry &curves, const AttrDomain domain, const StringRef name, const T default_value=T())
static void copy_point_selection_custom_knots(const CurvesGeometry &curves, const IndexMask &points_to_copy, const Span< int > curve_point_counts, CurvesGeometry &dst_curves)
static VArray< T > get_varray_attribute(const CurvesGeometry &curves, const AttrDomain domain, const StringRef name, const T default_value)
constexpr StringRef ATTR_CURVE_TYPE
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type)
static GVArray adapt_curve_domain_point_to_curve(const CurvesGeometry &curves, const GVArray &varray)
constexpr StringRef ATTR_CYCLIC
void gather_attributes(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
CurvesGeometry curves_new_no_attributes(int point_num, int curve_num)
constexpr StringRef ATTR_SURFACE_UV_COORDINATE
constexpr StringRef ATTR_HANDLE_POSITION_RIGHT
std::array< int, CURVE_TYPES_NUM > calculate_type_counts(const VArray< int8_t > &types)
static void evaluate_generic_data_for_curve(const EvalData &eval_data, const int curve_index, const GSpan src, GMutableSpan dst)
static void reverse_custom_knots(MutableSpan< float > custom_knots)
constexpr StringRef ATTR_NORMAL_MODE
constexpr StringRef ATTR_TILT
constexpr StringRef ATTR_HANDLE_POSITION_LEFT
void transform_custom_normal_attribute(const float4x4 &transform, MutableAttributeAccessor &attributes)
static Span< T > get_span_attribute(const CurvesGeometry &curves, const AttrDomain domain, const StringRef name)
void build_offsets(MutableSpan< int > offsets, const CountFn &count_fn)
static void reverse_curve_point_data(const CurvesGeometry &curves, const IndexMask &curve_selection, MutableSpan< T > data)
constexpr StringRef ATTR_HANDLE_TYPE_LEFT
void gather_attributes_group_to_group(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, OffsetIndices< int > src_offsets, OffsetIndices< int > dst_offsets, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
static int domain_num(const CurvesGeometry &curves, const AttrDomain domain)
static void reverse_swap_curve_point_data(const CurvesGeometry &curves, const IndexMask &curve_selection, MutableSpan< T > data_a, MutableSpan< T > data_b)
constexpr StringRef ATTR_NURBS_KNOTS_MODE
constexpr StringRef ATTR_POSITION
static GVArray adapt_curve_domain_curve_to_point(const CurvesGeometry &curves, const GVArray &varray)
static void adapt_curve_domain_curve_to_point_impl(const CurvesGeometry &curves, const VArray< T > &old_values, MutableSpan< T > r_values)
constexpr StringRef ATTR_NURBS_ORDER
constexpr StringRef ATTR_NURBS_WEIGHT
constexpr StringRef ATTR_HANDLE_TYPE_RIGHT
void curves_convert_storage_to_customdata(CurvesGeometry &curves)
static void rotate_directions_around_axes(MutableSpan< float3 > directions, const Span< float3 > axes, const Span< float > angles)
static void copy_curve_selection_custom_knots(const CurvesGeometry &curves, const IndexMask &curves_to_copy, CurvesGeometry &dst_curves)
static void calculate_evaluated_offsets(const CurvesGeometry &curves, MutableSpan< int > offsets, MutableSpan< int > all_bezier_offsets)
static void adapt_curve_domain_point_to_curve_impl(const CurvesGeometry &curves, const VArray< T > &old_values, MutableSpan< T > r_values)
void attribute_storage_blend_write_prepare(AttributeStorage &data, const Map< AttrDomain, Vector< CustomDataLayer, 16 > * > &layers_to_write, AttributeStorage::BlendWriteData &write_data)
std::optional< Bounds< T > > min_max_with_radii(const Span< T > values, const Span< RadiusT > radii)
std::optional< Bounds< T > > min_max(const std::optional< Bounds< T > > &a, const T &b)
std::optional< T > max(const VArray< T > &values)
void resize_trivial_array(T **data, const ImplicitSharingInfo **sharing_info, int64_t old_size, int64_t new_size)
const ImplicitSharingInfo * info_for_mem_free(void *data)
void free_shared_data(T **data, const ImplicitSharingInfo **sharing_info)
void make_trivial_data_mutable(T **data, const ImplicitSharingInfo **sharing_info, const int64_t size)
void masked_fill(MutableSpan< T > data, const T &value, const IndexMask &mask)
void accumulate_lengths(const Span< T > values, const bool cyclic, MutableSpan< float > lengths)
float3 rotate_direction_around_axis(const float3 &direction, const float3 &axis, float angle)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
bool almost_equal_relative(const VecBase< T, Size > &a, const VecBase< T, Size > &b, const T &epsilon_factor)
void build_reverse_map(OffsetIndices< int > offsets, MutableSpan< int > r_map)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
OffsetIndices< int > gather_selected_offsets(OffsetIndices< int > src_offsets, const IndexMask &selection, int start_offset, MutableSpan< int > dst_offsets)
void parallel_invoke(Functions &&...functions)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
MatBase< float, 4, 4 > float4x4
VecBase< float, 3 > float3
static void init(bNodeTree *, bNode *node)
static Span< T > get_span_attribute(const PointCloud &pointcloud, const StringRef name)
static VArray< T > get_varray_attribute(const PointCloud &pointcloud, const StringRef name, const T default_value)
static MutableSpan< T > get_mutable_attribute(PointCloud &pointcloud, const StringRef name, const T default_value=T())
struct Attribute * dna_attributes
int vertex_group_active_index
CurvesGeometryRuntimeHandle * runtime
ListBase vertex_group_names
int attributes_active_index
struct AttributeStorage attribute_storage
void pad(const PaddingT &padding)
Vector< int > all_bezier_offsets
Vector< int > evaluated_offsets
Vector< CustomDataLayer, 16 > & curve_layers
Vector< CustomDataLayer, 16 > & point_layers
AttributeStorage::BlendWriteData attribute_data
const VArray< bool > & cyclic
const Span< float > nurbs_weights
const Span< int > all_bezier_evaluated_offsets
const VArray< int > & resolution
const Span< curves::nurbs::BasisCache > nurbs_basis_cache
const VArray< int8_t > & nurbs_orders
const VArray< int8_t > & types
const OffsetIndices< int > points_by_curve