diff options
author | Jacques Lucke <jacques@blender.org> | 2020-12-11 20:00:37 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2020-12-11 20:00:37 +0300 |
commit | f5dc34ec9c05cc8f1163313baafe634f4798c29b (patch) | |
tree | b3cc27fc8009fc0180f4b35c5c3646cb2527a72c /source/blender/nodes | |
parent | 5ced167336d49ef42e96e205c72d3935ff302a7e (diff) |
Geometry Nodes: support instancing collections
The Point Instance node can instance entire collections now.
Before, only individual collections were supported.
Randomly selecting objects from the collection on a per point basis
is not support, yet.
Last part of D9739.
Ref T82372.
Diffstat (limited to 'source/blender/nodes')
-rw-r--r-- | source/blender/nodes/NOD_static_types.h | 2 | ||||
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc | 4 | ||||
-rw-r--r-- | source/blender/nodes/geometry/nodes/node_geo_point_instance.cc | 63 |
3 files changed, 52 insertions, 17 deletions
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index d1032647ba8..491f49cf425 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -272,7 +272,7 @@ DefNode(GeometryNode, GEO_NODE_TRANSFORM, 0, "TRANSFORM", Transform, "Transform" DefNode(GeometryNode, GEO_NODE_SUBDIVISION_SURFACE, 0, "SUBDIVISION_SURFACE", SubdivisionSurface, "Subdivision Surface", "") DefNode(GeometryNode, GEO_NODE_BOOLEAN, def_geo_boolean, "BOOLEAN", Boolean, "Boolean", "") DefNode(GeometryNode, GEO_NODE_POINT_DISTRIBUTE, 0, "POINT_DISTRIBUTE", PointDistribute, "Point Distribute", "") -DefNode(GeometryNode, GEO_NODE_POINT_INSTANCE, 0, "POINT_INSTANCE", PointInstance, "Point Instance", "") +DefNode(GeometryNode, GEO_NODE_POINT_INSTANCE, def_geo_point_instance, "POINT_INSTANCE", PointInstance, "Point Instance", "") DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "") DefNode(GeometryNode, GEO_NODE_RANDOM_ATTRIBUTE, def_geo_random_attribute, "RANDOM_ATTRIBUTE", RandomAttribute, "Random Attribute", "") DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MATH, def_geo_attribute_math, "ATTRIBUTE_MATH", AttributeMath, "Attribute Math", "") diff --git a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc index dedc3213a1f..80ac45aed4e 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_join_geometry.cc @@ -218,12 +218,12 @@ static void join_components(Span<const InstancesComponent *> src_components, Geo InstancesComponent &dst_component = result.get_component_for_write<InstancesComponent>(); for (const InstancesComponent *component : src_components) { const int size = component->instances_amount(); - Span<const Object *> objects = component->objects(); + Span<InstancedData> instanced_data = component->instanced_data(); Span<float3> positions = component->positions(); Span<float3> rotations = component->rotations(); Span<float3> scales = component->scales(); for (const int i : IndexRange(size)) { - dst_component.add_instance(objects[i], positions[i], rotations[i], scales[i]); + dst_component.add_instance(instanced_data[i], positions[i], rotations[i], scales[i]); } } } diff --git a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc index 6d979e3b7da..e030bc3eec6 100644 --- a/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc +++ b/source/blender/nodes/geometry/nodes/node_geo_point_instance.cc @@ -25,6 +25,7 @@ static bNodeSocketTemplate geo_node_point_instance_in[] = { {SOCK_GEOMETRY, N_("Geometry")}, {SOCK_OBJECT, N_("Object")}, + {SOCK_COLLECTION, N_("Collection")}, {-1, ""}, }; @@ -35,9 +36,21 @@ static bNodeSocketTemplate geo_node_point_instance_out[] = { namespace blender::nodes { +static void geo_node_point_instance_update(bNodeTree *UNUSED(tree), bNode *node) +{ + bNodeSocket *object_socket = (bNodeSocket *)BLI_findlink(&node->inputs, 1); + bNodeSocket *collection_socket = object_socket->next; + + GeometryNodePointInstanceType type = (GeometryNodePointInstanceType)node->custom1; + + nodeSetSocketAvailability(object_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_OBJECT); + nodeSetSocketAvailability(collection_socket, type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION); +} + static void add_instances_from_geometry_component(InstancesComponent &instances, const GeometryComponent &src_geometry, - Object *object) + Object *object, + Collection *collection) { Float3ReadAttribute positions = src_geometry.attribute_get_for_read<float3>( "position", ATTR_DOMAIN_POINT, {0, 0, 0}); @@ -47,30 +60,51 @@ static void add_instances_from_geometry_component(InstancesComponent &instances, "scale", ATTR_DOMAIN_POINT, {1, 1, 1}); for (const int i : IndexRange(positions.size())) { - instances.add_instance(object, positions[i], rotations[i], scales[i]); + if (object != nullptr) { + instances.add_instance(object, positions[i], rotations[i], scales[i]); + } + if (collection != nullptr) { + instances.add_instance(collection, positions[i], rotations[i], scales[i]); + } } } static void geo_node_point_instance_exec(GeoNodeExecParams params) { + GeometryNodePointInstanceType type = (GeometryNodePointInstanceType)params.node().custom1; GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry"); GeometrySet geometry_set_out; - bke::PersistentObjectHandle object_handle = params.extract_input<bke::PersistentObjectHandle>( - "Object"); - Object *object = params.handle_map().lookup(object_handle); + Object *object = nullptr; + Collection *collection = nullptr; - if (object != nullptr && object != params.self_object()) { - InstancesComponent &instances = geometry_set_out.get_component_for_write<InstancesComponent>(); - if (geometry_set.has<MeshComponent>()) { - add_instances_from_geometry_component( - instances, *geometry_set.get_component_for_read<MeshComponent>(), object); - } - if (geometry_set.has<PointCloudComponent>()) { - add_instances_from_geometry_component( - instances, *geometry_set.get_component_for_read<PointCloudComponent>(), object); + if (type == GEO_NODE_POINT_INSTANCE_TYPE_OBJECT) { + bke::PersistentObjectHandle object_handle = params.extract_input<bke::PersistentObjectHandle>( + "Object"); + object = params.handle_map().lookup(object_handle); + /* Avoid accidental recursion of instances. */ + if (object == params.self_object()) { + object = nullptr; } } + else if (type == GEO_NODE_POINT_INSTANCE_TYPE_COLLECTION) { + bke::PersistentCollectionHandle collection_handle = + params.extract_input<bke::PersistentCollectionHandle>("Collection"); + collection = params.handle_map().lookup(collection_handle); + } + + InstancesComponent &instances = geometry_set_out.get_component_for_write<InstancesComponent>(); + if (geometry_set.has<MeshComponent>()) { + add_instances_from_geometry_component( + instances, *geometry_set.get_component_for_read<MeshComponent>(), object, collection); + } + if (geometry_set.has<PointCloudComponent>()) { + add_instances_from_geometry_component( + instances, + *geometry_set.get_component_for_read<PointCloudComponent>(), + object, + collection); + } params.set_output("Geometry", std::move(geometry_set_out)); } @@ -82,6 +116,7 @@ void register_node_type_geo_point_instance() geo_node_type_base(&ntype, GEO_NODE_POINT_INSTANCE, "Point Instance", NODE_CLASS_GEOMETRY, 0); node_type_socket_templates(&ntype, geo_node_point_instance_in, geo_node_point_instance_out); + node_type_update(&ntype, blender::nodes::geo_node_point_instance_update); ntype.geometry_node_execute = blender::nodes::geo_node_point_instance_exec; nodeRegisterType(&ntype); } |