diff options
Diffstat (limited to 'source/blender/blenkernel/intern/object_dupli.c')
-rw-r--r-- | source/blender/blenkernel/intern/object_dupli.c | 175 |
1 files changed, 94 insertions, 81 deletions
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 56d5cb609fc..391be751ae0 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -49,10 +49,10 @@ #include "BKE_animsys.h" #include "BKE_DerivedMesh.h" -#include "BKE_depsgraph.h" #include "BKE_font.h" -#include "BKE_group.h" #include "BKE_global.h" +#include "BKE_group.h" +#include "BKE_idprop.h" #include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -62,6 +62,7 @@ #include "BKE_editmesh.h" #include "BKE_anim.h" +#include "DEG_depsgraph.h" #include "BLI_strict_flags.h" #include "BLI_hash.h" @@ -69,15 +70,16 @@ /* Dupli-Geometry */ typedef struct DupliContext { - EvaluationContext *eval_ctx; + const EvaluationContext *eval_ctx; bool do_update; bool animated; Group *group; /* XXX child objects are selected from this group if set, could be nicer */ + Object *obedit; /* Only to check if the object is in edit-mode. */ Scene *scene; + ViewLayer *view_layer; Object *object; float space_mat[4][4]; - unsigned int lay; int persistent_id[MAX_DUPLI_RECUR]; int level; @@ -96,21 +98,22 @@ typedef struct DupliGenerator { static const DupliGenerator *get_dupli_generator(const DupliContext *ctx); /* create initial context for root object */ -static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], bool update) +static void init_context(DupliContext *r_ctx, const EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], bool update) { r_ctx->eval_ctx = eval_ctx; r_ctx->scene = scene; + r_ctx->view_layer = eval_ctx->view_layer; /* don't allow BKE_object_handle_update for viewport during render, can crash */ r_ctx->do_update = update && !(G.is_rendering && eval_ctx->mode != DAG_EVAL_RENDER); r_ctx->animated = false; r_ctx->group = NULL; + r_ctx->obedit = OBEDIT_FROM_EVAL_CTX(eval_ctx); r_ctx->object = ob; if (space_mat) copy_m4_m4(r_ctx->space_mat, space_mat); else unit_m4(r_ctx->space_mat); - r_ctx->lay = ob->lay; r_ctx->level = 0; r_ctx->gen = get_dupli_generator(r_ctx); @@ -143,7 +146,8 @@ static void copy_dupli_context(DupliContext *r_ctx, const DupliContext *ctx, Obj */ static DupliObject *make_dupli(const DupliContext *ctx, Object *ob, float mat[4][4], int index, - bool animated, bool hide) + bool animated, bool hide, + IDProperty *collection_properties) { DupliObject *dob; int i; @@ -198,6 +202,10 @@ static DupliObject *make_dupli(const DupliContext *ctx, dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->object->id.name + 2)); } + if (collection_properties) { + dob->collection_properties = IDP_CopyProperty(collection_properties); + } + return dob; } @@ -235,35 +243,32 @@ static bool is_child(const Object *ob, const Object *parent) static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChildDuplisFunc make_child_duplis_cb) { Object *parent = ctx->object; - Object *obedit = ctx->scene->obedit; if (ctx->group) { - unsigned int lay = ctx->group->layer; int groupid = 0; - GroupObject *go; - for (go = ctx->group->gobject.first; go; go = go->next, groupid++) { - Object *ob = go->ob; - - if ((ob->lay & lay) && ob != obedit && is_child(ob, parent)) { + FOREACH_GROUP_BASE_BEGIN(ctx->group, base) + { + Object *ob = base->object; + if ((base->flag & BASE_VISIBLED) && ob != ctx->obedit && is_child(ob, parent)) { DupliContext pctx; copy_dupli_context(&pctx, ctx, ctx->object, NULL, groupid, false); /* mballs have a different dupli handling */ - if (ob->type != OB_MBALL) + if (ob->type != OB_MBALL) { ob->flag |= OB_DONE; /* doesnt render */ - + } make_child_duplis_cb(&pctx, userdata, ob); } + groupid++; } + FOREACH_GROUP_BASE_END } else { - unsigned int lay = ctx->scene->lay; int baseid = 0; - Base *base; - for (base = ctx->scene->base.first; base; base = base->next, baseid++) { + ViewLayer *view_layer = ctx->view_layer; + for (Base *base = view_layer->object_bases.first; base; base = base->next, baseid++) { Object *ob = base->object; - - if ((base->lay & lay) && ob != obedit && is_child(ob, parent)) { + if ((ob != ctx->obedit) && is_child(ob, parent)) { DupliContext pctx; copy_dupli_context(&pctx, ctx, ctx->object, NULL, baseid, false); @@ -283,13 +288,12 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild /* OB_DUPLIGROUP */ static void make_duplis_group(const DupliContext *ctx) { - bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER); Object *ob = ctx->object; Group *group; - GroupObject *go; + Base *base; float group_mat[4][4]; int id; - bool animated, hide; + bool animated; if (ob->dup_group == NULL) return; group = ob->dup_group; @@ -311,34 +315,18 @@ static void make_duplis_group(const DupliContext *ctx) animated = BKE_group_is_animated(group, ob); - for (go = group->gobject.first, id = 0; go; go = go->next, id++) { - /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ - if (go->ob != ob) { + for (base = group->view_layer->object_bases.first, id = 0; base; base = base->next, id++) { + if (base->object != ob && (base->flag & BASE_VISIBLED)) { float mat[4][4]; - /* Special case for instancing dupli-groups, see: T40051 - * this object may be instanced via dupli-verts/faces, in this case we don't want to render - * (blender convention), but _do_ show in the viewport. - * - * Regular objects work fine but not if we're instancing dupli-groups, - * because the rules for rendering aren't applied to objects they instance. - * We could recursively pass down the 'hide' flag instead, but that seems unnecessary. - */ - if (for_render && go->ob->parent && go->ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES)) { - continue; - } - /* group dupli offset, should apply after everything else */ - mul_m4_m4m4(mat, group_mat, go->ob->obmat); + mul_m4_m4m4(mat, group_mat, base->object->obmat); - /* check the group instance and object layers match, also that the object visible flags are ok. */ - hide = (go->ob->lay & group->layer) == 0 || - (for_render ? go->ob->restrictflag & OB_RESTRICT_RENDER : go->ob->restrictflag & OB_RESTRICT_VIEW); - - make_dupli(ctx, go->ob, mat, id, animated, hide); + BLI_assert(base->collection_properties != NULL); + make_dupli(ctx, base->object, mat, id, animated, false, base->collection_properties); /* recursion */ - make_recursive_duplis(ctx, go->ob, group_mat, id, animated); + make_recursive_duplis(ctx, base->object, group_mat, id, animated); } } } @@ -377,10 +365,6 @@ static void make_duplis_frames(const DupliContext *ctx) /* duplicate over the required range */ if (ob->transflag & OB_DUPLINOSPEED) enable_cu_speed = 0; - /* special flag to avoid setting recalc flags to notify the depsgraph of - * updates, as this is not a permanent change to the object */ - ob->id.recalc |= ID_RECALC_SKIP_ANIM_TAG; - for (scene->r.cfra = ob->dupsta; scene->r.cfra <= dupend; scene->r.cfra++) { int ok = 1; @@ -399,9 +383,9 @@ static void make_duplis_frames(const DupliContext *ctx) * However, this has always been the way that this worked (i.e. pre 2.5), so I guess that it'll be fine! */ BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ - BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra); + BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, (float)scene->r.cfra); - make_dupli(ctx, ob, ob->obmat, scene->r.cfra, false, false); + make_dupli(ctx, ob, ob->obmat, scene->r.cfra, false, false, NULL); } } @@ -413,7 +397,7 @@ static void make_duplis_frames(const DupliContext *ctx) scene->r.cfra = cfrao; BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ - BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra); + BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, (float)scene->r.cfra); /* but, to make sure unkeyed object transforms are still sane, * let's copy object's original data back over @@ -486,7 +470,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], */ mul_m4_m4m4(space_mat, obmat, inst_ob->imat); - dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index, false, false); + dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index, false, false, NULL); if (vdd->orco) copy_v3_v3(dob->orco, vdd->orco[index]); @@ -548,13 +532,13 @@ static void make_duplis_verts(const DupliContext *ctx) CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH); if (ctx->eval_ctx->mode == DAG_EVAL_RENDER) { - vdd.dm = mesh_create_derived_render(scene, parent, dm_mask); + vdd.dm = mesh_create_derived_render(ctx->eval_ctx, scene, parent, dm_mask); } else if (em) { - vdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); + vdd.dm = editbmesh_get_derived_cage(ctx->eval_ctx, scene, parent, em, dm_mask); } else { - vdd.dm = mesh_get_derived_final(scene, parent, dm_mask); + vdd.dm = mesh_get_derived_final(ctx->eval_ctx, scene, parent, dm_mask); } vdd.edit_btmesh = me->edit_btmesh; @@ -671,7 +655,7 @@ static void make_duplis_font(const DupliContext *ctx) copy_v3_v3(obmat[3], vec); - make_dupli(ctx, ob, obmat, a, false, false); + make_dupli(ctx, ob, obmat, a, false, false, NULL); } } @@ -777,7 +761,7 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj */ mul_m4_m4m4(space_mat, obmat, inst_ob->imat); - dob = make_dupli(ctx, inst_ob, obmat, a, false, false); + dob = make_dupli(ctx, inst_ob, obmat, a, false, false, NULL); if (use_texcoords) { float w = 1.0f / (float)mp->totloop; @@ -816,13 +800,13 @@ static void make_duplis_faces(const DupliContext *ctx) CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH); if (ctx->eval_ctx->mode == DAG_EVAL_RENDER) { - fdd.dm = mesh_create_derived_render(scene, parent, dm_mask); + fdd.dm = mesh_create_derived_render(ctx->eval_ctx, scene, parent, dm_mask); } else if (em) { - fdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); + fdd.dm = editbmesh_get_derived_cage(ctx->eval_ctx, scene, parent, em, dm_mask); } else { - fdd.dm = mesh_get_derived_final(scene, parent, dm_mask); + fdd.dm = mesh_get_derived_final(ctx->eval_ctx, scene, parent, dm_mask); } if (use_texcoords) { @@ -860,7 +844,6 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER; bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); - GroupObject *go; Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; DupliObject *dob; ParticleDupliWeight *dw; @@ -900,6 +883,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { ParticleSimulationData sim = {NULL}; + sim.eval_ctx = ctx->eval_ctx; sim.scene = scene; sim.ob = par; sim.psys = psys; @@ -913,10 +897,10 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem return; } else { /*PART_DRAW_GR */ - if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->gobject)) + if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->view_layer->object_bases)) return; - if (BLI_findptr(&part->dup_group->gobject, par, offsetof(GroupObject, ob))) { + if (BLI_findptr(&part->dup_group->view_layer->object_bases, par, offsetof(Base, object))) { return; } } @@ -948,8 +932,12 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem totgroup += dw->count; } else { - for (go = part->dup_group->gobject.first; go; go = go->next) + FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object) + { + (void) object; totgroup++; + } + FOREACH_GROUP_OBJECT_END } /* we also copy the actual objects to restore afterwards, since @@ -968,11 +956,18 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem } } else { - go = part->dup_group->gobject.first; - for (a = 0; a < totgroup; a++, go = go->next) { - oblist[a] = go->ob; - obcopylist[a] = *go->ob; + a = 0; + FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object) + { + oblist[a] = object; + obcopylist[a] = *object; + a++; + + if (a >= totgroup) { + continue; + } } + FOREACH_GROUP_OBJECT_END } } else { @@ -1061,27 +1056,37 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem } if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { - for (go = part->dup_group->gobject.first, b = 0; go; go = go->next, b++) { - + b = 0; + FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object) + { copy_m4_m4(tmat, oblist[b]->obmat); + /* apply particle scale */ mul_mat3_m4_fl(tmat, size * scale); mul_v3_fl(tmat[3], size * scale); + /* group dupli offset, should apply after everything else */ - if (!is_zero_v3(part->dup_group->dupli_ofs)) + if (!is_zero_v3(part->dup_group->dupli_ofs)) { sub_v3_v3(tmat[3], part->dup_group->dupli_ofs); + } + /* individual particle transform */ mul_m4_m4m4(mat, pamat, tmat); - dob = make_dupli(ctx, go->ob, mat, a, false, false); + dob = make_dupli(ctx, object, mat, a, false, false, NULL); dob->particle_system = psys; - if (use_texcoords) + + if (use_texcoords) { psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); + } + + b++; } + FOREACH_GROUP_OBJECT_END } else { /* to give ipos in object correct offset */ - BKE_object_where_is_calc_time(scene, ob, ctime - pa_time); + BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, ctime - pa_time); copy_v3_v3(vec, obmat[3]); obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; @@ -1122,7 +1127,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); - dob = make_dupli(ctx, ob, mat, a, false, false); + dob = make_dupli(ctx, ob, mat, a, false, false, NULL); dob->particle_system = psys; if (use_texcoords) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); @@ -1217,7 +1222,7 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx) /* ---- ListBase dupli container implementation ---- */ /* Returns a list of DupliObject */ -ListBase *object_duplilist_ex(EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update) +ListBase *object_duplilist_ex(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update) { ListBase *duplilist = MEM_callocN(sizeof(ListBase), "duplilist"); DupliContext ctx; @@ -1232,13 +1237,21 @@ ListBase *object_duplilist_ex(EvaluationContext *eval_ctx, Scene *scene, Object /* note: previously updating was always done, this is why it defaults to be on * but there are likely places it can be called without updating */ -ListBase *object_duplilist(EvaluationContext *eval_ctx, Scene *sce, Object *ob) +ListBase *object_duplilist(const EvaluationContext *eval_ctx, Scene *sce, Object *ob) { return object_duplilist_ex(eval_ctx, sce, ob, true); } void free_object_duplilist(ListBase *lb) { + + for (DupliObject *dob = lb->first; dob; dob = dob->next) { + if (dob->collection_properties) { + IDP_FreeProperty(dob->collection_properties); + MEM_freeN(dob->collection_properties); + } + } + BLI_freelistN(lb); MEM_freeN(lb); } @@ -1273,7 +1286,7 @@ int count_duplilist(Object *ob) return 1; } -DupliApplyData *duplilist_apply(Object *ob, Scene *scene, ListBase *duplilist) +DupliApplyData *duplilist_apply(const EvaluationContext *eval_ctx, Object *ob, Scene *scene, ListBase *duplilist) { DupliApplyData *apply_data = NULL; int num_objects = BLI_listbase_count(duplilist); @@ -1289,7 +1302,7 @@ DupliApplyData *duplilist_apply(Object *ob, Scene *scene, ListBase *duplilist) for (dob = duplilist->first, i = 0; dob; dob = dob->next, ++i) { /* make sure derivedmesh is calculated once, before drawing */ if (scene && !(dob->ob->transflag & OB_DUPLICALCDERIVED) && dob->ob->type == OB_MESH) { - mesh_get_derived_final(scene, dob->ob, scene->customdata_mask); + mesh_get_derived_final(eval_ctx, scene, dob->ob, scene->customdata_mask); dob->ob->transflag |= OB_DUPLICALCDERIVED; } } |