31 b.use_custom_socket_order();
32 b.allow_any_socket_order();
33 b.add_default_layout();
34 b.add_input<
decl::Geometry>(
"Geometry").description(
"Geometry to sort the elements of");
35 b.add_output<
decl::Geometry>(
"Geometry").propagate_all().align_with_previous();
55 const auto comparator = [&](
const int index_a,
const int index_b) {
56 const float weight_a = weights[index_a];
57 const float weight_b = weights[index_b];
58 if (
UNLIKELY(weight_a == weight_b)) {
60 return index_a < index_b;
62 return weight_a < weight_b;
66 for (const int group_index : range) {
67 MutableSpan<int> group = indices.slice(offsets[group_index]);
68 parallel_sort(group.begin(), group.end(), comparator);
81 const int curve_index =
indices[index];
82 r_indices[r_offsets[curve_index] + counts[curve_index]] = int(index);
83 counts[curve_index]++;
87template<
typename T,
typename Func>
91 MutableSpan<T> values_range = values.slice(range);
92 std::transform(values_range.begin(), values_range.end(), values_range.begin(), func);
100 for (const int64_t i : range) {
101 data[permutation[i]] = i;
109 const VectorSet<int> deduplicated_identifiers(r_identifiers_to_indices);
111 return deduplicated_identifiers.
index_of(identifier);
117 return deduplicated_identifiers[index_a] < deduplicated_identifiers[index_b];
121 r_identifiers_to_indices, 4096, [&](
const int index) {
return permutation[index]; });
122 return deduplicated_identifiers.
size();
126 const int domain_size,
131 if (domain_size == 0) {
137 evaluator.
add(group_id_field);
138 evaluator.
add(weight_field);
144 if (group_id.
is_single() && weight.is_single()) {
147 if (
mask.is_empty()) {
154 mask.to_indices<
int>(gathered_indices);
163 Array<int> offsets_to_sort(total_groups + 1, 0);
165 if (!weight.is_single()) {
177 if (
mask.size() == domain_size) {
178 return gathered_indices;
188 [&](
const int index) {
indices[index] = index; });
209 std::atomic<bool> has_reorder =
false;
210 std::atomic<bool> has_unsupported =
false;
215 instances->instances_num(),
221 *instances, *
indices, attribute_filter);
231 if (src_component ==
nullptr || src_component->
is_empty()) {
234 if (!domains.contains(domain)) {
235 has_unsupported =
true;
249 *src_component, *
indices, domain, attribute_filter);
250 geometry_set.
remove(type);
251 geometry_set.
add(*dst_component.
get());
256 if (has_unsupported && !has_reorder) {
258 TIP_(
"Domain and geometry type combination is unsupported"));
261 params.set_output(
"Geometry", std::move(geometry_set));
274 items.
append({0,
nullptr, 0,
nullptr,
nullptr});
292 supported_items.
data(),
302 ntype.
ui_name =
"Sort Elements";
303 ntype.
ui_description =
"Rearrange geometry elements, changing their indices";
#define NODE_CLASS_GEOMETRY
#define GEO_NODE_SORT_ELEMENTS
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_inline_enum_accessors(member)
BMesh const char void * data
Span< T > as_span() const
MutableSpan< T > as_mutable_span()
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool contains(const T &value) const
int64_t index_of(const Key &key) const
void append(const T &value)
int attribute_domain_size(AttrDomain domain) const
virtual bool is_empty() const
void set_selection(Field< bool > selection)
int add(GField field, GVArray *varray_ptr)
IndexMask get_evaluated_selection_as_mask() const
const GVArray & get_evaluated(const int field_index) const
void foreach_index_optimized(Fn &&fn) const
static void remember_deformed_positions_if_necessary(GeometrySet &geometry)
IndexRange index_range() const
ccl_device_inline float2 mask(const MaskType mask, const float2 a)
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
bool indices_are_range(Span< int > indices, IndexRange range)
void scatter(const Span< T > src, const Span< IndexT > indices, MutableSpan< T > dst, const int64_t grain_size=4096)
void gather(const GVArray &src, const IndexMask &indices, GMutableSpan dst, int64_t grain_size=4096)
void fill_index_range(MutableSpan< T > span, const T start=0)
ImplicitSharingPtr< GeometryComponent > GeometryComponentPtr
void node_register_type(bNodeType &ntype)
void foreach_real_geometry(bke::GeometrySet &geometry, FunctionRef< void(bke::GeometrySet &geometry_set)> fn)
const MultiValueMap< bke::GeometryComponent::Type, bke::AttrDomain > & components_supported_reordering()
bke::GeometryComponentPtr reordered_component(const bke::GeometryComponent &src_component, Span< int > old_by_new_map, bke::AttrDomain domain, const bke::AttributeFilter &attribute_filter)
bke::Instances * reorder_instaces(const bke::Instances &src_instances, Span< int > old_by_new_map, const bke::AttributeFilter &attribute_filter)
static void node_declare(NodeDeclarationBuilder &b)
static int identifiers_to_indices(MutableSpan< int > r_identifiers_to_indices)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void parallel_transform(MutableSpan< T > values, const int64_t grain_size, const Func &func)
static void node_geo_exec(GeoNodeExecParams params)
static void node_register()
static void node_rna(StructRNA *srna)
static Vector< EnumPropertyItem > items_value_in(const Span< T > values, const EnumPropertyItem *src_items)
static Array< int > invert_permutation(const Span< int > permutation)
static std::optional< Array< int > > sorted_indices(const fn::FieldContext &field_context, const int domain_size, const Field< bool > selection_field, const Field< int > group_id_field, const Field< float > weight_field)
static void grouped_sort(const OffsetIndices< int > offsets, const Span< float > weights, MutableSpan< int > indices)
static void find_points_by_group_index(const Span< int > indices, MutableSpan< int > r_offsets, MutableSpan< int > r_indices)
static void node_init(bNodeTree *, bNode *node)
PropertyRNA * RNA_def_node_enum(StructRNA *srna, const char *identifier, const char *ui_name, const char *ui_description, const EnumPropertyItem *static_items, const EnumRNAAccessors accessors, std::optional< int > default_value, const EnumPropertyItemFunc item_func, const bool allow_animation)
void build_reverse_offsets(Span< int > indices, MutableSpan< int > offsets)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
void parallel_sort(RandomAccessIterator begin, RandomAccessIterator end)
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
const EnumPropertyItem rna_enum_attribute_domain_items[]
void replace_instances(Instances *instances, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
const GeometryComponent * get_component(GeometryComponent::Type component_type) const
const Instances * get_instances() const
void remove(const GeometryComponent::Type component_type)
void add(const GeometryComponent &component)
std::string ui_description
void(* initfunc)(bNodeTree *ntree, bNode *node)
NodeGeometryExecFunction geometry_node_execute
const char * enum_name_legacy
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeDeclareFunction declare
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)