diff options
author | Jacques Lucke <jacques@blender.org> | 2021-09-27 18:35:26 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-09-27 18:35:45 +0300 |
commit | 0559971ab3772e3b5efb0fcad396735ea4ac22fe (patch) | |
tree | e373f64625d71d643e03f28a1383ee7c9b276d42 /source/blender/blenkernel/intern/geometry_set_instances.cc | |
parent | 2189dfd6e25a7bb6b734116619d87bc2d2a535ff (diff) |
Geometry Nodes: add utility to process all instances separately
This adds a new `GeometrySet::modify_geometry_sets` method that can be
used to update each sub-geometry-set separately without making any
instances real.
Differential Revision: https://developer.blender.org/D12650
Diffstat (limited to 'source/blender/blenkernel/intern/geometry_set_instances.cc')
-rw-r--r-- | source/blender/blenkernel/intern/geometry_set_instances.cc | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc index 162f91a4a47..ad13342ad9e 100644 --- a/source/blender/blenkernel/intern/geometry_set_instances.cc +++ b/source/blender/blenkernel/intern/geometry_set_instances.cc @@ -652,3 +652,58 @@ void InstancesComponent::foreach_referenced_geometry( } } } + +/** + * If references have a collection or object type, convert them into geometry instances + * recursively. After that, the geometry sets can be edited. There may still be instances of other + * types of they can't be converted to geometry sets. + */ +void InstancesComponent::ensure_geometry_instances() +{ + using namespace blender; + using namespace blender::bke; + VectorSet<InstanceReference> new_references; + new_references.reserve(references_.size()); + for (const InstanceReference &reference : references_) { + switch (reference.type()) { + case InstanceReference::Type::None: + case InstanceReference::Type::GeometrySet: { + /* Those references can stay as their were. */ + new_references.add_new(reference); + break; + } + case InstanceReference::Type::Object: { + /* Create a new reference that contains the geometry set of the object. We may want to + * treat e.g. lamps and similar object types separately here. */ + const Object &object = reference.object(); + GeometrySet object_geometry_set = object_get_geometry_set_for_read(object); + if (object_geometry_set.has_instances()) { + InstancesComponent &component = + object_geometry_set.get_component_for_write<InstancesComponent>(); + component.ensure_geometry_instances(); + } + new_references.add_new(std::move(object_geometry_set)); + break; + } + case InstanceReference::Type::Collection: { + /* Create a new reference that contains a geometry set that contains all objects from the + * collection as instances. */ + GeometrySet collection_geometry_set; + InstancesComponent &component = + collection_geometry_set.get_component_for_write<InstancesComponent>(); + Collection &collection = reference.collection(); + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (&collection, object) { + const int handle = component.add_reference(*object); + component.add_instance(handle, object->obmat); + float4x4 &transform = component.instance_transforms().last(); + sub_v3_v3(transform.values[3], collection.instance_offset); + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + component.ensure_geometry_instances(); + new_references.add_new(std::move(collection_geometry_set)); + break; + } + } + } + references_ = std::move(new_references); +} |