69 this->
runtime = MEM_new<CurvesGeometryRuntime>(__func__);
106 if (other.
runtime->curve_offsets_sharing_info) {
107 other.
runtime->curve_offsets_sharing_info->add_user();
112 if (other.
runtime->custom_knots_sharing_info) {
113 other.
runtime->custom_knots_sharing_info->add_user();
128 this->
runtime = MEM_new<CurvesGeometryRuntime>(
131 other.
runtime->custom_knots_sharing_info,
133 other.
runtime->evaluated_offsets_cache,
134 other.
runtime->has_cyclic_curve_cache,
135 other.
runtime->nurbs_basis_cache,
136 other.
runtime->evaluated_position_cache,
138 other.
runtime->bounds_with_radius_cache,
139 other.
runtime->evaluated_length_cache,
140 other.
runtime->evaluated_tangent_cache,
141 other.
runtime->evaluated_normal_cache,
142 other.
runtime->max_material_index_cache,
143 other.
runtime->custom_knot_offsets_cache,
147 if (other.
runtime->bake_materials) {
148 this->
runtime->bake_materials = std::make_unique<bake::BakeMaterialsList>(
149 *other.
runtime->bake_materials);
155 if (
this == &other) {
158 std::destroy_at(
this);
166 other.curve_offsets =
nullptr;
169 other.custom_knots =
nullptr;
172 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()
216 &this->
runtime->curve_offsets_sharing_info);
218 &this->
runtime->custom_knots_sharing_info);
244void CurvesGeometry::fill_curve_types(
const CurveType type)
254 this->
runtime->type_counts.fill(0);
261 if (selection.
size() == this->curves_num()) {
265 if (std::optional<int8_t> single_type = this->
curve_types().get_if_single()) {
266 if (single_type == type) {
279 using CountsType = std::array<int, CURVE_TYPES_NUM>;
283 if (
types.is_single()) {
284 counts[
types.get_internal_single()] =
types.size();
294 CountsType result = init;
295 for (const int curve_index : curves_range) {
296 result[types_span[curve_index]]++;
300 [](
const CountsType &a,
const CountsType &
b) {
309void CurvesGeometry::update_curve_types()
431std::optional<Span<float3>> CurvesGeometry::handle_positions_left()
const
446std::optional<Span<float3>> CurvesGeometry::handle_positions_right()
const
472std::optional<Span<float>> CurvesGeometry::nurbs_weights()
const
503std::optional<Span<float2>> CurvesGeometry::surface_uv_coords()
const
563 for (
const int curve : range) {
580void CurvesGeometry::nurbs_custom_knots_update_size()
582 this->
runtime->custom_knot_offsets_cache.tag_dirty();
584 const int knots_num = knots_by_curve.
total_size();
587 &this->
runtime->custom_knots_sharing_info,
588 this->custom_knot_num,
594void CurvesGeometry::nurbs_custom_knots_resize(
int knots_num)
597 &this->
runtime->custom_knots_sharing_info,
598 this->custom_knot_num,
601 this->
runtime->custom_knot_offsets_cache.tag_dirty();
608 if (dverts ==
nullptr) {
618 if (dvert !=
nullptr) {
637 offset += count_fn(
i);
639 offsets.
last() = offset;
654 handle_types_left =
curves.handle_types_left();
655 handle_types_right =
curves.handle_types_right();
664 const IndexRange points = points_by_curve[curve_index];
665 switch (
types[curve_index]) {
668 points.
size(), cyclic[curve_index], resolution[curve_index]);
670 return points.
size();
674 handle_types_right.
slice(points),
676 resolution[curve_index],
677 all_bezier_offsets.
slice(offsets));
678 return all_bezier_offsets[offsets.
last()];
681 const bool is_cyclic = cyclic[curve_index];
682 const int8_t order = nurbs_orders[curve_index];
684 const IndexRange custom_knots_range = custom_knots_by_curve[curve_index];
688 all_custom_knots.
slice(custom_knots_range) :
691 points.
size(), order,
is_cyclic, resolution[curve_index], knots_mode, custom_knots);
727bool CurvesGeometry::has_cyclic_curve()
const
729 this->
runtime->has_cyclic_curve_cache.ensure([&](
bool &r_data) {
732 return this->
runtime->has_cyclic_curve_cache.data();
756void CurvesGeometry::ensure_nurbs_basis_cache()
const
767 r_data.
resize(this->curves_num());
770 const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
774 const VArray<int> resolutions = this->resolution();
776 const Span<float> custom_knots = this->nurbs_custom_knots();
780 for (
const int curve_index : segment) {
781 const IndexRange points = points_by_curve[curve_index];
782 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
784 const int8_t order = orders[curve_index];
785 const int resolution = resolutions[curve_index];
786 const bool is_cyclic = cyclic[curve_index];
789 if (!curves::nurbs::check_valid_eval_params(
792 r_data[curve_index].invalid =
true;
795 const int knots_num = curves::nurbs::knots_num(points.
size(), order,
is_cyclic);
797 curves::nurbs::load_curve_knots(mode,
801 custom_knots_by_curve[curve_index],
805 curves::nurbs::calculate_basis_cache(points.
size(),
806 evaluated_points.
size(),
812 r_data[curve_index]);
822 runtime.evaluated_position_cache.ensure(
826 this->ensure_nurbs_basis_cache();
835 auto evaluate_catmull = [&](
const IndexMask &selection) {
838 selection.foreach_index(
GrainSize(128), [&](
const int curve_index) {
847 auto evaluate_poly = [&](
const IndexMask &selection) {
851 auto evaluate_bezier = [&](
const IndexMask &selection) {
859 runtime.evaluated_offsets_cache.data().all_bezier_offsets;
860 selection.foreach_index(
GrainSize(128), [&](
const int curve_index) {
871 auto evaluate_nurbs = [&](
const IndexMask &selection) {
872 this->ensure_nurbs_basis_cache();
874 const std::optional<Span<float>>
nurbs_weights = this->nurbs_weights();
876 selection.foreach_index(
GrainSize(128), [&](
const int curve_index) {
895 return runtime.evaluated_position_cache.data();
914 tangents.
slice(evaluated_points));
930 if (
cyclic[curve_index]) {
936 const float epsilon = 1e-6f;
947 handles_left[points.
last()]);
952 return runtime.evaluated_tangent_cache.data();
970 for (
const int i :
data.index_range()) {
988 const int curve_index,
993 switch (eval_data.
types[curve_index]) {
996 src, eval_data.
cyclic[curve_index], eval_data.
resolution[curve_index], dst);
1021 this->ensure_nurbs_basis_cache();
1035 runtime.evaluated_offsets_cache.data().all_bezier_offsets,
1036 runtime.nurbs_basis_cache.data(),
1042 const bool use_tilt = !(
tilt.is_single() &&
tilt.get_internal_single() == 0.0f);
1050 custom_normal_span = custom_normal;
1073 if (custom_normal_span.
is_empty()) {
1094 tilt_span.
slice(points));
1100 tilt_span.
slice(points),
1113void CurvesGeometry::interpolate_to_evaluated(
const int curve_index,
1119 this->points_by_curve(),
1123 runtime.evaluated_offsets_cache.data().all_bezier_offsets,
1124 runtime.nurbs_basis_cache.data(),
1128 BLI_assert(src.
size() == this->points_by_curve()[curve_index].size());
1129 BLI_assert(dst.
size() == this->evaluated_points_by_curve()[curve_index].size());
1142 runtime.evaluated_offsets_cache.data().all_bezier_offsets,
1143 runtime.nurbs_basis_cache.data(),
1154 eval_data, curve_index, src.
slice(points), dst.
slice(evaluated_points));
1159void CurvesGeometry::ensure_evaluated_lengths()
const
1166 r_data.
resize(total_num);
1175 const bool cyclic = curves_cyclic[curve_index];
1177 const IndexRange lengths_range = this->lengths_range_for_curve(curve_index,
cyclic);
1180 evaluated_lengths.
slice(lengths_range));
1186void CurvesGeometry::ensure_can_interpolate_to_evaluated()
const
1188 this->evaluated_points_by_curve();
1189 this->ensure_nurbs_basis_cache();
1210 this->curve_num == 0 ? 0 : (this->curve_num + 1),
1222void CurvesGeometry::tag_positions_changed()
1231void CurvesGeometry::tag_topology_changed()
1241void CurvesGeometry::tag_normals_changed()
1245void CurvesGeometry::tag_radii_changed()
1249void CurvesGeometry::tag_material_index_changed()
1257 for (float3 &position : positions.slice(range)) {
1258 position += translation;
1263void CurvesGeometry::calculate_bezier_auto_handles()
1281 for (
const int i_curve : range) {
1285 types_left.
slice(points),
1286 types_right.
slice(points),
1288 positions_left.
slice(points),
1289 positions_right.
slice(points));
1295void CurvesGeometry::translate(
const float3 &translation)
1301 std::optional<Bounds<float3>>
bounds;
1316 bounds->min += translation;
1317 bounds->max += translation;
1336std::optional<Bounds<float3>> CurvesGeometry::bounds_min_max(
const bool use_radius)
const
1339 return std::nullopt;
1344 if (
const std::optional radius_single =
radius.get_if_single()) {
1346 r_bounds.
pad(*radius_single);
1349 const Span radius_span =
radius.get_internal_span();
1369std::optional<int> CurvesGeometry::material_index_max()
const
1376 if (r_max_material_index.has_value()) {
1377 r_max_material_index = std::clamp(*r_max_material_index, 0,
MAXMAT);
1387 this->nurbs_custom_knots().size_in_bytes());
1402 const IndexMask custom_knot_curves =
curves.nurbs_custom_knot_curves(memory);
1404 points_by_curve, custom_knot_curves, memory);
1406 points_to_copy, custom_knot_points, memory);
1408 int dst_knot_count = 0;
1411 curve_point_counts[curve], orders[curve], cyclic[curve]);
1417 new_knots.
reserve(dst_knot_count);
1420 custom_knot_points_to_copy,
1423 const IndexRange src_range = src_knots_by_curve[curve];
1424 const int order = orders[curve];
1425 const int leading_spans = order / 2;
1426 const int point_to_knot = -points.
start() + src_range.
start();
1427 const int point_to_span = point_to_knot + leading_spans;
1429 const int first_knot = ranges_to_copy.
first().start() + point_to_knot;
1432 float last_knot = new_knots.
last();
1434 for (
const int spans_left_knot : range.shift(point_to_span)) {
1435 last_knot += src_knots[spans_left_knot + 1] - src_knots[spans_left_knot];
1436 new_knots.
append(last_knot);
1439 const int last_spans_left_knot = ranges_to_copy.last().last() + point_to_span + 1;
1440 last_knot += src_knots[last_spans_left_knot + 1] - src_knots[last_spans_left_knot];
1441 new_knots.
append(last_knot);
1454 [&](
const int64_t point_i) { curve_point_counts[point_to_curve_map[point_i]]++; });
1459 return curve_point_counts[
i] > 0;
1467 dst_curves.curves_num() > 1024,
1469 if (curves_to_copy.is_empty()) {
1474 curve_point_counts.
as_span(), curves_to_copy, new_curve_offsets.drop_back(1));
1478 gather_attributes(curves.attributes(),
1483 dst_curves.attributes_for_write());
1484 gather_attributes(curves.attributes(),
1489 dst_curves.attributes_for_write());
1492 if (curves.nurbs_has_custom_knots()) {
1493 copy_point_selection_custom_knots(curves, points_to_copy, curve_point_counts, dst_curves);
1496 if (dst_curves.curves_num() == curves.curves_num()) {
1497 dst_curves.runtime->type_counts = curves.runtime->type_counts;
1500 dst_curves.remove_attributes_based_on_types();
1506void CurvesGeometry::remove_points(
const IndexMask &points_to_delete,
1512 if (points_to_delete.
size() == this->points_num()) {
1527 const IndexMask custom_knot_curves =
curves.nurbs_custom_knot_curves(memory);
1529 curves_to_copy, custom_knot_curves, memory);
1531 Array<int> dst_knot_offsets_data(custom_knot_curves_to_copy.
size() + 1, 0);
1535 src_knots_by_curve, custom_knot_curves_to_copy, dst_knot_offsets_data);
1540 custom_knot_curves_to_copy,
1541 curves.nurbs_custom_knots(),
1565 dst_points_by_curve,
1576 if (
curves.nurbs_has_custom_knots()) {
1586void CurvesGeometry::remove_curves(
const IndexMask &curves_to_delete,
1592 if (curves_to_delete.
size() == this->curves_num()) {
1604 const float last = custom_knots.
last();
1606 for (
float &knot_value : custom_knots) {
1607 knot_value = last - knot_value;
1618 GrainSize(256), [&](
const int curve_i) {
data.slice(points_by_curve[curve_i]).reverse(); });
1629 const IndexRange points = points_by_curve[curve_i];
1633 const int end_index = points.
size() - 1 -
i;
1634 std::swap(a[end_index],
b[
i]);
1635 std::swap(
b[end_index], a[
i]);
1637 if (points.
size() % 2) {
1639 std::swap(a[middle_index],
b[middle_index]);
1644void CurvesGeometry::reverse_curves(
const IndexMask &curves_to_reverse)
1666 using T = decltype(dummy);
1667 reverse_curve_point_data<T>(*this, curves_to_reverse, attribute.span.typed<T>());
1677 const IndexRange curve_knots = custom_knots_by_curve[curve];
1707void CurvesGeometry::remove_attributes_based_on_types()
1729 curves.point_num = point_num;
1730 curves.attribute_storage.wrap().remove(
"position");
1756 for (const int i_curve : range) {
1757 for (const int i_point : points_by_curve[i_curve]) {
1758 mixer.mix_in(i_curve, old_values[i_point]);
1761 mixer.finalize(range);
1778 r_values.
fill(
true);
1780 for (
const int i_point : points_by_curve[i_curve]) {
1781 if (!old_values[i_point]) {
1782 r_values[i_curve] =
false;
1794 using T = decltype(dummy);
1795 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
1796 Array<T> values(curves.curves_num());
1797 adapt_curve_domain_point_to_curve_impl<T>(curves, varray.typed<T>(), values);
1798 new_varray = VArray<T>::from_container(std::move(values));
1818 r_values.
slice(points_by_curve[i_curve]).
fill(old_values[i_curve]);
1827 using T = decltype(dummy);
1828 Array<T> values(curves.points_num());
1829 adapt_curve_domain_curve_to_point_impl<T>(curves, varray.typed<T>(), values);
1830 new_varray = VArray<T>::from_container(std::move(values));
1883 this->runtime = MEM_new<blender::bke::CurvesGeometryRuntime>(__func__);
1901 &reader, &this->custom_knots, [&]() {
1919void CurvesGeometry::blend_write_prepare(CurvesGeometry::BlendWriteData &write_data)
1926 write_data.point_layers,
1927 write_data.attribute_data);
1928 if (write_data.attribute_data.attributes.is_empty()) {
1933 this->
attribute_storage.dna_attributes = write_data.attribute_data.attributes.data();
1934 this->
attribute_storage.dna_attributes_num = write_data.attribute_data.attributes.size();
1940 const CurvesGeometry::BlendWriteData &write_data)
1952 [&]() { BLO_write_int32_array(&writer, this->curve_num + 1, this->curve_offsets); });
1963 [&]() { 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)
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
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)
#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)
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
#define CD_MASK_MDEFORMVERT
Object is a sort of wrapper for general info.
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(int64_t start, int64_t size) const
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
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 from_single(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
constexpr bool is_empty() 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 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
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
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
SharedCache< bool > has_cyclic_curve_cache
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
std::optional< Span< float > > nurbs_weights() const
void nurbs_custom_knots_update_size()
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
std::optional< Span< float3 > > handle_positions_left() const
Span< float3 > positions() const
OffsetIndices< int > evaluated_points_by_curve() const
bool has_curve_with_type(CurveType type) const
std::optional< Span< float3 > > handle_positions_right() const
void tag_topology_changed()
void resize(int points_num, int curves_num)
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 add(const StringRef attribute_id, const AttrDomain domain, const AttrType data_type, const AttributeInit &initializer)
bool remove(const StringRef attribute_id)
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)
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)
bool contains(const VArray< bool > &varray, const IndexMask &indices_to_check, bool value)
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, Span< float > knots)
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)
void foreach_selected_point_ranges_per_curve(const IndexMask &mask, OffsetIndices< int > points_by_curve, SelectedCallback selected_fn)
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)
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 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
GMutableSpan get_mutable_attribute(AttributeStorage &storage, const AttrDomain domain, const CPPType &cpp_type, const StringRef name, const int64_t domain_size, const void *custom_default_value)
static void copy_point_selection_custom_knots(const CurvesGeometry &curves, const IndexMask &points_to_copy, const Span< int > curve_point_counts, CurvesGeometry &dst_curves)
void attribute_storage_blend_write_prepare(AttributeStorage &data, AttributeStorage::BlendWriteData &write_data)
std::optional< GSpan > get_span_attribute(const AttributeStorage &storage, const AttrDomain domain, const CPPType &cpp_type, const StringRef name, const int64_t domain_size)
constexpr StringRef ATTR_CURVE_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)
GVArray get_varray_attribute(const AttributeStorage &storage, AttrDomain domain, const CPPType &cpp_type, StringRef name, int64_t domain_size, const void *default_value)
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)
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 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
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)
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 transform_points(const float4x4 &transform, MutableSpan< float3 > points, bool use_threading=true)
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)
CustomData curve_data_legacy
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< 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
const std::optional< Span< float > > nurbs_weights