71 this->
runtime = MEM_new<CurvesGeometryRuntime>(__func__);
95 dst.
runtime->type_counts =
src.runtime->type_counts;
106 if (
this != &other) {
139 if (
this != &other) {
179 const T default_value)
186 if (
data !=
nullptr) {
202 if (
data ==
nullptr) {
212 const T default_value =
T())
220 if (
data !=
nullptr) {
226 if (num > 0 && span.
first() != default_value) {
227 span.
fill(default_value);
234 return get_varray_attribute<int8_t>(
246 this->
runtime->type_counts.fill(0);
253 if (selection.
size() == this->curves_num()) {
265 using CountsType = std::array<int, CURVE_TYPES_NUM>;
269 if (
types.is_single()) {
270 counts[
types.get_internal_single()] =
types.size();
280 CountsType result = init;
281 for (const int curve_index : curves_range) {
282 result[types_span[curve_index]]++;
286 [](
const CountsType &
a,
const CountsType &
b) {
295 void CurvesGeometry::update_curve_types()
311 return {this->curve_offsets, this->curve_num + 1};
315 return {this->curve_offsets, this->curve_num + 1};
479 switch (
types[curve_index]) {
482 points.
size(), cyclic[curve_index], resolution[curve_index]);
484 return points.
size();
487 handle_types_right.slice(points),
489 resolution[curve_index],
490 bezier_evaluated_offsets.
slice(points));
491 return bezier_evaluated_offsets[points.
last()];
494 nurbs_orders[curve_index],
496 resolution[curve_index],
497 KnotsMode(nurbs_knots_modes[curve_index]));
504 void CurvesGeometry::ensure_evaluated_offsets()
const
506 if (!this->runtime->offsets_cache_dirty) {
511 std::scoped_lock
lock{this->runtime->offsets_cache_mutex};
512 if (!this->runtime->offsets_cache_dirty) {
517 this->runtime->evaluated_offsets_cache.resize(this->curves_num() + 1);
520 this->runtime->bezier_evaluated_offsets.resize(this->points_num());
523 this->runtime->bezier_evaluated_offsets.clear_and_make_inline();
527 *
this, this->runtime->evaluated_offsets_cache, this->runtime->bezier_evaluated_offsets);
530 this->runtime->offsets_cache_dirty =
false;
535 this->ensure_evaluated_offsets();
536 return this->runtime->evaluated_offsets_cache;
542 return this->indices_for_curve_type(
type, this->curves_range(), r_indices);
550 this->curve_types(), this->curve_type_counts(),
type, selection, r_indices);
553 void CurvesGeometry::ensure_nurbs_basis_cache()
const
555 if (!this->runtime->nurbs_basis_cache_dirty) {
560 std::scoped_lock
lock{this->runtime->nurbs_basis_cache_mutex};
561 if (!this->runtime->nurbs_basis_cache_dirty) {
566 Vector<int64_t> nurbs_indices;
567 const IndexMask nurbs_mask = this->indices_for_curve_type(
CURVE_TYPE_NURBS, nurbs_indices);
568 if (nurbs_mask.is_empty()) {
572 this->runtime->nurbs_basis_cache.resize(this->curves_num());
573 MutableSpan<curves::nurbs::BasisCache> basis_caches(this->runtime->nurbs_basis_cache);
575 VArray<bool> cyclic = this->cyclic();
576 VArray<int8_t> orders = this->nurbs_orders();
577 VArray<int8_t> knots_modes = this->nurbs_knots_modes();
580 for (const int curve_index : nurbs_mask.slice(range)) {
581 const IndexRange points = this->points_for_curve(curve_index);
582 const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
584 const int8_t order = orders[curve_index];
585 const bool is_cyclic = cyclic[curve_index];
586 const KnotsMode mode = KnotsMode(knots_modes[curve_index]);
588 if (!curves::nurbs::check_valid_num_and_order(points.size(), order, is_cyclic, mode)) {
589 basis_caches[curve_index].invalid = true;
593 const int knots_num = curves::nurbs::knots_num(points.size(), order, is_cyclic);
594 Array<float> knots(knots_num);
595 curves::nurbs::calculate_knots(points.size(), mode, order, is_cyclic, knots);
596 curves::nurbs::calculate_basis_cache(points.size(),
597 evaluated_points.size(),
601 basis_caches[curve_index]);
606 this->runtime->nurbs_basis_cache_dirty =
false;
611 if (!this->runtime->position_cache_dirty) {
612 return this->runtime->evaluated_positions_span;
616 std::scoped_lock
lock{this->runtime->position_cache_mutex};
617 if (!this->runtime->position_cache_dirty) {
618 return this->runtime->evaluated_positions_span;
623 this->runtime->evaluated_positions_span = this->
positions();
624 this->runtime->evaluated_position_cache.clear_and_make_inline();
628 this->runtime->evaluated_position_cache.resize(this->evaluated_points_num());
630 this->runtime->evaluated_positions_span = evaluated_positions;
637 Span<float3> handle_positions_left = this->handle_positions_left();
638 Span<float3> handle_positions_right = this->handle_positions_right();
639 Span<int> bezier_evaluated_offsets = this->runtime->bezier_evaluated_offsets;
644 this->ensure_nurbs_basis_cache();
647 for (
const int curve_index : curves_range) {
648 const IndexRange points = this->points_for_curve(curve_index);
649 const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
651 switch (
types[curve_index]) {
656 resolution[curve_index],
657 evaluated_positions.
slice(evaluated_points));
665 handle_positions_left.
slice(points),
666 handle_positions_right.
slice(points),
667 bezier_evaluated_offsets.
slice(points),
668 evaluated_positions.
slice(evaluated_points));
672 nurbs_orders[curve_index],
673 nurbs_weights.
slice(points),
675 evaluated_positions.
slice(evaluated_points));
686 this->runtime->position_cache_dirty =
false;
687 return this->runtime->evaluated_positions_span;
692 if (!this->runtime->tangent_cache_dirty) {
693 return this->runtime->evaluated_tangent_cache;
697 std::scoped_lock
lock{this->runtime->tangent_cache_mutex};
698 if (!this->runtime->tangent_cache_dirty) {
699 return this->runtime->evaluated_tangent_cache;
703 const Span<float3> evaluated_positions = this->evaluated_positions();
706 this->runtime->evaluated_tangent_cache.resize(this->evaluated_points_num());
710 for (
const int curve_index : curves_range) {
711 const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
725 const Span<float3> handles_left = this->handle_positions_left();
726 const Span<float3> handles_right = this->handle_positions_right();
729 for (const int curve_index : bezier_mask.slice(range)) {
730 if (cyclic[curve_index]) {
733 const IndexRange points = this->points_for_curve(curve_index);
734 const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
736 const float epsilon = 1e-6f;
737 if (!math::almost_equal_relative(
738 handles_right[points.first()], positions[points.first()], epsilon)) {
739 tangents[evaluated_points.first()] = math::normalize(handles_right[points.first()] -
740 positions[points.first()]);
742 if (!math::almost_equal_relative(
743 handles_left[points.last()], positions[points.last()], epsilon)) {
744 tangents[evaluated_points.last()] = math::normalize(positions[points.last()] -
745 handles_left[points.last()]);
752 this->runtime->tangent_cache_dirty =
false;
753 return this->runtime->evaluated_tangent_cache;
767 if (!this->runtime->normal_cache_dirty) {
768 return this->runtime->evaluated_normal_cache;
772 std::scoped_lock
lock{this->runtime->normal_cache_mutex};
773 if (!this->runtime->normal_cache_dirty) {
774 return this->runtime->evaluated_normal_cache;
778 const Span<float3> evaluated_tangents = this->evaluated_tangents();
784 this->runtime->evaluated_normal_cache.resize(this->evaluated_points_num());
791 for (
const int curve_index : curves_range) {
792 const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
793 switch (normal_mode[curve_index]) {
796 evaluated_normals.
slice(evaluated_points));
801 evaluated_normals.
slice(evaluated_points));
808 const IndexRange points = this->points_for_curve(curve_index);
812 evaluated_tangents.
slice(evaluated_points),
816 evaluated_tilts.
clear();
817 evaluated_tilts.
resize(evaluated_points.
size());
821 evaluated_tangents.
slice(evaluated_points),
829 this->runtime->normal_cache_dirty =
false;
830 return this->runtime->evaluated_normal_cache;
837 BLI_assert(!this->runtime->offsets_cache_dirty);
838 BLI_assert(!this->runtime->nurbs_basis_cache_dirty);
839 const IndexRange points = this->points_for_curve(curve_index);
841 BLI_assert(dst.
size() == this->evaluated_points_for_curve(curve_index).size());
842 switch (this->curve_types()[curve_index]) {
845 src, this->cyclic()[curve_index], this->resolution()[curve_index], dst);
852 src, this->runtime->bezier_evaluated_offsets.as_span().slice(points), dst);
856 this->nurbs_orders()[curve_index],
857 this->nurbs_weights().slice(points),
867 BLI_assert(!this->runtime->offsets_cache_dirty);
868 BLI_assert(!this->runtime->nurbs_basis_cache_dirty);
873 const Span<float> nurbs_weights = this->nurbs_weights();
876 for (
const int curve_index : curves_range) {
877 const IndexRange points = this->points_for_curve(curve_index);
878 const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
879 switch (
types[curve_index]) {
883 resolution[curve_index],
884 dst.
slice(evaluated_points));
892 this->runtime->bezier_evaluated_offsets.as_span().slice(points),
893 dst.
slice(evaluated_points));
897 nurbs_orders[curve_index],
898 nurbs_weights.
slice(points),
900 dst.
slice(evaluated_points));
907 void CurvesGeometry::ensure_evaluated_lengths()
const
909 if (!this->runtime->length_cache_dirty) {
914 std::scoped_lock
lock{this->runtime->length_cache_mutex};
915 if (!this->runtime->length_cache_dirty) {
922 const int total_num = this->evaluated_points_num() + this->curves_num();
923 this->runtime->evaluated_length_cache.resize(total_num);
926 Span<float3> evaluated_positions = this->evaluated_positions();
930 for (
const int curve_index : curves_range) {
931 const bool cyclic = curves_cyclic[curve_index];
932 const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
933 const IndexRange lengths_range = this->lengths_range_for_curve(curve_index, cyclic);
936 evaluated_lengths.
slice(lengths_range));
941 this->runtime->length_cache_dirty =
false;
944 void CurvesGeometry::ensure_can_interpolate_to_evaluated()
const
946 this->ensure_evaluated_offsets();
947 this->ensure_nurbs_basis_cache();
956 void CurvesGeometry::resize(
const int points_num,
const int curves_num)
958 if (points_num != this->point_num) {
960 this->point_num = points_num;
962 if (curves_num != this->curve_num) {
964 this->curve_num = curves_num;
965 this->curve_offsets = (
int *)
MEM_reallocN(this->curve_offsets,
sizeof(
int) * (curves_num + 1));
967 this->tag_topology_changed();
970 void CurvesGeometry::tag_positions_changed()
972 this->runtime->position_cache_dirty =
true;
973 this->runtime->tangent_cache_dirty =
true;
974 this->runtime->normal_cache_dirty =
true;
975 this->runtime->length_cache_dirty =
true;
977 void CurvesGeometry::tag_topology_changed()
979 this->runtime->position_cache_dirty =
true;
980 this->runtime->tangent_cache_dirty =
true;
981 this->runtime->normal_cache_dirty =
true;
982 this->runtime->offsets_cache_dirty =
true;
983 this->runtime->nurbs_basis_cache_dirty =
true;
984 this->runtime->length_cache_dirty =
true;
986 void CurvesGeometry::tag_normals_changed()
988 this->runtime->normal_cache_dirty =
true;
994 for (float3 &position : positions.slice(range)) {
995 position += translation;
1003 for (float3 &position : positions.slice(range)) {
1004 position = matrix * position;
1009 void CurvesGeometry::calculate_bezier_auto_handles()
1015 if (this->handle_positions_left().is_empty() || this->handle_positions_right().is_empty()) {
1026 for (
const int i_curve : range) {
1028 const IndexRange points = this->points_for_curve(i_curve);
1030 types_left.slice(points),
1031 types_right.slice(points),
1033 positions_left.
slice(points),
1034 positions_right.
slice(points));
1040 void CurvesGeometry::translate(
const float3 &translation)
1043 if (!this->handle_positions_left().is_empty()) {
1046 if (!this->handle_positions_right().is_empty()) {
1049 this->tag_positions_changed();
1055 if (!this->handle_positions_left().is_empty()) {
1058 if (!this->handle_positions_right().is_empty()) {
1061 this->tag_positions_changed();
1069 if (!(
radii.is_single() &&
radii.get_internal_single() == 0.0f)) {
1087 const void *src_buffer,
1098 template<
typename T>
1102 for (const int i : range) {
1103 dst[i] = src[map[i]];
1111 using T = decltype(dummy);
1112 copy_with_map(src.typed<T>(), map, dst.typed<T>());
1123 for (const int i_curve : curves_range) {
1124 point_to_curve_map.as_mutable_span().slice(curves.points_for_curve(i_curve)).fill(i_curve);
1127 return point_to_curve_map;
1140 int new_point_count = 0;
1141 Array<int> copy_point_range_dst_offsets(copy_point_ranges.
size());
1142 for (
const int i : copy_point_ranges.
index_range()) {
1143 copy_point_range_dst_offsets[i] = new_point_count;
1144 new_point_count += copy_point_ranges[i].
size();
1150 for (
const IndexRange range : copy_point_ranges) {
1151 for (
const int point_i : range) {
1152 curve_point_counts[point_to_curve_map[point_i]]++;
1159 int new_curve_count = 0;
1160 int curve_point_offset = 0;
1163 new_curve_offsets.
append(0);
1164 for (
const int i : curve_point_counts.
index_range()) {
1165 if (curve_point_counts[i] > 0) {
1166 curve_point_offset += curve_point_counts[i];
1167 new_curve_offsets.
append(curve_point_offset);
1170 new_curve_orig_indices.
append(i);
1177 256 < new_point_count * new_curve_count,
1179 [&]() { new_curves.offsets_for_write().copy_from(new_curve_offsets); },
1185 for (const int range_i : range) {
1186 const IndexRange src_range = copy_point_ranges[range_i];
1187 copy_between_buffers(attribute.src.type(),
1188 attribute.src.data(),
1189 attribute.dst.span.data(),
1191 {copy_point_range_dst_offsets[range_i], src_range.size()});
1202 if (new_curves.curves_num() ==
curves.curves_num()) {
1215 void CurvesGeometry::remove_points(
const IndexMask points_to_delete)
1220 if (points_to_delete.
size() == this->points_num()) {
1231 curves.curves_range(),
nullptr);
1235 int new_tot_points = 0;
1236 int new_tot_curves = 0;
1237 for (
const IndexRange &curve_range : old_curve_ranges) {
1239 new_tot_curves += curve_range.size();
1242 old_point_ranges.
append(old_point_range);
1244 new_tot_points += old_point_range.
size();
1250 256 < new_tot_points * new_tot_curves,
1254 new_offsets.
last() = new_tot_points;
1257 for (const int range_i : ranges_range) {
1258 const IndexRange old_curve_range = old_curve_ranges[range_i];
1259 const IndexRange new_curve_range = new_curve_ranges[range_i];
1260 const IndexRange old_point_range = old_point_ranges[range_i];
1261 const IndexRange new_point_range = new_point_ranges[range_i];
1262 const int offset_shift = new_point_range.start() - old_point_range.start();
1263 const int curves_in_range = old_curve_range.size();
1264 threading::parallel_for(
1265 IndexRange(curves_in_range), 512, [&](const IndexRange range) {
1266 for (const int i : range) {
1267 const int old_curve_i = old_curve_range[i];
1268 const int new_curve_i = new_curve_range[i];
1269 const int old_offset = old_offsets[old_curve_i];
1270 const int new_offset = old_offset + offset_shift;
1271 new_offsets[new_curve_i] = new_offset;
1282 for (const int range_i : range) {
1283 copy_between_buffers(attribute.src.type(),
1284 attribute.src.data(),
1285 attribute.dst.span.data(),
1286 old_point_ranges[range_i],
1287 new_point_ranges[range_i]);
1296 for (const int range_i : range) {
1297 copy_between_buffers(attribute.src.type(),
1298 attribute.src.data(),
1299 attribute.dst.span.data(),
1300 old_curve_ranges[range_i],
1301 new_curve_ranges[range_i]);
1311 void CurvesGeometry::remove_curves(
const IndexMask curves_to_delete)
1316 if (curves_to_delete.
size() == this->curves_num()) {
1323 template<
typename T>
1329 for (const int curve_i : curve_selection.slice(range)) {
1330 data.slice(curves.points_for_curve(curve_i)).reverse();
1335 template<
typename T>
1342 for (const int curve_i : curve_selection.slice(range)) {
1343 const IndexRange points = curves.points_for_curve(curve_i);
1344 MutableSpan<T> a = data_a.slice(points);
1345 MutableSpan<T> b = data_b.slice(points);
1346 for (const int i : IndexRange(points.size() / 2)) {
1347 const int end_index = points.size() - 1 - i;
1348 std::swap(a[end_index], b[i]);
1349 std::swap(b[end_index], a[i]);
1351 if (points.size() % 2) {
1352 const int64_t middle_index = points.size() / 2;
1353 std::swap(a[middle_index], b[middle_index]);
1366 return layer.
name == name;
1369 void CurvesGeometry::reverse_curves(
const IndexMask curves_to_reverse)
1380 for (
const int layer_i :
IndexRange(this->point_data.totlayer)) {
1385 positions_left = {
static_cast<float3 *
>(layer.
data), this->points_num()};
1390 positions_right = {
static_cast<float3 *
>(layer.
data), this->points_num()};
1395 types_left = {
static_cast<int8_t *
>(layer.
data), this->points_num()};
1400 types_right = {
static_cast<int8_t *
>(layer.
data), this->points_num()};
1406 using T = decltype(dummy);
1407 reverse_curve_point_data<T>(
1408 *
this, curves_to_reverse, {
static_cast<T *
>(layer.
data), this->points_num()});
1424 this->tag_topology_changed();
1427 void CurvesGeometry::remove_attributes_based_on_types()
1429 const int points_num = this->points_num();
1430 const int curves_num = this->curves_num();
1460 template<
typename T>
1467 for (
const int i_point :
curves.points_for_curve(i_curve)) {
1468 mixer.mix_in(i_curve, old_values[i_point]);
1486 r_values.
fill(
true);
1488 for (
const int i_point :
curves.points_for_curve(i_curve)) {
1489 if (!old_values[i_point]) {
1490 r_values[i_curve] =
false;
1502 using T = decltype(dummy);
1503 if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
1504 Array<T> values(curves.curves_num());
1505 adapt_curve_domain_point_to_curve_impl<T>(curves, varray.typed<T>(), values);
1506 new_varray = VArray<T>::ForContainer(std::move(values));
1519 template<
typename T>
1525 r_values.
slice(
curves.points_for_curve(i_curve)).
fill(old_values[i_curve]);
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));
Low-level operations for curves.
Low-level operations for curves.
bool CustomData_free_layer_named(struct CustomData *data, const char *name, const int totelem)
void CustomData_free(struct CustomData *data, int totelem)
void CustomData_copy(const struct CustomData *source, struct CustomData *dest, eCustomDataMask mask, eCDAllocType alloctype, int totelem)
void * CustomData_duplicate_referenced_layer_named(struct CustomData *data, int type, const char *name, int totelem)
void * CustomData_add_layer_named(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem, const char *name)
void * CustomData_get_layer_named(const struct CustomData *data, int type, const char *name)
void CustomData_realloc(struct CustomData *data, int totelem)
void CustomData_duplicate_referenced_layers(CustomData *data, int totelem)
void CustomData_reset(struct CustomData *data)
#define BLI_assert_unreachable()
#define POINTER_OFFSET(v, ofs)
@ NORMAL_MODE_MINIMUM_TWIST
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to curves
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color attribute
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
IndexRange index_range() const
void copy_assign_n(const void *src, void *dst, int64_t n) const
const CPPType & type() const
void copy_from(GSpan values)
GMutableSpan slice(const int64_t start, int64_t size) const
const CPPType & type() const
Vector< IndexRange > extract_ranges_invert(const IndexRange full_range, Vector< int64_t > *r_skip_amounts=nullptr) const
IndexRange index_range() const
constexpr int64_t last(const int64_t n=0) const
constexpr int64_t size() const
constexpr int64_t start() const
constexpr void fill(const T &value)
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 T & last(const int64_t n=0) const
constexpr void copy_from(Span< T > values)
constexpr IndexRange index_range() const
constexpr T & first() const
constexpr Span slice(int64_t start, int64_t size) const
constexpr const char * c_str() 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)
MutableSpan< T > as_mutable_span()
void append(const T &value)
Span< T > as_span() const
IndexRange index_range() const
void resize(const int64_t new_size)
void update_curve_types()
MutableSpan< int8_t > curve_types_for_write()
void tag_topology_changed()
void fill_curve_types(CurveType type)
MutableSpan< int > offsets_for_write()
VArray< int8_t > curve_types() const
CurvesGeometry & operator=(const CurvesGeometry &other)
static const char * ATTR_POSITION
SyclQueue void void * src
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
typename DefaultMixerStruct< T >::type DefaultMixer
void convert_to_static_type(const CPPType &cpp_type, const Func &func)
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_positions(Span< float3 > positions, Span< float3 > handles_left, Span< float3 > handles_right, Span< int > evaluated_offsets, MutableSpan< float3 > evaluated_positions)
void interpolate_to_evaluated(GSpan src, Span< int > evaluated_offsets, GMutableSpan dst)
int calculate_evaluated_num(int points_num, bool cyclic, int resolution)
IndexMask indices_for_type(const VArray< int8_t > &types, const std::array< int, CURVE_TYPES_NUM > &type_counts, const CurveType type, const IndexMask selection, Vector< int64_t > &r_indices)
static int domain_num(const CurvesGeometry &curves, const eAttrDomain domain)
static void reverse_curve_point_data(const CurvesGeometry &curves, const IndexMask curve_selection, MutableSpan< T > data)
static void translate_positions(MutableSpan< float3 > positions, const float3 &translation)
static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves, const IndexMask curves_to_delete)
Vector< AttributeTransferData > retrieve_attributes_for_transfer(const bke::AttributeAccessor src_attributes, bke::MutableAttributeAccessor dst_attributes, eAttrDomainMask domain_mask, const Set< std::string > &skip={})
static const std::string ATTR_HANDLE_POSITION_RIGHT
static void copy_between_buffers(const CPPType &type, const void *src_buffer, void *dst_buffer, const IndexRange src_range, const IndexRange dst_range)
static void reverse_swap_curve_point_data(const CurvesGeometry &curves, const IndexMask curve_selection, MutableSpan< T > data_a, MutableSpan< T > data_b)
static CurvesGeometry copy_with_removed_points(const CurvesGeometry &curves, const IndexMask points_to_delete)
static Array< int > build_point_to_curve_map(const CurvesGeometry &curves)
static void move_curves_geometry(CurvesGeometry &dst, CurvesGeometry &src)
static VArray< T > get_varray_attribute(const CurvesGeometry &curves, const eAttrDomain domain, const StringRefNull name, const T default_value)
static CustomData & domain_custom_data(CurvesGeometry &curves, const eAttrDomain domain)
static const std::string ATTR_NURBS_WEIGHT
static const std::string ATTR_HANDLE_TYPE_RIGHT
static const std::string ATTR_NURBS_KNOTS_MODE
static const std::string ATTR_RADIUS
static MutableSpan< T > get_mutable_attribute(CurvesGeometry &curves, const eAttrDomain domain, const StringRefNull name, const T default_value=T())
static GVArray adapt_curve_domain_point_to_curve(const CurvesGeometry &curves, const GVArray &varray)
static Span< T > get_span_attribute(const CurvesGeometry &curves, const eAttrDomain domain, const StringRefNull name)
static bool layer_matches_name_and_type(const CustomDataLayer &layer, const StringRef name, const eCustomDataType type)
static const std::string ATTR_NORMAL_MODE
static void copy_curves_geometry(CurvesGeometry &dst, const CurvesGeometry &src)
static const std::string ATTR_POSITION
static const std::string ATTR_HANDLE_TYPE_LEFT
static const std::string ATTR_CYCLIC
static const std::string ATTR_SURFACE_UV_COORDINATE
static void copy_with_map(const GSpan src, const Span< int > map, GMutableSpan dst)
std::array< int, CURVE_TYPES_NUM > calculate_type_counts(const VArray< int8_t > &types)
static const std::string ATTR_RESOLUTION
static const std::string ATTR_TILT
static void calculate_evaluated_offsets(const CurvesGeometry &curves, MutableSpan< int > offsets, MutableSpan< int > bezier_evaluated_offsets)
static const std::string ATTR_CURVE_TYPE
void adapt_curve_domain_point_to_curve_impl(const CurvesGeometry &curves, const VArray< bool > &old_values, MutableSpan< bool > r_values)
static const std::string ATTR_HANDLE_POSITION_LEFT
void build_offsets(MutableSpan< int > offsets, const CountFn &count_fn)
static const std::string ATTR_NURBS_ORDER
static void transform_positions(MutableSpan< float3 > positions, const float4x4 &matrix)
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 std::optional< bounds::MinMaxResult< float3 > > curves_bounds(const CurvesGeometry &curves)
static void rotate_directions_around_axes(MutableSpan< float3 > directions, const Span< float3 > axes, const Span< float > angles)
static const std::string ATTR_SELECTION_POINT_FLOAT
eCustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
static const std::string ATTR_SELECTION_CURVE_FLOAT
static std::optional< MinMaxResult< T > > min_max(Span< T > values)
static std::optional< MinMaxResult< T > > min_max_with_radii(Span< T > values, Span< RadiusT > radii)
void accumulate_lengths(const Span< T > values, const bool cyclic, MutableSpan< float > lengths)
T min(const T &a, const T &b)
float3 rotate_direction_around_axis(const float3 &direction, const float3 &axis, float angle)
T max(const T &a, const T &b)
void isolate_task(const Function &function)
void parallel_for(IndexRange range, int64_t grain_size, const Function &function)
void parallel_invoke(Functions &&...functions)
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
MutableSpan< float3 > positions
MutableSpan< float > radii
MutableSpan< float3 > tangents
SocketIndexByIdentifierMap * map
static void calculate_normals_z_up(Span< float3 > tangents, MutableSpan< float3 > r_normals)
static void calculate_normals_minimum(Span< float3 > tangents, const bool cyclic, MutableSpan< float3 > r_normals)
static void calculate_tangents(Span< float3 > positions, const bool is_cyclic, MutableSpan< float3 > tangents)
CurvesGeometryRuntimeHandle * runtime