Initial implememtation for dupli objects

Now dupli groups, objects, particles, ... are all working.

This introduces a flag for the iterator to determine whether we go over
Set and dupli objects or not.

Important to remember to keep the iteration of DEG_ as readonly.

Cycles is not working well for dupli groups, and it's memleaking
for dupli particles. So for now we iterate over main objects and set
only, not dupli.

To change that go in rna_scene.c and:

-DEG_OBJECT_ITER(graph, ob, DEG_OBJECT_ITER_FLAG_SET)
+DEG_OBJECT_ITER(graph, ob, DEG_OBJECT_ITER_FLAG_ALL)

Review and suggestions by Sergey Sharybin
This commit is contained in:
Dalai Felinto 2017-06-01 15:26:47 +02:00
parent f8ea2c92db
commit 824bf261f7
Notes: blender-bot 2023-02-14 08:07:50 +01:00
Referenced by commit c5dccc9734, Fixup for 824bf261f7 so Cycles does not show dupli
5 changed files with 138 additions and 43 deletions

View File

@ -35,8 +35,12 @@
struct ID;
struct Depsgraph;
struct Base;
struct BLI_Iterator;
struct Depsgraph;
struct DupliObject;
struct ListBase;
struct Scene;
struct SceneLayer;
#ifdef __cplusplus
@ -60,19 +64,48 @@ struct Object *DEG_get_object(struct Depsgraph *depsgraph, struct Object *ob);
/* ************************ DAG iterators ********************* */
void DEG_objects_iterator_begin(struct BLI_Iterator *iter, void *data_in);
enum {
DEG_OBJECT_ITER_FLAG_SET = (1 << 0),
DEG_OBJECT_ITER_FLAG_DUPLI = (1 << 1),
};
#define DEG_OBJECT_ITER_FLAG_ALL (DEG_OBJECT_ITER_FLAG_SET | DEG_OBJECT_ITER_FLAG_DUPLI)
typedef struct DEGObjectsIteratorData {
struct Depsgraph *graph;
struct Scene *scene;
struct EvaluationContext *eval_ctx;
struct SceneLayer *scene_layer;
struct Base *base;
int base_flag;
int flag;
/* Dupli */
struct ListBase *dupli_list;
struct DupliObject *dupli_object;
struct Object temp_dupli_object;
} DEGObjectsIteratorData;
void DEG_objects_iterator_begin(struct BLI_Iterator *iter, DEGObjectsIteratorData *data);
void DEG_objects_iterator_next(struct BLI_Iterator *iter);
void DEG_objects_iterator_end(struct BLI_Iterator *iter);
/* Temporary hacky solution waiting for cow depsgraph implementation. */
#define DEG_OBJECT_ITER(graph_, instance_) \
ITER_BEGIN(DEG_objects_iterator_begin, \
DEG_objects_iterator_next, \
DEG_objects_iterator_end, \
graph_, Object *, instance_)
#define DEG_OBJECT_ITER(graph_, instance_, flag_) \
{ \
DEGObjectsIteratorData data_ = { \
.graph = (graph_), \
.flag = (flag_), \
}; \
\
ITER_BEGIN(DEG_objects_iterator_begin, \
DEG_objects_iterator_next, \
DEG_objects_iterator_end, \
&data_, Object *, instance_)
#define DEG_OBJECT_ITER_END \
ITER_END
#define DEG_OBJECT_ITER_END \
ITER_END \
}
#ifdef __cplusplus
} /* extern "C" */

View File

@ -33,6 +33,8 @@
#include "MEM_guardedalloc.h"
extern "C" {
#include "BLI_math.h"
#include "BKE_anim.h"
#include "BKE_idcode.h"
#include "BKE_layer.h"
#include "BKE_main.h"
@ -40,6 +42,7 @@ extern "C" {
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
} /* extern "C" */
@ -97,42 +100,88 @@ Object *DEG_get_object(Depsgraph * /*depsgraph*/, Object *ob)
/* ************************ DAG ITERATORS ********************* */
typedef struct DEGObjectsIteratorData {
Depsgraph *graph;
Scene *scene;
SceneLayer *scene_layer;
Base *base;
int flag;
} DEGObjectsIteratorData;
void DEG_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
void DEG_objects_iterator_begin(BLI_Iterator *iter, DEGObjectsIteratorData *data)
{
SceneLayer *scene_layer;
Depsgraph *graph = (Depsgraph *) data_in;
DEGObjectsIteratorData *data = (DEGObjectsIteratorData *)
MEM_callocN(sizeof(DEGObjectsIteratorData), __func__);
Depsgraph *graph = data->graph;
iter->data = data;
iter->valid = true;
data->graph = graph;
/* TODO: Make it in-place initilization of evaluation context. */
data->eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER);
data->scene = DEG_get_scene(graph);
scene_layer = DEG_get_scene_layer(graph);
data->flag = ~(BASE_FROM_SET);
data->base_flag = ~(BASE_FROM_SET);
Base base = {(Base *)scene_layer->object_bases.first, NULL};
data->base = &base;
DEG_objects_iterator_next(iter);
}
/**
* Temporary function to flush depsgraph until we get copy on write (CoW)
*/
static void deg_flush_data(Object *ob, Base *base, const int flag)
{
ob->base_flag = (base->flag | BASE_FROM_SET) & flag;
ob->base_collection_properties = base->collection_properties;
ob->base_selection_color = base->selcol;
}
static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
{
DEGObjectsIteratorData *data = (DEGObjectsIteratorData *)iter->data;
while (data->dupli_object) {
DupliObject *dob = data->dupli_object;
Object *obd = dob->ob;
data->dupli_object = data->dupli_object->next;
/* Group duplis need to set ob matrices correct, for deform. so no_draw is part handled. */
if ((obd->transflag & OB_RENDER_DUPLI) == 0 && dob->no_draw) {
continue;
}
if (obd->type == OB_MBALL) {
continue;
}
/* Temporary object to evaluate. */
data->temp_dupli_object = *dob->ob;
copy_m4_m4(data->temp_dupli_object.obmat, dob->mat);
deg_flush_data(&data->temp_dupli_object, data->base, data->base_flag | BASE_FROMDUPLI);
iter->current = &data->temp_dupli_object;
return true;
}
return false;
}
void DEG_objects_iterator_next(BLI_Iterator *iter)
{
DEGObjectsIteratorData *data = (DEGObjectsIteratorData *)iter->data;
Base *base = data->base->next;
Base *base;
if (data->dupli_list) {
if (deg_objects_dupli_iterator_next(iter)) {
return;
}
else {
free_object_duplilist(data->dupli_list);
data->dupli_list = NULL;
data->dupli_object = NULL;
}
}
base = data->base->next;
while (base) {
if ((base->flag & BASE_VISIBLED) != 0) {
Object *ob = DEG_get_object(data->graph, base->object);
iter->current = ob;
data->base = base;
/* Make sure we have the base collection settings is already populated.
* This will fail when BKE_layer_eval_layer_collection_pre hasn't run yet
@ -140,20 +189,23 @@ void DEG_objects_iterator_next(BLI_Iterator *iter)
BLI_assert(!BLI_listbase_is_empty(&base->collection_properties->data.group));
/* Flushing depsgraph data. */
ob->base_flag = (base->flag | BASE_FROM_SET) & data->flag;
ob->base_collection_properties = base->collection_properties;
ob->base_selection_color = base->selcol;
data->base = base;
deg_flush_data(ob, base, data->base_flag);
if ((data->flag & DEG_OBJECT_ITER_FLAG_DUPLI) && (ob->transflag & OB_DUPLI)) {
data->dupli_list = object_duplilist(data->eval_ctx, data->scene, ob);
data->dupli_object = (DupliObject *)data->dupli_list->first;
}
return;
}
base = base->next;
}
/* Look for an object in the next set. */
if (data->scene->set) {
if ((data->flag & DEG_OBJECT_ITER_FLAG_SET) && data->scene->set) {
SceneLayer *scene_layer;
data->scene = data->scene->set;
data->flag = ~(BASE_SELECTED | BASE_SELECTABLED);
data->base_flag = ~(BASE_SELECTED | BASE_SELECTABLED);
/* For the sets we use the layer used for rendering. */
scene_layer = BKE_scene_layer_render_active(data->scene);
@ -171,7 +223,7 @@ void DEG_objects_iterator_next(BLI_Iterator *iter)
void DEG_objects_iterator_end(BLI_Iterator *iter)
{
DEGObjectsIteratorData *data = (DEGObjectsIteratorData *)iter->data;
if (data) {
MEM_freeN(data);
if (data->eval_ctx != NULL) {
DEG_evaluation_context_free(data->eval_ctx);
}
}

View File

@ -206,7 +206,7 @@ typedef struct DRWCallHeader {
typedef struct DRWCall {
DRWCallHeader head;
float (*obmat)[4];
float obmat[4][4];
Batch *geometry;
Object *ob; /* Optionnal */
@ -215,7 +215,7 @@ typedef struct DRWCall {
typedef struct DRWCallGenerate {
DRWCallHeader head;
float (*obmat)[4];
float obmat[4][4];
DRWCallGenerateFn *geometry_fn;
void *user_data;
@ -848,7 +848,10 @@ void DRW_shgroup_call_add(DRWShadingGroup *shgroup, Batch *geom, float (*obmat)[
call->head.select_id = g_DRW_select_id;
#endif
call->obmat = obmat;
if (obmat != NULL) {
copy_m4_m4(call->obmat, obmat);
}
call->geometry = geom;
BLI_addtail(&shgroup->calls, call);
@ -865,7 +868,7 @@ void DRW_shgroup_call_object_add(DRWShadingGroup *shgroup, Batch *geom, Object *
call->head.select_id = g_DRW_select_id;
#endif
call->obmat = ob->obmat;
copy_m4_m4(call->obmat, ob->obmat);
call->geometry = geom;
call->ob = ob;
@ -886,7 +889,9 @@ void DRW_shgroup_call_generate_add(
call->head.select_id = g_DRW_select_id;
#endif
call->obmat = obmat;
if (obmat != NULL) {
copy_m4_m4(call->obmat, obmat);
}
call->geometry_fn = geometry_fn;
call->user_data = user_data;
@ -2866,7 +2871,7 @@ void DRW_draw_render_loop(
if (cache_is_dirty) {
DRW_engines_cache_init();
DEG_OBJECT_ITER(graph, ob);
DEG_OBJECT_ITER(graph, ob, DEG_OBJECT_ITER_FLAG_ALL);
{
DRW_engines_cache_populate(ob);
/* XXX find a better place for this. maybe Depsgraph? */
@ -3029,7 +3034,7 @@ void DRW_draw_select_loop(
DRW_engines_cache_populate(scene->obedit);
}
else {
DEG_OBJECT_ITER(graph, ob)
DEG_OBJECT_ITER(graph, ob, DEG_OBJECT_ITER_FLAG_ALL)
{
if ((ob->base_flag & BASE_SELECTABLED) != 0) {
DRW_select_load_id(ob->base_selection_color);
@ -3116,7 +3121,7 @@ void DRW_draw_depth_loop(
DRW_engines_cache_init();
DEG_OBJECT_ITER(graph, ob)
DEG_OBJECT_ITER(graph, ob, DEG_OBJECT_ITER_FLAG_ALL)
{
DRW_engines_cache_populate(ob);
}

View File

@ -86,9 +86,13 @@ static void rna_Depsgraph_debug_stats(Depsgraph *graph, ReportList *reports)
static void rna_Depsgraph_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
Depsgraph *graph = (Depsgraph *)ptr->data;
iter->internal.custom = MEM_callocN(sizeof(BLI_Iterator), __func__);
DEG_objects_iterator_begin(iter->internal.custom, graph);
DEGObjectsIteratorData *data = MEM_callocN(sizeof(DEGObjectsIteratorData), __func__);
data->graph = (Depsgraph *)ptr->data;
data->flag = DEG_OBJECT_ITER_FLAG_ALL;
DEG_objects_iterator_begin(iter->internal.custom, data);
iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
}
@ -101,6 +105,7 @@ static void rna_Depsgraph_objects_next(CollectionPropertyIterator *iter)
static void rna_Depsgraph_objects_end(CollectionPropertyIterator *iter)
{
DEG_objects_iterator_end(iter->internal.custom);
MEM_freeN(((BLI_Iterator *)iter->internal.custom)->data);
MEM_freeN(iter->internal.custom);
}

View File

@ -3024,7 +3024,7 @@ static int rna_SceneLayer_multiple_engines_get(PointerRNA *UNUSED(ptr))
static void rna_SceneLayer_update_tagged(SceneLayer *UNUSED(sl), bContext *C)
{
Depsgraph *graph = CTX_data_depsgraph(C);
DEG_OBJECT_ITER(graph, ob)
DEG_OBJECT_ITER(graph, ob, DEG_OBJECT_ITER_FLAG_SET)
{
/* Don't do anything, we just need to run the iterator to flush
* the base info to the objects. */