36 .
description(
"All geometry groups as separate instances");
39 .
description(
"The group ID of each group instance");
52 for (
const int group_id : group_ids) {
53 geometry_by_group_id.lookup_or_add_cb(group_id,
54 []() {
return std::make_unique<GeometrySet>(); });
73 const AttrDomain domain,
76 Map<
int, std::unique_ptr<GeometrySet>> &geometry_by_group_id,
85 field_evaluator.
add(group_id_field);
89 if (selection.is_empty()) {
101 const AttrDomain domain,
105 Map<
int, std::unique_ptr<GeometrySet>> &geometry_by_group_id)
109 component, domain, selection_field, group_id_field, geometry_by_group_id, split_groups))
113 const Mesh &src_mesh = *component.
get();
117 [&]() {
return Array<bool>(domain_size,
false); }};
121 threading::isolate_task([&]() {
122 MutableSpan<bool> group_selection = group_selection_per_thread.local();
123 const VArray<bool> group_selection_varray = VArray<bool>::ForSpan(group_selection);
124 for (const int group_index : range) {
125 const IndexMask &mask = split_groups.group_masks[group_index];
126 index_mask::masked_fill(group_selection, true, mask);
127 const int group_id = split_groups.group_ids[group_index];
131 std::optional<Mesh *> group_mesh_opt = geometry::mesh_copy_selection(
132 src_mesh, group_selection_varray, domain, attribute_filter);
133 GeometrySet &group_geometry = *geometry_by_group_id.lookup(group_id);
134 if (group_mesh_opt.has_value()) {
135 if (Mesh *group_mesh = *group_mesh_opt) {
136 group_geometry.replace_mesh(group_mesh);
139 group_geometry.replace_mesh(nullptr);
143 group_geometry.add(component);
146 index_mask::masked_fill(group_selection, false, mask);
156 Map<
int, std::unique_ptr<GeometrySet>> &geometry_by_group_id)
163 geometry_by_group_id,
170 for (const int group_index : range) {
171 const IndexMask &mask = split_groups.group_masks[group_index];
172 const int group_id = split_groups.group_ids[group_index];
174 PointCloud *group_pointcloud = BKE_pointcloud_new_nomain(mask.size());
176 const AttributeAccessor src_attributes = src_pointcloud.attributes();
177 MutableAttributeAccessor dst_attributes = group_pointcloud->attributes_for_write();
178 bke::gather_attributes(src_attributes,
185 GeometrySet &group_geometry = *geometry_by_group_id.lookup(group_id);
186 group_geometry.replace_pointcloud(group_pointcloud);
192 const AttrDomain domain,
196 Map<
int, std::unique_ptr<GeometrySet>> &geometry_by_group_id)
200 component, domain, selection_field, group_id_field, geometry_by_group_id, split_groups))
206 for (const int group_index : range) {
207 const IndexMask &mask = split_groups.group_masks[group_index];
208 const int group_id = split_groups.group_ids[group_index];
210 bke::CurvesGeometry group_curves;
211 if (domain == AttrDomain::Point) {
212 group_curves = bke::curves_copy_point_selection(src_curves, mask, attribute_filter);
215 group_curves = bke::curves_copy_curve_selection(src_curves, mask, attribute_filter);
217 Curves *group_curves_id = bke::curves_new_nomain(std::move(group_curves));
218 GeometrySet &group_geometry = *geometry_by_group_id.lookup(group_id);
219 group_geometry.replace_curves(group_curves_id);
228 Map<
int, std::unique_ptr<GeometrySet>> &geometry_by_group_id)
232 AttrDomain::Instance,
235 geometry_by_group_id,
242 for (const int group_index : range) {
243 const IndexMask &mask = split_groups.group_masks[group_index];
244 const int group_id = split_groups.group_ids[group_index];
246 bke::Instances *group_instances = new bke::Instances();
247 group_instances->resize(mask.size());
249 for (const bke::InstanceReference &reference : src_instances.references()) {
250 group_instances->add_reference(reference);
253 bke::gather_attributes(src_instances.attributes(),
254 AttrDomain::Instance,
255 AttrDomain::Instance,
258 group_instances->attributes_for_write());
259 group_instances->remove_unused_references();
261 GeometrySet &group_geometry = *geometry_by_group_id.lookup(group_id);
262 group_geometry.replace_instances(group_instances);
270 const AttrDomain domain = AttrDomain(node.custom1);
281 ELEM(domain, AttrDomain::Point, AttrDomain::Edge, AttrDomain::Face))
289 geometry_by_group_id);
291 if (src_geometry.
has_pointcloud() && domain == AttrDomain::Point) {
294 component, selection_field, group_id_field, attribute_filter, geometry_by_group_id);
296 if (src_geometry.
has_curves() &&
ELEM(domain, AttrDomain::Point, AttrDomain::Curve)) {
303 geometry_by_group_id);
305 if (src_geometry.
has_instances() && domain == AttrDomain::Instance) {
308 component, selection_field, group_id_field, attribute_filter, geometry_by_group_id);
312 GeometrySet dst_geometry = GeometrySet::from_instances(dst_instances);
313 const int total_groups_num = geometry_by_group_id.
size();
314 dst_instances->
resize(total_groups_num);
316 std::optional<std::string> dst_group_id_attribute_id =
317 params.get_output_anonymous_attribute_id_if_needed(
"Group ID");
318 if (dst_group_id_attribute_id) {
321 *dst_group_id_attribute_id, AttrDomain::Instance);
322 std::copy(geometry_by_group_id.
keys().
begin(),
323 geometry_by_group_id.
keys().
end(),
324 dst_group_id.
span.begin());
331 for (
auto item : geometry_by_group_id.
items()) {
332 std::unique_ptr<GeometrySet> &group_geometry = item.value;
336 dst_geometry.
name = src_geometry.
name;
338 geometry::debug_randomize_instance_order(dst_instances);
340 params.set_output(
"Instances", std::move(dst_geometry));
348 "Attribute domain for the Selection and Group ID inputs",
351 int(AttrDomain::Point));
Low-level operations for curves.
#define NODE_CLASS_GEOMETRY
General operations for point clouds.
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_inline_enum_accessors(member)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
SubIterator begin() const
ItemIterator items() const
IndexRange index_range() const
const Curves * get() const
int attribute_domain_size(AttrDomain domain) const
const Instances * get() const
MutableSpan< int > reference_handles_for_write()
int add_reference(const InstanceReference &reference)
void resize(int capacity)
bke::MutableAttributeAccessor attributes_for_write()
MutableSpan< float4x4 > transforms_for_write()
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, eCustomDataType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
const PointCloud * get() 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
static Vector< IndexMask, 4 > from_group_ids(const VArray< int > &group_ids, IndexMaskMemory &memory, VectorSet< int > &r_index_by_group_id)
local_group_size(16, 16) .push_constant(Type b
void node_register_type(bNodeType *ntype)
static void node_rna(StructRNA *srna)
static void node_declare(NodeDeclarationBuilder &b)
static void node_register()
static void split_pointcloud_groups(const PointCloudComponent &component, const Field< bool > &selection_field, const Field< int > &group_id_field, const AttributeFilter &attribute_filter, Map< int, std::unique_ptr< GeometrySet > > &geometry_by_group_id)
static bool do_common_split(const GeometryComponent &src_component, const AttrDomain domain, const Field< bool > &selection_field, const Field< int > &group_id_field, Map< int, std::unique_ptr< GeometrySet > > &geometry_by_group_id, SplitGroups &r_groups)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
static void split_mesh_groups(const MeshComponent &component, const AttrDomain domain, const Field< bool > &selection_field, const Field< int > &group_id_field, const AttributeFilter &attribute_filter, Map< int, std::unique_ptr< GeometrySet > > &geometry_by_group_id)
static void split_instance_groups(const InstancesComponent &component, const Field< bool > &selection_field, const Field< int > &group_id_field, const AttributeFilter &attribute_filter, Map< int, std::unique_ptr< GeometrySet > > &geometry_by_group_id)
static void ensure_group_geometries(Map< int, std::unique_ptr< GeometrySet > > &geometry_by_group_id, const Span< int > group_ids)
static void node_geo_exec(GeoNodeExecParams params)
static void split_curve_groups(const bke::CurveComponent &component, const AttrDomain domain, const Field< bool > &selection_field, const Field< int > &group_id_field, const AttributeFilter &attribute_filter, Map< int, std::unique_ptr< GeometrySet > > &geometry_by_group_id)
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 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)
const EnumPropertyItem rna_enum_attribute_domain_without_corner_items[]
bool has_pointcloud() const
const GeometryComponent * get_component(GeometryComponent::Type component_type) const
bool has_instances() const
MutableVArraySpan< T > span
NodeGeometryExecFunction geometry_node_execute
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeDeclareFunction declare
Vector< IndexMask > group_masks
std::optional< bke::GeometryFieldContext > field_context
VectorSet< int > group_ids
std::optional< FieldEvaluator > field_evaluator