33 "A curve is created for every distinct group ID. All points with the same ID are put "
34 "into the same curve");
36 "Determines the order of points in each curve");
45 const auto comparator = [&](
const int index_a,
const int index_b) {
46 const float weight_a = weights[index_a];
47 const float weight_b = weights[index_b];
48 if (
UNLIKELY(weight_a == weight_b)) {
50 return index_a < index_b;
52 return weight_a < weight_b;
56 for (const int group_index : range) {
57 MutableSpan<int> group = indices.slice(offsets[group_index]);
58 parallel_sort(group.begin(), group.end(), comparator);
67 offset_indices::build_reverse_offsets(indices_of_curves, r_offsets);
71 const int curve_index = indices_of_curves[index];
72 r_indices[r_offsets[curve_index] + counts[curve_index]] =
int(index);
73 counts[curve_index]++;
79 const VectorSet<int> deduplicated_groups(r_identifiers_to_indices);
80 threading::parallel_for(
82 for (int &value : r_identifiers_to_indices.slice(range)) {
83 value = deduplicated_groups.index_of(value);
86 return deduplicated_groups.size();
93 const int domain_size = weights_varray.
size();
97 bke::copy_attributes(attributes,
101 curves.attributes_for_write());
105 array_utils::fill_index_range<int>(indices);
108 bke::gather_attributes(attributes,
113 curves.attributes_for_write());
122 const int domain_size = points.totpoint;
123 if (domain_size == 0) {
129 evaluator.
add(group_id_field);
130 evaluator.
add(weight_field);
143 if (total_curves == 1) {
147 Curves *curves_id = bke::curves_new_nomain(domain_size, total_curves);
156 if (!weights_varray.is_single()) {
160 bke::gather_attributes(points.attributes(),
165 curves.attributes_for_write());
167 geometry::debug_randomize_curve_order(&curves);
182 *points, group_id_field, weight_field, attribute_filter);
188 params.set_output(
"Curves", std::move(geometry_set));
Low-level operations for curves.
#define NODE_CLASS_GEOMETRY
#define NOD_REGISTER_NODE(REGISTER_FUNC)
MutableSpan< T > as_mutable_span()
constexpr int64_t size() const
constexpr void fill(const T &value) const
constexpr IndexRange index_range() const
constexpr IndexRange index_range() const
void materialize(MutableSpan< T > r_span) const
int add(GField field, GVArray *varray_ptr)
const GVArray & get_evaluated(const int field_index) const
IndexRange index_range() const
local_group_size(16, 16) .push_constant(Type b
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
void node_register_type(bNodeType *ntype)
static void node_geo_exec(GeoNodeExecParams params)
static Curves * curve_from_points(const AttributeAccessor attributes, const VArray< float > &weights_varray, const AttributeFilter &attribute_filter)
static void find_points_by_group_index(const Span< int > indices_of_curves, MutableSpan< int > r_offsets, MutableSpan< int > r_indices)
static void grouped_sort(const OffsetIndices< int > offsets, const Span< float > weights, MutableSpan< int > indices)
static void node_declare(NodeDeclarationBuilder &b)
static Curves * curves_from_points(const PointCloud &points, const Field< int > &group_id_field, const Field< float > &weight_field, const AttributeFilter &attribute_filter)
static int identifiers_to_indices(MutableSpan< int > r_identifiers_to_indices)
static void node_register()
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
void geo_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void keep_only_during_modify(Span< GeometryComponent::Type > component_types)
void replace_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const PointCloud * get_pointcloud() const
void modify_geometry_sets(ForeachSubGeometryCallback callback)
NodeGeometryExecFunction geometry_node_execute
NodeDeclareFunction declare