60CurvesGeometry::CurvesGeometry(
const int point_num,
const int curve_num)
62 this->
runtime = MEM_new<CurvesGeometryRuntime>(__func__);
96 if (other.runtime->curve_offsets_sharing_info) {
97 other.runtime->curve_offsets_sharing_info->add_user();
111 this->
runtime = MEM_new<CurvesGeometryRuntime>(
114 other.runtime->type_counts,
115 other.runtime->evaluated_offsets_cache,
116 other.runtime->nurbs_basis_cache,
117 other.runtime->evaluated_position_cache,
118 other.runtime->bounds_cache,
119 other.runtime->evaluated_length_cache,
120 other.runtime->evaluated_tangent_cache,
121 other.runtime->evaluated_normal_cache,
125 if (other.runtime->bake_materials) {
126 this->
runtime->bake_materials = std::make_unique<bake::BakeMaterialsList>(
127 *other.runtime->bake_materials);
133 if (
this == &other) {
136 std::destroy_at(
this);
144 other.curve_offsets =
nullptr;
162 other.vertex_group_active_index = 0;
165 other.attributes_active_index = 0;
168 other.runtime =
nullptr;
173 if (
this == &other) {
176 std::destroy_at(
this);
181CurvesGeometry::~CurvesGeometry()
188 &this->
runtime->curve_offsets_sharing_info);
218 const T default_value)
225 if (data !=
nullptr) {
241 if (data ==
nullptr) {
251 const T default_value =
T())
261 if (data !=
nullptr) {
266 if (num > 0 && span.
first() != default_value) {
267 span.
fill(default_value);
283void CurvesGeometry::fill_curve_types(
const CurveType type)
293 this->
runtime->type_counts.fill(0);
300 if (selection.size() == this->curves_num()) {
304 if (std::optional<int8_t> single_type = this->
curve_types().get_if_single()) {
305 if (single_type == type) {
318 using CountsType = std::array<int, CURVE_TYPES_NUM>;
322 if (types.is_single()) {
323 counts[types.get_internal_single()] = types.size();
333 CountsType result = init;
334 for (const int curve_index : curves_range) {
335 result[types_span[curve_index]]++;
339 [](
const CountsType &a,
const CountsType &
b) {
340 CountsType result = a;
348void CurvesGeometry::update_curve_types()
355 return get_span_attribute<float3>(*
this, AttrDomain::Point,
ATTR_POSITION);
359 return get_mutable_attribute<float3>(*
this, AttrDomain::Point,
ATTR_POSITION);
364 if (this->curve_num == 0) {
367 return {this->curve_offsets, this->curve_num + 1};
371 if (this->curve_num == 0) {
375 &this->curve_offsets, &this->runtime->curve_offsets_sharing_info, this->curve_num + 1);
376 return {this->curve_offsets, this->curve_num + 1};
381 return get_varray_attribute<bool>(*
this, AttrDomain::Curve,
ATTR_CYCLIC,
false);
385 return get_mutable_attribute<bool>(*
this, AttrDomain::Curve,
ATTR_CYCLIC,
false);
390 return get_varray_attribute<int>(*
this, AttrDomain::Curve,
ATTR_RESOLUTION, 12);
394 return get_mutable_attribute<int>(*
this, AttrDomain::Curve,
ATTR_RESOLUTION, 12);
399 return get_varray_attribute<int8_t>(*
this, AttrDomain::Curve,
ATTR_NORMAL_MODE, 0);
403 return get_mutable_attribute<int8_t>(*
this, AttrDomain::Curve,
ATTR_NORMAL_MODE);
408 return get_varray_attribute<float>(*
this, AttrDomain::Point,
ATTR_TILT, 0.0f);
412 return get_mutable_attribute<float>(*
this, AttrDomain::Point,
ATTR_TILT);
453 return get_varray_attribute<int8_t>(*
this, AttrDomain::Curve,
ATTR_NURBS_ORDER, 4);
457 return get_mutable_attribute<int8_t>(*
this, AttrDomain::Curve,
ATTR_NURBS_ORDER, 4);
466 return get_mutable_attribute<float>(*
this, AttrDomain::Point,
ATTR_NURBS_WEIGHT);
492 if (dverts ==
nullptr) {
495 return {dverts, this->point_num};
502 if (dvert !=
nullptr) {
503 return {dvert, this->point_num};
521 offset += count_fn(i);
523 offsets.
last() = offset;
530 const OffsetIndices points_by_curve = curves.points_by_curve();
532 const VArray<int> resolution = curves.resolution();
538 handle_types_left = curves.handle_types_left();
539 handle_types_right = curves.handle_types_right();
543 const VArray<int8_t> nurbs_knots_modes = curves.nurbs_knots_modes();
546 const IndexRange points = points_by_curve[curve_index];
547 switch (types[curve_index]) {
549 return curves::catmull_rom::calculate_evaluated_num(
550 points.size(), cyclic[curve_index], resolution[curve_index]);
552 return points.size();
554 const IndexRange offsets = curves::per_curve_point_offsets_range(points, curve_index);
555 curves::bezier::calculate_evaluated_offsets(handle_types_left.
slice(points),
556 handle_types_right.
slice(points),
558 resolution[curve_index],
559 all_bezier_offsets.
slice(offsets));
560 return all_bezier_offsets[offsets.
last()];
563 return curves::nurbs::calculate_evaluated_num(points.size(),
564 nurbs_orders[curve_index],
566 resolution[curve_index],
567 KnotsMode(nurbs_knots_modes[curve_index]));
584 return this->points_by_curve();
606 return this->indices_for_curve_type(type, this->curves_range(), memory);
613 return curves::indices_for_type(
614 this->curve_types(), this->curve_type_counts(), type, selection, memory);
624void CurvesGeometry::ensure_nurbs_basis_cache()
const
635 r_data.
resize(this->curves_num());
638 const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
645 for (
const int curve_index : segment) {
646 const IndexRange points = points_by_curve[curve_index];
647 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
649 const int8_t order = orders[curve_index];
650 const bool is_cyclic = cyclic[curve_index];
653 if (!curves::nurbs::check_valid_num_and_order(points.size(), order,
is_cyclic, mode)) {
654 r_data[curve_index].invalid =
true;
659 curves::nurbs::calculate_knots(points.size(), mode, order,
is_cyclic, knots);
660 curves::nurbs::calculate_basis_cache(
661 points.size(), evaluated_points.
size(), order,
is_cyclic, knots, r_data[curve_index]);
673 return this->positions();
675 this->ensure_nurbs_basis_cache();
677 r_data.
resize(this->evaluated_points_num());
681 const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
687 selection.foreach_index(
GrainSize(128), [&](
const int curve_index) {
688 const IndexRange points = points_by_curve[curve_index];
689 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
690 curves::catmull_rom::interpolate_to_evaluated(positions.slice(points),
692 resolution[curve_index],
693 evaluated_positions.
slice(evaluated_points));
698 points_by_curve, evaluated_points_by_curve, selection, positions, evaluated_positions);
701 const Span<float3> handle_positions_left = this->handle_positions_left();
702 const Span<float3> handle_positions_right = this->handle_positions_right();
703 if (handle_positions_left.
is_empty() || handle_positions_right.
is_empty()) {
704 curves::fill_points(evaluated_points_by_curve, selection,
float3(0), evaluated_positions);
709 selection.foreach_index(
GrainSize(128), [&](
const int curve_index) {
710 const IndexRange points = points_by_curve[curve_index];
711 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
712 const IndexRange offsets = curves::per_curve_point_offsets_range(points, curve_index);
713 curves::bezier::calculate_evaluated_positions(positions.slice(points),
714 handle_positions_left.
slice(points),
715 handle_positions_right.
slice(points),
716 all_bezier_offsets.
slice(offsets),
717 evaluated_positions.
slice(evaluated_points));
721 this->ensure_nurbs_basis_cache();
723 const Span<float> nurbs_weights = this->nurbs_weights();
725 selection.foreach_index(
GrainSize(128), [&](
const int curve_index) {
726 const IndexRange points = points_by_curve[curve_index];
727 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
728 curves::nurbs::interpolate_to_evaluated(nurbs_basis_cache[curve_index],
729 nurbs_orders[curve_index],
731 positions.
slice(points),
732 evaluated_positions.
slice(evaluated_points));
735 curves::foreach_curve_by_type(this->curve_types(),
736 this->curve_type_counts(),
737 this->curves_range(),
750 const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
751 const Span<float3> evaluated_positions = this->evaluated_positions();
754 r_data.
resize(this->evaluated_points_num());
758 for (
const int curve_index : curves_range) {
759 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
760 curves::poly::calculate_tangents(evaluated_positions.
slice(evaluated_points),
762 tangents.
slice(evaluated_points));
774 const Span<float3> handles_left = this->handle_positions_left();
775 const Span<float3> handles_right = this->handle_positions_right();
778 if (cyclic[curve_index]) {
781 const IndexRange points = points_by_curve[curve_index];
782 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
784 const float epsilon = 1e-6f;
786 handles_right[points.first()], positions[points.first()], epsilon))
788 tangents[evaluated_points.first()] = math::normalize(handles_right[points.first()] -
789 positions[points.first()]);
792 handles_left[points.last()], positions[points.last()], epsilon))
794 tangents[evaluated_points.last()] = math::normalize(positions[points.last()] -
795 handles_left[points.last()]);
808 const float3 axis = axes[i];
818 for (
const int i : data.index_range()) {
836 const int curve_index,
841 switch (eval_data.
types[curve_index]) {
843 curves::catmull_rom::interpolate_to_evaluated(
844 src, eval_data.
cyclic[curve_index], eval_data.
resolution[curve_index], dst);
850 const IndexRange offsets = curves::per_curve_point_offsets_range(points, curve_index);
851 curves::bezier::interpolate_to_evaluated(
856 curves::nurbs::interpolate_to_evaluated(eval_data.
nurbs_basis_cache[curve_index],
868 this->ensure_nurbs_basis_cache();
871 const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
875 const Span<float3> evaluated_tangents = this->evaluated_tangents();
884 this->nurbs_orders(),
885 this->nurbs_weights(),
889 const bool use_tilt = !(tilt.is_single() && tilt.get_internal_single() == 0.0f);
897 custom_normal_span = custom_normal;
900 r_data.
resize(this->evaluated_points_num());
907 for (
const int curve_index : curves_range) {
908 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
909 switch (
NormalMode(normal_mode[curve_index])) {
911 curves::poly::calculate_normals_z_up(evaluated_tangents.
slice(evaluated_points),
912 evaluated_normals.
slice(evaluated_points));
915 curves::poly::calculate_normals_minimum(evaluated_tangents.
slice(evaluated_points),
917 evaluated_normals.
slice(evaluated_points));
920 if (custom_normal_span.
is_empty()) {
921 curves::poly::calculate_normals_z_up(evaluated_tangents.
slice(evaluated_points),
922 evaluated_normals.
slice(evaluated_points));
927 evaluated_points_by_curve[curve_index]);
937 const IndexRange points = points_by_curve[curve_index];
940 evaluated_tangents.
slice(evaluated_points),
941 tilt_span.
slice(points));
947 tilt_span.
slice(points),
950 evaluated_tangents.
slice(evaluated_points),
960void CurvesGeometry::interpolate_to_evaluated(
const int curve_index,
966 this->points_by_curve(),
972 this->nurbs_orders(),
973 this->nurbs_weights(),
975 BLI_assert(src.
size() == this->points_by_curve()[curve_index].size());
976 BLI_assert(dst.
size() == this->evaluated_points_by_curve()[curve_index].size());
983 const OffsetIndices points_by_curve = this->points_by_curve();
991 this->nurbs_orders(),
992 this->nurbs_weights(),
994 const OffsetIndices evaluated_points_by_curve = this->evaluated_points_by_curve();
997 for (
const int curve_index : curves_range) {
998 const IndexRange points = points_by_curve[curve_index];
999 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
1001 eval_data, curve_index, src.
slice(points), dst.
slice(evaluated_points));
1006void CurvesGeometry::ensure_evaluated_lengths()
const
1012 const int total_num = this->evaluated_points_num() + this->curves_num();
1013 r_data.
resize(total_num);
1016 const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
1017 const Span<float3> evaluated_positions = this->evaluated_positions();
1021 for (
const int curve_index : curves_range) {
1022 const bool cyclic = curves_cyclic[curve_index];
1023 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
1024 const IndexRange lengths_range = this->lengths_range_for_curve(curve_index, cyclic);
1027 evaluated_lengths.
slice(lengths_range));
1033void CurvesGeometry::ensure_can_interpolate_to_evaluated()
const
1035 this->evaluated_points_by_curve();
1036 this->ensure_nurbs_basis_cache();
1045void CurvesGeometry::resize(
const int points_num,
const int curves_num)
1047 if (points_num != this->point_num) {
1049 this->point_num = points_num;
1051 if (curves_num != this->curve_num) {
1055 this->curve_num == 0 ? 0 : (this->curve_num + 1),
1058 this->curve_offsets[0] = 0;
1059 this->curve_offsets[curves_num] = this->point_num;
1060 this->curve_num = curves_num;
1062 this->tag_topology_changed();
1065void CurvesGeometry::tag_positions_changed()
1073void CurvesGeometry::tag_topology_changed()
1075 this->tag_positions_changed();
1080void CurvesGeometry::tag_normals_changed()
1084void CurvesGeometry::tag_radii_changed() {}
1089 for (float3 &position : positions.slice(range)) {
1090 position += translation;
1098 for (float3 &position : positions.slice(range)) {
1099 position = math::transform_point(matrix, position);
1108 for (float3 &normal : normals.slice(range)) {
1109 normal = normal_transform * normal;
1114void CurvesGeometry::calculate_bezier_auto_handles()
1119 if (this->handle_positions_left().is_empty() || this->handle_positions_right().is_empty()) {
1122 const OffsetIndices points_by_curve = this->points_by_curve();
1132 for (
const int i_curve :
range) {
1134 const IndexRange points = points_by_curve[i_curve];
1135 curves::bezier::calculate_auto_handles(cyclic[i_curve],
1136 types_left.slice(points),
1137 types_right.slice(points),
1138 positions.slice(points),
1139 positions_left.
slice(points),
1140 positions_right.
slice(points));
1146void CurvesGeometry::translate(
const float3 &translation)
1152 std::optional<Bounds<float3>> bounds;
1158 if (!this->handle_positions_left().is_empty()) {
1161 if (!this->handle_positions_right().is_empty()) {
1164 this->tag_positions_changed();
1167 bounds->min += translation;
1168 bounds->max += translation;
1176 if (!this->handle_positions_left().is_empty()) {
1179 if (!this->handle_positions_right().is_empty()) {
1187 this->tag_positions_changed();
1190std::optional<Bounds<float3>> CurvesGeometry::bounds_min_max()
const
1192 if (this->points_num() == 0) {
1193 return std::nullopt;
1211 const Array<int> point_to_curve_map = curves.point_to_curve_map();
1212 Array<int> curve_point_counts(curves.curves_num(), 0);
1214 [&](
const int64_t point_i) { curve_point_counts[point_to_curve_map[point_i]]++; });
1219 return curve_point_counts[i] > 0;
1227 dst_curves.curves_num() > 1024,
1229 if (curves_to_copy.is_empty()) {
1234 curve_point_counts.
as_span(), curves_to_copy, new_curve_offsets.drop_back(1));
1238 gather_attributes(curves.attributes(),
1243 dst_curves.attributes_for_write());
1244 gather_attributes(curves.attributes(),
1249 dst_curves.attributes_for_write());
1252 if (dst_curves.curves_num() == curves.curves_num()) {
1253 dst_curves.runtime->type_counts = curves.runtime->type_counts;
1256 dst_curves.remove_attributes_based_on_types();
1262void CurvesGeometry::remove_points(
const IndexMask &points_to_delete,
1268 if (points_to_delete.
size() == this->points_num()) {
1273 const IndexMask points_to_copy = points_to_delete.
complement(this->points_range(), memory);
1281 const OffsetIndices points_by_curve = curves.points_by_curve();
1297 dst_points_by_curve,
1314void CurvesGeometry::remove_curves(
const IndexMask &curves_to_delete,
1320 if (curves_to_delete.
size() == this->curves_num()) {
1325 const IndexMask curves_to_copy = curves_to_delete.
complement(this->curves_range(), memory);
1334 const OffsetIndices points_by_curve = curves.points_by_curve();
1336 GrainSize(256), [&](
const int curve_i) { data.slice(points_by_curve[curve_i]).reverse(); });
1345 const OffsetIndices points_by_curve = curves.points_by_curve();
1347 const IndexRange points = points_by_curve[curve_i];
1350 for (
const int i :
IndexRange(points.size() / 2)) {
1351 const int end_index = points.
size() - 1 - i;
1352 std::swap(a[end_index],
b[i]);
1353 std::swap(
b[end_index], a[i]);
1355 if (points.size() % 2) {
1356 const int64_t middle_index = points.size() / 2;
1357 std::swap(a[middle_index],
b[middle_index]);
1362void CurvesGeometry::reverse_curves(
const IndexMask &curves_to_reverse)
1371 attributes.foreach_attribute([&](
const AttributeIter &iter) {
1372 if (iter.
domain != AttrDomain::Point) {
1378 if (bezier_handle_names.contains(iter.
name)) {
1383 attribute_math::convert_to_static_type(attribute.span.type(), [&](
auto dummy) {
1384 using T = decltype(dummy);
1385 reverse_curve_point_data<T>(*this, curves_to_reverse, attribute.span.typed<T>());
1401 this->handle_positions_left_for_write(),
1402 this->handle_positions_right_for_write());
1407 this->handle_types_left_for_write(),
1408 this->handle_types_right_for_write());
1411 this->tag_topology_changed();
1414void CurvesGeometry::remove_attributes_based_on_types()
1436 curves.point_num = point_num;
1461 const OffsetIndices points_by_curve = curves.points_by_curve();
1463 for (const int i_curve : range) {
1464 for (const int i_point : points_by_curve[i_curve]) {
1465 mixer.mix_in(i_curve, old_values[i_point]);
1468 mixer.finalize(range);
1484 const OffsetIndices points_by_curve = curves.points_by_curve();
1485 r_values.
fill(
true);
1486 for (
const int i_curve :
IndexRange(curves.curves_num())) {
1487 for (
const int i_point : points_by_curve[i_curve]) {
1488 if (!old_values[i_point]) {
1489 r_values[i_curve] =
false;
1500 attribute_math::convert_to_static_type(varray.
type(), [&](
auto dummy) {
1501 using T = decltype(dummy);
1502 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
1503 Array<T> values(curves.curves_num());
1504 adapt_curve_domain_point_to_curve_impl<T>(curves, varray.typed<T>(), values);
1505 new_varray = VArray<T>::ForContainer(std::move(values));
1523 const OffsetIndices points_by_curve = curves.points_by_curve();
1524 for (
const int i_curve :
IndexRange(curves.curves_num())) {
1525 r_values.
slice(points_by_curve[i_curve]).
fill(old_values[i_curve]);
1533 attribute_math::convert_to_static_type(varray.
type(), [&](
auto dummy) {
1534 using T = decltype(dummy);
1535 Array<T> values(curves.points_num());
1536 adapt_curve_domain_curve_to_point_impl<T>(curves, varray.typed<T>(), values);
1537 new_varray = VArray<T>::ForContainer(std::move(values));
1561 if (from == AttrDomain::Point && to == AttrDomain::Curve) {
1564 if (from == AttrDomain::Curve && to == AttrDomain::Point) {
1580 this->runtime = MEM_new<blender::bke::CurvesGeometryRuntime>(__func__);
1585 if (this->curve_offsets) {
1587 &reader, &this->curve_offsets, [&]() {
1596 this->update_curve_types();
1599CurvesGeometry::BlendWriteData CurvesGeometry::blend_write_prepare()
1601 CurvesGeometry::BlendWriteData write_data;
1609 const CurvesGeometry::BlendWriteData &write_data)
1612 &writer, &this->point_data, write_data.point_layers, this->point_num,
CD_MASK_ALL, &
id);
1614 &writer, &this->curve_data, write_data.curve_layers, this->curve_num,
CD_MASK_ALL, &
id);
1616 if (this->curve_offsets) {
1619 this->curve_offsets,
1620 sizeof(
int) * (this->curve_num + 1),
1622 [&]() { BLO_write_int32_array(&writer, this->curve_num + 1, this->curve_offsets); });
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::Vector< CustomDataLayer, 16 > &layers_to_write, const blender::Set< std::string > &skip_names={})
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)
bool CustomData_free_layer_named(CustomData *data, blender::StringRef name, const 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_init_from(const CustomData *source, CustomData *dest, eCustomDataMask mask, int totelem)
void CustomData_free(CustomData *data, 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(struct ListBase *lb)
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
void BLO_read_int32_array(BlendDataReader *reader, int 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.
static const char * ATTR_POSITION
static void translate_positions(MutableSpan< float3 > positions, const float3 &translation)
Span< T > as_span() const
static const CPPType & get()
void copy_from(GSpan values)
GMutableSpan slice(const int64_t start, int64_t size) 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)
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr int64_t size() 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 T & first() const
constexpr IndexRange index_range() const
constexpr T & last(const int64_t n=0) const
constexpr Span slice_safe(const int64_t start, const int64_t size) const
constexpr Span slice(int64_t start, int64_t size) const
constexpr bool is_empty() const
static VArray ForSingle(T value, const int64_t size)
static VArray ForSpan(Span< T > values)
void resize(const int64_t new_size)
MutableSpan< T > as_mutable_span()
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< Vector< float3 > > evaluated_tangent_cache
SharedCache< EvaluatedOffsets > evaluated_offsets_cache
SharedCache< Vector< float3 > > evaluated_normal_cache
SharedCache< Bounds< float3 > > bounds_cache
SharedCache< Vector< float3 > > evaluated_position_cache
const ImplicitSharingInfo * curve_offsets_sharing_info
void remove_attributes_based_on_types()
void update_curve_types()
MutableSpan< int8_t > curve_types_for_write()
MutableAttributeAccessor attributes_for_write()
void tag_topology_changed()
void resize(int points_num, int curves_num)
void fill_curve_types(CurveType type)
MutableSpan< int > offsets_for_write()
VArray< int8_t > curve_types() const
bool remove(const StringRef attribute_id)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
static IndexMask from_predicate(const IndexMask &universe, GrainSize grain_size, IndexMaskMemory &memory, Fn &&predicate)
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)
local_group_size(16, 16) .push_constant(Type b
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(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
typename DefaultMixerStruct< T >::type DefaultMixer
static void normalize_span(MutableSpan< float3 > data)
static CustomData & domain_custom_data(CurvesGeometry &curves, const AttrDomain domain)
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)
static const std::string ATTR_HANDLE_POSITION_RIGHT
static MutableSpan< T > get_mutable_attribute(CurvesGeometry &curves, const AttrDomain domain, const StringRef name, const T default_value=T())
static VArray< T > get_varray_attribute(const CurvesGeometry &curves, const AttrDomain domain, const StringRef name, const T default_value)
static const std::string ATTR_NURBS_WEIGHT
eCustomDataType cpp_type_to_custom_data_type(const CPPType &type)
static const std::string ATTR_HANDLE_TYPE_RIGHT
static const std::string ATTR_NURBS_KNOTS_MODE
static const std::string ATTR_RADIUS
static GVArray adapt_curve_domain_point_to_curve(const CurvesGeometry &curves, const GVArray &varray)
static const std::string ATTR_NORMAL_MODE
void gather_attributes(AttributeAccessor src_attributes, AttrDomain src_domain, AttrDomain dst_domain, const AttributeFilter &attribute_filter, const IndexMask &selection, MutableAttributeAccessor dst_attributes)
static const std::string ATTR_POSITION
static const std::string ATTR_HANDLE_TYPE_LEFT
CurvesGeometry curves_new_no_attributes(int point_num, int curve_num)
static const std::string ATTR_CYCLIC
static const std::string ATTR_SURFACE_UV_COORDINATE
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 transform_normals(MutableSpan< float3 > normals, const float4x4 &matrix)
static const std::string ATTR_RESOLUTION
static const std::string ATTR_TILT
static const std::string ATTR_CURVE_TYPE
static Span< T > get_span_attribute(const CurvesGeometry &curves, const AttrDomain domain, const StringRef name)
static const std::string ATTR_HANDLE_POSITION_LEFT
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)
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 const std::string ATTR_NURBS_ORDER
static void reverse_swap_curve_point_data(const CurvesGeometry &curves, const IndexMask &curve_selection, MutableSpan< T > data_a, MutableSpan< T > data_b)
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)
static void rotate_directions_around_axes(MutableSpan< float3 > directions, const Span< float3 > axes, const Span< float > angles)
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(const std::optional< Bounds< T > > &a, const T &b)
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)
MatBase< T, NumCol, NumRow > transpose(const MatBase< T, NumRow, NumCol > &mat)
CartesianBasis invert(const CartesianBasis &basis)
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, 3, 3 > float3x3
VecBase< float, 3 > float3
GPU_SHADER_INTERFACE_INFO(overlay_edit_curve_handle_iface, "vert").flat(Type pos vertex_in(1, Type::UINT, "data") .vertex_out(overlay_edit_curve_handle_iface) .geometry_layout(PrimitiveIn Frequency::GEOMETRY storage_buf(1, Qualifier::READ, "uint", "data[]", Frequency::GEOMETRY) .push_constant(Type Frequency::GEOMETRY selection[]
int vertex_group_active_index
CurvesGeometryRuntimeHandle * runtime
ListBase vertex_group_names
int attributes_active_index
Vector< int > all_bezier_offsets
Vector< int > evaluated_offsets
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