Page MenuHome
Paste P2728

instance
ActivePublic

Authored by Johnny Matthews (guitargeek) on Jan 13 2022, 5:52 AM.
static void duplicate_instances(GeometrySet &geometry_set,
const Field<int> &count_field,
const Field<bool> &selection_field,
IndexAttributes &attributes)
{
if (!geometry_set.has_instances()) {
geometry_set.clear();
return;
}
geometry_set.keep_only({GEO_COMPONENT_TYPE_INSTANCES});
AttributeMap map;
const InstancesComponent &instance_component =
*geometry_set.get_component_for_read<InstancesComponent>();
const int domain_size = instance_component.attribute_domain_size(ATTR_DOMAIN_INSTANCE);
GeometryComponentFieldContext field_context{instance_component, ATTR_DOMAIN_INSTANCE};
map.domain_duplicates = Array<int>(domain_size);
FieldEvaluator evaluator{field_context, domain_size};
evaluator.add_with_destination(count_field, map.domain_duplicates.as_mutable_span());
evaluator.set_selection(selection_field);
evaluator.evaluate();
IndexMask selection = evaluator.get_evaluated_selection_as_mask();
int total_instances = 0;
for (const int i_instance : selection) {
map.domain_duplicates[i_instance] = std::max(0, map.domain_duplicates[i_instance]);
total_instances += map.domain_duplicates[i_instance];
}
if (total_instances == 0) {
geometry_set.clear();
return;
}
InstancesComponent new_component;
new_component.resize(total_instances);
for (const int i_instance : selection) {
if (map.domain_duplicates[i_instance] == 0) {
continue;
}
const int old_handle = instance_component.instance_reference_handles()[i_instance];
const InstanceReference reference = instance_component.references()[old_handle];
const int new_handle = new_component.add_reference(reference);
const float4x4 transform = instance_component.instance_transforms()[i_instance];
int instance_index = 0;
for ([[maybe_unused]] const int i_duplicate : IndexRange(map.domain_duplicates[i_instance])) {
new_component.instance_reference_handles()[instance_index] = new_handle;
new_component.instance_transforms()[instance_index] = transform;
instance_index++;
}
}
// TODO - copy_attributes_instance(geometry_set, map, instance_component);
new_component.attributes().reallocate(total_instances);
geometry_set.remove(GEO_COMPONENT_TYPE_INSTANCES);
geometry_set.add(new_component);
if (attributes.copy_index) {
OutputAttribute_Typed<int> attribute = new_component.attribute_try_get_for_output_only<int>(
attributes.copy_index.get(), ATTR_DOMAIN_INSTANCE);
MutableSpan<int> copy_indices = attribute.as_span();
int instance_index = 0;
for (const int i_instance : IndexRange(total_instances)) {
for (const int i_duplicate : IndexRange(map.domain_duplicates[i_instance])) {
copy_indices[instance_index] = i_duplicate;
instance_index++;
}
}
attribute.save();
}
}

Event Timeline