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:
Diffstat (limited to 'source/blender/blenkernel/intern/object_dupli.cc')
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc61
1 files changed, 43 insertions, 18 deletions
diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc
index ddf7826969b..768fa9373c1 100644
--- a/source/blender/blenkernel/intern/object_dupli.cc
+++ b/source/blender/blenkernel/intern/object_dupli.cc
@@ -36,6 +36,7 @@
#include "BLI_math.h"
#include "BLI_rand.h"
#include "BLI_span.hh"
+#include "BLI_vector.hh"
#include "DNA_anim_types.h"
#include "DNA_collection_types.h"
@@ -73,6 +74,7 @@ using blender::Array;
using blender::float3;
using blender::float4x4;
using blender::Span;
+using blender::Vector;
/* -------------------------------------------------------------------- */
/** \name Internal Duplicate Context
@@ -90,6 +92,13 @@ struct DupliContext {
Object *object;
float space_mat[4][4];
+ /**
+ * A stack that contains all the "parent" objects of a particular instance when recursive
+ * instancing is used. This is used to prevent objects from instancing themselves accidentally.
+ * Use a vector instead of a stack because we want to use the #contains method.
+ */
+ Vector<Object *> *instance_stack;
+
int persistent_id[MAX_DUPLI_RECUR];
int level;
@@ -113,7 +122,8 @@ static void init_context(DupliContext *r_ctx,
Depsgraph *depsgraph,
Scene *scene,
Object *ob,
- const float space_mat[4][4])
+ const float space_mat[4][4],
+ Vector<Object *> &instance_stack)
{
r_ctx->depsgraph = depsgraph;
r_ctx->scene = scene;
@@ -122,6 +132,7 @@ static void init_context(DupliContext *r_ctx,
r_ctx->object = ob;
r_ctx->obedit = OBEDIT_FROM_OBACT(ob);
+ r_ctx->instance_stack = &instance_stack;
if (space_mat) {
copy_m4_m4(r_ctx->space_mat, space_mat);
}
@@ -150,6 +161,7 @@ static void copy_dupli_context(
}
r_ctx->object = ob;
+ r_ctx->instance_stack = ctx->instance_stack;
if (mat) {
mul_m4_m4m4(r_ctx->space_mat, (float(*)[4])ctx->space_mat, mat);
}
@@ -235,12 +247,19 @@ static void make_recursive_duplis(const DupliContext *ctx,
const float space_mat[4][4],
int index)
{
+ if (ctx->instance_stack->contains(ob)) {
+ /* Avoid recursive instances. */
+ printf("Warning: '%s' object is trying to instance itself.\n", ob->id.name + 2);
+ return;
+ }
/* Simple preventing of too deep nested collections with #MAX_DUPLI_RECUR. */
if (ctx->level < MAX_DUPLI_RECUR) {
DupliContext rctx;
copy_dupli_context(&rctx, ctx, ob, space_mat, index);
if (rctx.gen) {
+ ctx->instance_stack->append(ob);
rctx.gen->make_duplis(&rctx);
+ ctx->instance_stack->remove_last();
}
}
}
@@ -823,38 +842,38 @@ static void make_duplis_instances_component(const DupliContext *ctx)
return;
}
- Span<float4x4> instance_offset_matrices = component->transforms();
+ Span<float4x4> instance_offset_matrices = component->instance_transforms();
+ Span<int> instance_reference_handles = component->instance_reference_handles();
Span<int> almost_unique_ids = component->almost_unique_ids();
- Span<InstancedData> instanced_data = component->instanced_data();
+ Span<InstanceReference> references = component->references();
- for (int i = 0; i < component->instances_amount(); i++) {
- const InstancedData &data = instanced_data[i];
+ for (int64_t i : instance_offset_matrices.index_range()) {
+ const InstanceReference &reference = references[instance_reference_handles[i]];
const int id = almost_unique_ids[i];
- if (data.type == INSTANCE_DATA_TYPE_OBJECT) {
- Object *object = data.data.object;
- if (object != nullptr) {
+ switch (reference.type()) {
+ case InstanceReference::Type::Object: {
+ Object &object = reference.object();
float matrix[4][4];
mul_m4_m4m4(matrix, ctx->object->obmat, instance_offset_matrices[i].values);
- make_dupli(ctx, object, matrix, id);
+ make_dupli(ctx, &object, matrix, id);
float space_matrix[4][4];
- mul_m4_m4m4(space_matrix, instance_offset_matrices[i].values, object->imat);
+ mul_m4_m4m4(space_matrix, instance_offset_matrices[i].values, object.imat);
mul_m4_m4_pre(space_matrix, ctx->object->obmat);
- make_recursive_duplis(ctx, object, space_matrix, id);
+ make_recursive_duplis(ctx, &object, space_matrix, id);
+ break;
}
- }
- else if (data.type == INSTANCE_DATA_TYPE_COLLECTION) {
- Collection *collection = data.data.collection;
- if (collection != nullptr) {
+ case InstanceReference::Type::Collection: {
+ Collection &collection = reference.collection();
float collection_matrix[4][4];
unit_m4(collection_matrix);
- sub_v3_v3(collection_matrix[3], collection->instance_offset);
+ sub_v3_v3(collection_matrix[3], collection.instance_offset);
mul_m4_m4_pre(collection_matrix, instance_offset_matrices[i].values);
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) {
+ FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN (&collection, object, mode) {
if (object == ctx->object) {
continue;
}
@@ -866,6 +885,10 @@ static void make_duplis_instances_component(const DupliContext *ctx)
make_recursive_duplis(ctx, object, collection_matrix, id);
}
FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END;
+ break;
+ }
+ case InstanceReference::Type::None: {
+ break;
}
}
}
@@ -1588,7 +1611,9 @@ ListBase *object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob)
{
ListBase *duplilist = (ListBase *)MEM_callocN(sizeof(ListBase), "duplilist");
DupliContext ctx;
- init_context(&ctx, depsgraph, sce, ob, nullptr);
+ Vector<Object *> instance_stack;
+ instance_stack.append(ob);
+ init_context(&ctx, depsgraph, sce, ob, nullptr, instance_stack);
if (ctx.gen) {
ctx.duplilist = duplilist;
ctx.gen->make_duplis(&ctx);