64CurvesGeometry::CurvesGeometry(
const int point_num,
const int curve_num)
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()
404 if (this->curve_num == 0) {
407 return {this->curve_offsets, this->curve_num + 1};
411 if (this->curve_num == 0) {
415 &this->curve_offsets, &this->runtime->curve_offsets_sharing_info,
this->curve_num + 1);
416 return {this->curve_offsets, this->curve_num + 1};
530 if (this->custom_knot_num == 0) {
533 return {this->custom_knots, this->custom_knot_num};
538 if (this->custom_knot_num == 0) {
542 &this->custom_knots, &this->runtime->custom_knots_sharing_info,
this->custom_knot_num);
543 return {this->custom_knots, this->custom_knot_num};
560 if (this->is_empty()) {
564 r_data.
resize(this->curve_num + 1, 0);
566 const OffsetIndices points_by_curve = this->points_by_curve();
571 for (
const int curve : this->curves_range()) {
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();
586 if (this->custom_knot_num != knots_num) {
588 &this->runtime->custom_knots_sharing_info,
589 this->custom_knot_num,
591 this->custom_knot_num = knots_num;
595void CurvesGeometry::nurbs_custom_knots_resize(
int knots_num)
598 &this->runtime->custom_knots_sharing_info,
599 this->custom_knot_num,
601 this->custom_knot_num = knots_num;
602 this->runtime->custom_knot_offsets_cache.tag_dirty();
609 if (dverts ==
nullptr) {
612 return {dverts, this->point_num};
619 if (dvert !=
nullptr) {
620 return {dvert, this->point_num};
638 offset += count_fn(i);
640 offsets.
last() = offset;
663 const IndexRange points = points_by_curve[curve_index];
664 switch (
types[curve_index]) {
666 return curves::catmull_rom::calculate_evaluated_num(
667 points.
size(), cyclic[curve_index], resolution[curve_index]);
669 return points.
size();
671 const IndexRange offsets = curves::per_curve_point_offsets_range(points, curve_index);
672 curves::bezier::calculate_evaluated_offsets(handle_types_left.
slice(points),
673 handle_types_right.
slice(points),
675 resolution[curve_index],
676 all_bezier_offsets.
slice(offsets));
677 return all_bezier_offsets[offsets.
last()];
680 return curves::nurbs::calculate_evaluated_num(points.
size(),
681 nurbs_orders[curve_index],
683 resolution[curve_index],
684 KnotsMode(nurbs_knots_modes[curve_index]));
701 return this->points_by_curve();
723 return this->indices_for_curve_type(type, this->curves_range(), memory);
730 return curves::indices_for_type(
731 this->curve_types(), this->curve_type_counts(), type, selection, memory);
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]);
799 return this->positions();
801 this->ensure_nurbs_basis_cache();
803 r_data.
resize(this->evaluated_points_num());
807 const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
810 auto evaluate_catmull = [&](
const IndexMask &selection) {
813 selection.foreach_index(
GrainSize(128), [&](
const int curve_index) {
814 const IndexRange points = points_by_curve[curve_index];
815 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
816 curves::catmull_rom::interpolate_to_evaluated(positions.
slice(points),
818 resolution[curve_index],
819 evaluated_positions.
slice(evaluated_points));
822 auto evaluate_poly = [&](
const IndexMask &selection) {
824 points_by_curve, evaluated_points_by_curve, selection, positions, evaluated_positions);
826 auto evaluate_bezier = [&](
const IndexMask &selection) {
827 const Span<float3> handle_positions_left = this->handle_positions_left();
828 const Span<float3> handle_positions_right = this->handle_positions_right();
829 if (handle_positions_left.
is_empty() || handle_positions_right.
is_empty()) {
830 curves::fill_points(evaluated_points_by_curve, selection,
float3(0), evaluated_positions);
835 selection.foreach_index(
GrainSize(128), [&](
const int curve_index) {
836 const IndexRange points = points_by_curve[curve_index];
837 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
838 const IndexRange offsets = curves::per_curve_point_offsets_range(points, curve_index);
839 curves::bezier::calculate_evaluated_positions(positions.
slice(points),
840 handle_positions_left.
slice(points),
841 handle_positions_right.
slice(points),
842 all_bezier_offsets.
slice(offsets),
843 evaluated_positions.
slice(evaluated_points));
846 auto evaluate_nurbs = [&](
const IndexMask &selection) {
847 this->ensure_nurbs_basis_cache();
849 const Span<float> nurbs_weights = this->nurbs_weights();
851 selection.foreach_index(
GrainSize(128), [&](
const int curve_index) {
852 const IndexRange points = points_by_curve[curve_index];
853 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
854 curves::nurbs::interpolate_to_evaluated(nurbs_basis_cache[curve_index],
855 nurbs_orders[curve_index],
857 positions.
slice(points),
858 evaluated_positions.
slice(evaluated_points));
861 curves::foreach_curve_by_type(this->curve_types(),
862 this->curve_type_counts(),
863 this->curves_range(),
876 const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
877 const Span<float3> evaluated_positions = this->evaluated_positions();
880 r_data.
resize(this->evaluated_points_num());
884 for (
const int curve_index : curves_range) {
885 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
886 curves::poly::calculate_tangents(evaluated_positions.
slice(evaluated_points),
888 tangents.
slice(evaluated_points));
900 const Span<float3> handles_left = this->handle_positions_left();
901 const Span<float3> handles_right = this->handle_positions_right();
904 if (cyclic[curve_index]) {
907 const IndexRange points = points_by_curve[curve_index];
908 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
910 const float epsilon = 1e-6f;
912 handles_right[points.
first()], positions[points.
first()], epsilon))
914 tangents[evaluated_points.first()] = math::normalize(handles_right[points.first()] -
915 positions[points.first()]);
918 handles_left[points.
last()], positions[points.
last()], epsilon))
920 tangents[evaluated_points.last()] = math::normalize(positions[points.last()] -
921 handles_left[points.last()]);
934 const float3 axis = axes[i];
944 for (
const int i :
data.index_range()) {
962 const int curve_index,
967 switch (eval_data.
types[curve_index]) {
969 curves::catmull_rom::interpolate_to_evaluated(
970 src, eval_data.
cyclic[curve_index], eval_data.
resolution[curve_index], dst);
976 const IndexRange offsets = curves::per_curve_point_offsets_range(points, curve_index);
977 curves::bezier::interpolate_to_evaluated(
982 curves::nurbs::interpolate_to_evaluated(eval_data.
nurbs_basis_cache[curve_index],
994 this->ensure_nurbs_basis_cache();
997 const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
1001 const Span<float3> evaluated_tangents = this->evaluated_tangents();
1010 this->nurbs_orders(),
1011 this->nurbs_weights(),
1023 custom_normal_span = custom_normal;
1026 r_data.
resize(this->evaluated_points_num());
1033 for (
const int curve_index : curves_range) {
1034 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
1035 switch (
NormalMode(normal_mode[curve_index])) {
1037 curves::poly::calculate_normals_z_up(evaluated_tangents.
slice(evaluated_points),
1038 evaluated_normals.
slice(evaluated_points));
1041 curves::poly::calculate_normals_minimum(evaluated_tangents.
slice(evaluated_points),
1042 cyclic[curve_index],
1043 evaluated_normals.
slice(evaluated_points));
1046 if (custom_normal_span.
is_empty()) {
1047 curves::poly::calculate_normals_z_up(evaluated_tangents.
slice(evaluated_points),
1048 evaluated_normals.
slice(evaluated_points));
1051 const Span<float3> src = custom_normal_span.
slice(points_by_curve[curve_index]);
1053 evaluated_points_by_curve[curve_index]);
1063 const IndexRange points = points_by_curve[curve_index];
1066 evaluated_tangents.
slice(evaluated_points),
1067 tilt_span.
slice(points));
1073 tilt_span.
slice(points),
1076 evaluated_tangents.
slice(evaluated_points),
1086void CurvesGeometry::interpolate_to_evaluated(
const int curve_index,
1092 this->points_by_curve(),
1093 this->curve_types(),
1098 this->nurbs_orders(),
1099 this->nurbs_weights(),
1109 const OffsetIndices points_by_curve = this->points_by_curve();
1112 this->curve_types(),
1117 this->nurbs_orders(),
1118 this->nurbs_weights(),
1120 const OffsetIndices evaluated_points_by_curve = this->evaluated_points_by_curve();
1123 for (
const int curve_index : curves_range) {
1124 const IndexRange points = points_by_curve[curve_index];
1125 const IndexRange evaluated_points = evaluated_points_by_curve[curve_index];
1127 eval_data, curve_index, src.
slice(points), dst.
slice(evaluated_points));
1132void CurvesGeometry::ensure_evaluated_lengths()
const
1138 const int total_num = this->evaluated_points_num() + this->curves_num();
1139 r_data.
resize(total_num);
1142 const OffsetIndices<int> evaluated_points_by_curve = this->evaluated_points_by_curve();
1143 const Span<float3> evaluated_positions = this->evaluated_positions();
1147 for (
const int curve_index : curves_range) {
1148 const bool cyclic = curves_cyclic[curve_index];
1149 const IndexRange evaluated_points = evaluated_points_by_curve[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();
1171void CurvesGeometry::resize(
const int points_num,
const int curves_num)
1173 BLI_assert(curves_num >= 0 && points_num >= 0);
1174 if (points_num != this->point_num) {
1176 this->point_num = points_num;
1178 if (curves_num != this->curve_num) {
1182 this->curve_num == 0 ? 0 : (this->curve_num + 1),
1183 curves_num == 0 ? 0 : (curves_num + 1));
1184 if (curves_num > 0) {
1186 this->curve_offsets[0] = 0;
1187 this->curve_offsets[curves_num] = this->point_num;
1189 this->curve_num = curves_num;
1191 this->tag_topology_changed();
1194void CurvesGeometry::tag_positions_changed()
1203void CurvesGeometry::tag_topology_changed()
1206 this->tag_positions_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()
1248 if (this->handle_positions_left().is_empty() || this->handle_positions_right().is_empty()) {
1251 const OffsetIndices points_by_curve = this->points_by_curve();
1261 for (
const int i_curve :
range) {
1263 const IndexRange points = points_by_curve[i_curve];
1264 curves::bezier::calculate_auto_handles(cyclic[i_curve],
1265 types_left.slice(points),
1266 types_right.slice(points),
1267 positions.
slice(points),
1268 positions_left.
slice(points),
1269 positions_right.
slice(points));
1275void CurvesGeometry::translate(
const float3 &translation)
1281 std::optional<Bounds<float3>> bounds;
1287 if (!this->handle_positions_left().is_empty()) {
1290 if (!this->handle_positions_right().is_empty()) {
1293 this->tag_positions_changed();
1296 bounds->min += translation;
1297 bounds->max += translation;
1305 if (!this->handle_positions_left().is_empty()) {
1308 if (!this->handle_positions_right().is_empty()) {
1313 this->tag_positions_changed();
1316std::optional<Bounds<float3>> CurvesGeometry::bounds_min_max(
const bool use_radius)
const
1318 if (this->is_empty()) {
1319 return std::nullopt;
1324 if (
const std::optional radius_single = radius.
get_if_single()) {
1325 r_bounds = *this->bounds_min_max(
false);
1326 r_bounds.
pad(*radius_single);
1335 this->ensure_can_interpolate_to_evaluated();
1336 this->interpolate_to_evaluated(radius_span, radii_eval.
as_mutable_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());
1384 points_by_curve, custom_knot_curves, memory);
1386 points_to_copy, custom_knot_points, memory);
1388 int dst_knot_count = 0;
1390 dst_knot_count += curves::nurbs::knots_num(
1397 new_knots.
reserve(dst_knot_count);
1399 curves::foreach_selected_point_ranges_per_curve(
1400 custom_knot_points_to_copy,
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));
1458 gather_attributes(curves.attributes(),
1463 dst_curves.attributes_for_write());
1464 gather_attributes(curves.attributes(),
1469 dst_curves.attributes_for_write());
1472 if (curves.nurbs_has_custom_knots()) {
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()) {
1494 this->update_curve_types();
1498 const IndexMask points_to_copy = points_to_delete.
complement(this->points_range(), 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,
1545 dst_points_by_curve,
1566void CurvesGeometry::remove_curves(
const IndexMask &curves_to_delete,
1572 if (curves_to_delete.
size() ==
this->curves_num()) {
1574 this->update_curve_types();
1578 const IndexMask curves_to_copy = curves_to_delete.
complement(this->curves_range(), memory);
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)
1634 if (iter.
domain != AttrDomain::Point) {
1640 if (bezier_handle_names.contains(iter.
name)) {
1645 attribute_math::convert_to_static_type(attribute.span.type(), [&](
auto dummy) {
1646 using T = decltype(dummy);
1647 reverse_curve_point_data<T>(*this, curves_to_reverse, attribute.span.typed<T>());
1653 if (this->nurbs_has_custom_knots()) {
1654 const OffsetIndices custom_knots_by_curve = this->nurbs_custom_knots_by_curve();
1659 reverse_custom_knots(custom_knots.slice(curve_knots));
1674 this->handle_positions_left_for_write(),
1675 this->handle_positions_right_for_write());
1680 this->handle_types_left_for_write(),
1681 this->handle_types_right_for_write());
1684 this->tag_topology_changed();
1687void CurvesGeometry::remove_attributes_based_on_types()
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;
1773 attribute_math::convert_to_static_type(varray.
type(), [&](
auto dummy) {
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]);
1806 attribute_math::convert_to_static_type(varray.
type(), [&](
auto dummy) {
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));
1834 if (
from == AttrDomain::Point && to == AttrDomain::Curve) {
1837 if (
from == AttrDomain::Curve && to == AttrDomain::Point) {
1863 this->runtime = MEM_new<blender::bke::CurvesGeometryRuntime>(__func__);
1867 this->attribute_storage.wrap().blend_read(reader);
1869 if (this->curve_offsets) {
1871 &reader, &this->curve_offsets, [&]() {
1882 if (this->custom_knot_num) {
1884 &reader, &this->custom_knots, [&]() {
1891 this->update_curve_types();
1898 attribute_data(scope)
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.
static const char * ATTR_POSITION
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
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 first() const
constexpr IndexRange shift(int64_t n) 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 bool is_empty() 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 void copy_from(Span< T > values) const
constexpr T & last(const int64_t n=0) const
void ensure(FunctionRef< void(T &data)> compute_cache)
constexpr Span slice_safe(const int64_t start, const int64_t size) const
constexpr Span slice(int64_t start, int64_t size) const
constexpr const T & first() const
constexpr const T & last(const int64_t n=0) const
constexpr bool is_empty() const
std::optional< T > get_if_single() const
T get_internal_single() const
Span< T > get_internal_span() 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
void foreach_attribute(const FunctionRef< void(const AttributeIter &)> fn) const
bool contains(StringRef attribute_id) const
GAttributeReader lookup(const StringRef attribute_id) 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()
Array< int > point_to_curve_map() const
MutableSpan< float > nurbs_custom_knots_for_write()
OffsetIndices< int > points_by_curve() const
VArray< int8_t > handle_types_right() const
IndexRange curves_range() const
void update_curve_types()
MutableSpan< int8_t > curve_types_for_write()
MutableAttributeAccessor attributes_for_write()
void nurbs_custom_knots_update_size()
Span< float > nurbs_custom_knots() const
VArray< int > resolution() const
VArray< int8_t > nurbs_knots_modes() const
bool has_curve_with_type(CurveType type) const
void tag_topology_changed()
void resize(int points_num, int curves_num)
void fill_curve_types(CurveType type)
AttributeAccessor attributes() const
IndexMask nurbs_custom_knot_curves(IndexMaskMemory &memory) const
MutableSpan< int > offsets_for_write()
bool nurbs_has_custom_knots() const
OffsetIndices< int > nurbs_custom_knots_by_curve() const
VArray< int8_t > curve_types() const
VArray< bool > cyclic() const
VArray< int8_t > nurbs_orders() const
bool remove(const StringRef attribute_id)
bool add(const StringRef attribute_id, const AttrDomain domain, const eCustomDataType data_type, const AttributeInit &initializer)
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
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)
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)
typename DefaultMixerStruct< T >::type DefaultMixer
IndexMask curve_to_point_selection(OffsetIndices< int > points_by_curve, const IndexMask &curve_selection, IndexMaskMemory &memory)
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 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)
VecBase< float, 3 > float3
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
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