Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2020-12-11 20:00:37 +0300
committerJacques Lucke <jacques@blender.org>2020-12-11 20:00:37 +0300
commitf5dc34ec9c05cc8f1163313baafe634f4798c29b (patch)
treeb3cc27fc8009fc0180f4b35c5c3646cb2527a72c /source/blender/blenkernel
parent5ced167336d49ef42e96e205c72d3935ff302a7e (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/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.h16
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh15
-rw-r--r--source/blender/blenkernel/intern/geometry_set.cc46
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c53
4 files changed, 103 insertions, 27 deletions
diff --git a/source/blender/blenkernel/BKE_geometry_set.h b/source/blender/blenkernel/BKE_geometry_set.h
index 026f4d39d51..87bb96be145 100644
--- a/source/blender/blenkernel/BKE_geometry_set.h
+++ b/source/blender/blenkernel/BKE_geometry_set.h
@@ -26,16 +26,30 @@ extern "C" {
struct Object;
struct GeometrySet;
+struct Collection;
void BKE_geometry_set_free(struct GeometrySet *geometry_set);
bool BKE_geometry_set_has_instances(const struct GeometrySet *geometry_set);
+typedef enum InstancedDataType {
+ INSTANCE_DATA_TYPE_OBJECT = 0,
+ INSTANCE_DATA_TYPE_COLLECTION = 1,
+} InstancedDataType;
+
+typedef struct InstancedData {
+ InstancedDataType type;
+ union {
+ struct Object *object;
+ struct Collection *collection;
+ } data;
+} InstancedData;
+
int BKE_geometry_set_instances(const struct GeometrySet *geometry_set,
float (**r_positions)[3],
float (**r_rotations)[3],
float (**r_scales)[3],
- struct Object ***r_objects);
+ struct InstancedData **r_instanced_data);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index b7cb9320086..617e0c45ae4 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -35,6 +35,7 @@
struct Mesh;
struct PointCloud;
struct Object;
+struct Collection;
/* Each geometry component has a specific type. The type determines what kind of data the component
* stores. Functions modifying a geometry will usually just modify a subset of the component types.
@@ -358,7 +359,7 @@ class InstancesComponent : public GeometryComponent {
blender::Vector<blender::float3> positions_;
blender::Vector<blender::float3> rotations_;
blender::Vector<blender::float3> scales_;
- blender::Vector<const Object *> objects_;
+ blender::Vector<InstancedData> instanced_data_;
public:
InstancesComponent();
@@ -366,12 +367,20 @@ class InstancesComponent : public GeometryComponent {
GeometryComponent *copy() const override;
void clear();
- void add_instance(const Object *object,
+ void add_instance(Object *object,
blender::float3 position,
blender::float3 rotation = {0, 0, 0},
blender::float3 scale = {1, 1, 1});
+ void add_instance(Collection *collection,
+ blender::float3 position,
+ blender::float3 rotation = {0, 0, 0},
+ blender::float3 scale = {1, 1, 1});
+ void add_instance(InstancedData data,
+ blender::float3 position,
+ blender::float3 rotation,
+ blender::float3 scale);
- blender::Span<const Object *> objects() const;
+ blender::Span<InstancedData> instanced_data() const;
blender::Span<blender::float3> positions() const;
blender::Span<blender::float3> rotations() const;
blender::Span<blender::float3> scales() const;
diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index 28695d769d3..e6a67b191f8 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -460,31 +460,54 @@ GeometryComponent *InstancesComponent::copy() const
new_component->positions_ = positions_;
new_component->rotations_ = rotations_;
new_component->scales_ = scales_;
- new_component->objects_ = objects_;
+ new_component->instanced_data_ = instanced_data_;
return new_component;
}
void InstancesComponent::clear()
{
- objects_.clear();
+ instanced_data_.clear();
positions_.clear();
rotations_.clear();
scales_.clear();
}
-void InstancesComponent::add_instance(const Object *object,
+
+void InstancesComponent::add_instance(Object *object,
+ blender::float3 position,
+ blender::float3 rotation,
+ blender::float3 scale)
+{
+ InstancedData data;
+ data.type = INSTANCE_DATA_TYPE_OBJECT;
+ data.data.object = object;
+ this->add_instance(data, position, rotation, scale);
+}
+
+void InstancesComponent::add_instance(Collection *collection,
+ blender::float3 position,
+ blender::float3 rotation,
+ blender::float3 scale)
+{
+ InstancedData data;
+ data.type = INSTANCE_DATA_TYPE_COLLECTION;
+ data.data.collection = collection;
+ this->add_instance(data, position, rotation, scale);
+}
+
+void InstancesComponent::add_instance(InstancedData data,
blender::float3 position,
blender::float3 rotation,
blender::float3 scale)
{
- objects_.append(object);
+ instanced_data_.append(data);
positions_.append(position);
rotations_.append(rotation);
scales_.append(scale);
}
-Span<const Object *> InstancesComponent::objects() const
+Span<InstancedData> InstancesComponent::instanced_data() const
{
- return objects_;
+ return instanced_data_;
}
Span<float3> InstancesComponent::positions() const
@@ -509,8 +532,11 @@ MutableSpan<float3> InstancesComponent::positions()
int InstancesComponent::instances_amount() const
{
- BLI_assert(positions_.size() == objects_.size());
- return objects_.size();
+ const int size = instanced_data_.size();
+ BLI_assert(positions_.size() == size);
+ BLI_assert(rotations_.size() == size);
+ BLI_assert(scales_.size() == size);
+ return size;
}
bool InstancesComponent::is_empty() const
@@ -538,7 +564,7 @@ int BKE_geometry_set_instances(const GeometrySet *geometry_set,
float (**r_positions)[3],
float (**r_rotations)[3],
float (**r_scales)[3],
- Object ***r_objects)
+ InstancedData **r_instanced_data)
{
const InstancesComponent *component = geometry_set->get_component_for_read<InstancesComponent>();
if (component == nullptr) {
@@ -547,7 +573,7 @@ int BKE_geometry_set_instances(const GeometrySet *geometry_set,
*r_positions = (float(*)[3])component->positions().data();
*r_rotations = (float(*)[3])component->rotations().data();
*r_scales = (float(*)[3])component->scales().data();
- *r_objects = (Object **)component->objects().data();
+ *r_instanced_data = (InstancedData *)component->instanced_data().data();
return component->instances_amount();
}
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index d5434710e23..8fa708f31cb 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -816,15 +816,13 @@ static void make_duplis_instances_component(const DupliContext *ctx)
float(*positions)[3];
float(*rotations)[3];
float(*scales)[3];
- Object **objects;
+ InstancedData *instanced_data;
const int amount = BKE_geometry_set_instances(
- ctx->object->runtime.geometry_set_eval, &positions, &rotations, &scales, &objects);
+ ctx->object->runtime.geometry_set_eval, &positions, &rotations, &scales, &instanced_data);
for (int i = 0; i < amount; i++) {
- Object *object = objects[i];
- if (object == NULL) {
- continue;
- }
+ InstancedData *data = &instanced_data[i];
+
float scale_matrix[4][4];
size_to_mat4(scale_matrix, scales[i]);
float rotation_matrix[4][4];
@@ -833,14 +831,43 @@ static void make_duplis_instances_component(const DupliContext *ctx)
mul_m4_m4m4(instance_offset_matrix, rotation_matrix, scale_matrix);
copy_v3_v3(instance_offset_matrix[3], positions[i]);
- float matrix[4][4];
- mul_m4_m4m4(matrix, ctx->object->obmat, instance_offset_matrix);
- make_dupli(ctx, object, matrix, i);
+ if (data->type == INSTANCE_DATA_TYPE_OBJECT) {
+ Object *object = data->data.object;
+ if (object != NULL) {
+ float matrix[4][4];
+ mul_m4_m4m4(matrix, ctx->object->obmat, instance_offset_matrix);
+ make_dupli(ctx, object, matrix, i);
+
+ float space_matrix[4][4];
+ mul_m4_m4m4(space_matrix, instance_offset_matrix, object->imat);
+ mul_m4_m4_pre(space_matrix, ctx->object->obmat);
+ make_recursive_duplis(ctx, object, space_matrix, i);
+ }
+ }
+ else if (data->type == INSTANCE_DATA_TYPE_COLLECTION) {
+ Collection *collection = data->data.collection;
+ if (collection != NULL) {
+ float collection_matrix[4][4];
+ unit_m4(collection_matrix);
+ sub_v3_v3(collection_matrix[3], collection->instance_offset);
+ mul_m4_m4_pre(collection_matrix, instance_offset_matrix);
+ mul_m4_m4_pre(collection_matrix, ctx->object->obmat);
+
+ eEvaluationMode mode = DEG_get_mode(ctx->depsgraph);
+ FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (collection, object, mode) {
+ if (object == ctx->object) {
+ continue;
+ }
+
+ float instance_matrix[4][4];
+ mul_m4_m4m4(instance_matrix, collection_matrix, object->obmat);
- float space_matrix[4][4];
- mul_m4_m4m4(space_matrix, instance_offset_matrix, object->imat);
- mul_m4_m4_pre(space_matrix, ctx->object->obmat);
- make_recursive_duplis(ctx, object, space_matrix, i);
+ make_dupli(ctx, object, instance_matrix, i);
+ make_recursive_duplis(ctx, object, collection_matrix, i);
+ }
+ FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
+ }
+ }
}
}