diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 4ed9f00e51f..eaf257c0c73 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -236,19 +236,24 @@ void BlenderSync::sync_background_light(bool use_portal) /* Object */ -Object *BlenderSync::sync_object(BL::Object& b_parent, - int persistent_id[OBJECT_PERSISTENT_ID_SIZE], - BL::DupliObject& b_dupli_ob, - Transform& tfm, +Object *BlenderSync::sync_object(BL::Depsgraph::duplis_iterator& b_dupli_iter, uint layer_flag, float motion_time, bool hide_tris, BlenderObjectCulling& culling, bool *use_portal) { - BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent); - bool motion = motion_time != 0.0f; - + BL::Object b_ob = b_dupli_iter->object(); + BL::Object b_parent = b_dupli_iter->parent() ? b_dupli_iter->parent() : b_dupli_iter->object(); + const bool motion = motion_time != 0.0f; + /*const*/ Transform tfm = get_transform(b_ob.matrix_world()); + int *persistent_id = NULL; + BL::Array persistent_id_array; + if(b_dupli_iter->parent()) { + persistent_id_array = b_dupli_iter->persistent_id(); + persistent_id = persistent_id_array.data; + } + /* light is handled separately */ if(object_is_light(b_ob)) { /* don't use lamps for excluded layers used as mask layer */ @@ -380,10 +385,10 @@ Object *BlenderSync::sync_object(BL::Object& b_parent, } /* dupli texture coordinates and random_id */ - if(b_dupli_ob) { - object->dupli_generated = 0.5f*get_float3(b_dupli_ob.orco()) - make_float3(0.5f, 0.5f, 0.5f); - object->dupli_uv = get_float2(b_dupli_ob.uv()); - object->random_id = b_dupli_ob.random_id(); + if(b_dupli_iter->parent()) { + object->dupli_generated = 0.5f*get_float3(b_dupli_iter->orco()) - make_float3(0.5f, 0.5f, 0.5f); + object->dupli_uv = get_float2(b_dupli_iter->uv()); + object->random_id = b_dupli_iter->random_id(); } else { object->dupli_generated = make_float3(0.0f, 0.0f, 0.0f); @@ -495,10 +500,12 @@ void BlenderSync::sync_objects(float motion_time) bool cancel = false; bool use_portal = false; - BL::Depsgraph::objects_iterator b_ob_iter; - - for(b_depsgraph.objects.begin(b_ob_iter); b_ob_iter != b_depsgraph.objects.end() && !cancel; ++b_ob_iter) { - BL::Object b_ob = *b_ob_iter; + BL::Depsgraph::duplis_iterator b_dupli_iter; + for(b_depsgraph.duplis.begin(b_dupli_iter); + b_dupli_iter != b_depsgraph.duplis.end() && !cancel; + ++b_dupli_iter) + { + BL::Object b_ob = b_dupli_iter->object(); progress.set_sync_status("Synchronizing object", b_ob.name()); /* load per-object culling data */ @@ -509,12 +516,7 @@ void BlenderSync::sync_objects(float motion_time) if(!object_render_hide(b_ob, true, true, hide_tris)) { /* object itself */ - Transform tfm = get_transform(b_ob.matrix_world()); - BL::DupliObject b_empty_dupli_ob(PointerRNA_NULL); - sync_object(b_ob, - NULL, - b_empty_dupli_ob, - tfm, + sync_object(b_dupli_iter, ~(0), /* until we get rid of layers */ motion_time, hide_tris, diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index e509cce3e31..4c8772d4d8f 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -121,10 +121,7 @@ private: BL::Object& b_ob, bool motion, int time_index = 0); - Object *sync_object(BL::Object& b_parent, - int persistent_id[OBJECT_PERSISTENT_ID_SIZE], - BL::DupliObject& b_dupli_ob, - Transform& tfm, + Object *sync_object(BL::Depsgraph::duplis_iterator& b_dupli_iter, uint layer_flag, float motion_time, bool hide_tris, diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h index ff2126992c4..888730552e9 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.h +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -75,14 +75,27 @@ typedef struct DEGObjectsIteratorData { struct Depsgraph *graph; struct Scene *scene; struct EvaluationContext *eval_ctx; - struct SceneLayer *scene_layer; + + /* TODO(sergey): Base should never be a thing coming FROM depsgraph. */ struct Base *base; int base_flag; int flag; - /* Dupli */ + /* **** Iteration over dupli-list. *** */ + + /* Object which created the dupli-list. */ + struct Object *dupli_parent; + /* List of duplicated objects. */ struct ListBase *dupli_list; - struct DupliObject *dupli_object; + /* Next duplicated object to step into. */ + struct DupliObject *dupli_object_next; + /* Corresponds to current object: current iterator object is evaluated from + * this duplicated object. + */ + struct DupliObject *dupli_object_current; + /* Temporary storage to report fully populated DNA to the render engine or + * other users of the iterator. + */ struct Object temp_dupli_object; } DEGObjectsIteratorData; diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc index d889dccfede..0661f24fb7b 100644 --- a/source/blender/depsgraph/intern/depsgraph_query.cc +++ b/source/blender/depsgraph/intern/depsgraph_query.cc @@ -104,27 +104,34 @@ Object *DEG_get_object(Depsgraph * /*depsgraph*/, Object *ob) void DEG_objects_iterator_begin(BLI_Iterator *iter, DEGObjectsIteratorData *data) { - SceneLayer *scene_layer; Depsgraph *graph = data->graph; + SceneLayer *scene_layer = DEG_get_scene_layer(graph); iter->data = data; iter->valid = true; - /* 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->base_flag = ~BASE_FLUSH_FLAGS; + /* TODO(sergey): Make it in-place initilization of evaluation context. */ + data->eval_ctx = DEG_evaluation_context_new(DAG_EVAL_RENDER); + /* TODO(sergey): It's really confusing to store pointer to a local data. */ Base base = {(Base *)scene_layer->object_bases.first, NULL}; data->base = &base; + + data->base_flag = ~(BASE_FLUSH_FLAGS); + + data->dupli_parent = NULL; + data->dupli_list = NULL; + data->dupli_object_next = NULL; + data->dupli_object_current = NULL; + 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) +static void deg_flush_base_flags_and_settings(Object *ob, Base *base, const int flag) { ob->base_flag = (base->flag | BASE_FLUSH_FLAGS) & flag; ob->base_collection_properties = base->collection_properties; @@ -134,13 +141,15 @@ static void deg_flush_data(Object *ob, Base *base, const int flag) static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter) { DEGObjectsIteratorData *data = (DEGObjectsIteratorData *)iter->data; - while (data->dupli_object) { - DupliObject *dob = data->dupli_object; + while (data->dupli_object_next != NULL) { + DupliObject *dob = data->dupli_object_next; Object *obd = dob->ob; - data->dupli_object = data->dupli_object->next; + data->dupli_object_next = data->dupli_object_next->next; - /* Group duplis need to set ob matrices correct, for deform. so no_draw is part handled. */ + /* 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; } @@ -149,11 +158,15 @@ static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter) continue; } + data->dupli_object_current = dob; + /* 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); + deg_flush_base_flags_and_settings(&data->temp_dupli_object, + data->base, + data->base_flag | BASE_FROMDUPLI); iter->current = &data->temp_dupli_object; return true; } @@ -172,14 +185,15 @@ void DEG_objects_iterator_next(BLI_Iterator *iter) } else { free_object_duplilist(data->dupli_list); + data->dupli_parent = NULL; data->dupli_list = NULL; - data->dupli_object = NULL; + data->dupli_object_next = NULL; + data->dupli_object_current = NULL; } } base = data->base->next; - - while (base) { + while (base != NULL) { if ((base->flag & BASE_VISIBLED) != 0) { Object *ob = DEG_get_object(data->graph, base->object); iter->current = ob; @@ -191,15 +205,17 @@ void DEG_objects_iterator_next(BLI_Iterator *iter) BLI_assert(!BLI_listbase_is_empty(&base->collection_properties->data.group)); /* Flushing depsgraph data. */ - deg_flush_data(ob, base, data->base_flag); + deg_flush_base_flags_and_settings(ob, + base, + data->base_flag); if ((data->flag & DEG_OBJECT_ITER_FLAG_DUPLI) && (ob->transflag & OB_DUPLI)) { + data->dupli_parent = ob; data->dupli_list = object_duplilist(data->eval_ctx, data->scene, ob); - data->dupli_object = (DupliObject *)data->dupli_list->first; + data->dupli_object_next = (DupliObject *)data->dupli_list->first; } return; } - base = base->next; } @@ -212,6 +228,7 @@ void DEG_objects_iterator_next(BLI_Iterator *iter) /* For the sets we use the layer used for rendering. */ scene_layer = BKE_scene_layer_render_active(data->scene); + /* TODO(sergey): It's really confusing to store pointer to a local data. */ Base base = {(Base *)scene_layer->object_bases.first, NULL}; data->base = &base; DEG_objects_iterator_next(iter); diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 2982c459169..b11cc7134c4 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -202,6 +202,8 @@ extern StructRNA RNA_CurveMapPoint; extern StructRNA RNA_CurveMapping; extern StructRNA RNA_CurveModifier; extern StructRNA RNA_CurvePoint; +extern StructRNA RNA_Depsgraph; +extern StructRNA RNA_DepsgraphIter; extern StructRNA RNA_DampedTrackConstraint; extern StructRNA RNA_DataTransferModifier; extern StructRNA RNA_DecimateModifier; diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index bac221f96ab..babca789361 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -3321,7 +3321,6 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_context.c", NULL, RNA_def_context}, {"rna_controller.c", "rna_controller_api.c", RNA_def_controller}, {"rna_curve.c", "rna_curve_api.c", RNA_def_curve}, - {"rna_depsgraph.c", NULL, RNA_def_depsgraph}, {"rna_dynamicpaint.c", NULL, RNA_def_dynamic_paint}, {"rna_fcurve.c", "rna_fcurve_api.c", RNA_def_fcurve}, {"rna_fluidsim.c", NULL, RNA_def_fluidsim}, @@ -3341,6 +3340,7 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_nodetree.c", NULL, RNA_def_nodetree}, {"rna_object.c", "rna_object_api.c", RNA_def_object}, {"rna_object_force.c", NULL, RNA_def_object_force}, + {"rna_depsgraph.c", NULL, RNA_def_depsgraph}, {"rna_packedfile.c", NULL, RNA_def_packedfile}, {"rna_palette.c", NULL, RNA_def_palette}, {"rna_particle.c", NULL, RNA_def_particle}, diff --git a/source/blender/makesrna/intern/rna_depsgraph.c b/source/blender/makesrna/intern/rna_depsgraph.c index 82f8c454b53..c1f84b44447 100644 --- a/source/blender/makesrna/intern/rna_depsgraph.c +++ b/source/blender/makesrna/intern/rna_depsgraph.c @@ -38,6 +38,8 @@ #include "BKE_depsgraph.h" +#include "DNA_object_types.h" + #ifdef RNA_RUNTIME #include "BLI_iterator.h" @@ -49,6 +51,58 @@ #include "MEM_guardedalloc.h" +/* **************** Depsgraph **************** */ + +static PointerRNA rna_DepsgraphIter_object_get(PointerRNA *ptr) +{ + BLI_Iterator *iterator = ptr->data; + return rna_pointer_inherit_refine(ptr, &RNA_Object, iterator->current); +} + +static PointerRNA rna_DepsgraphIter_parent_get(PointerRNA *ptr) +{ + BLI_Iterator *iterator = ptr->data; + DEGObjectsIteratorData *deg_iter = (DEGObjectsIteratorData *)iterator->data; + Object *dupli_parent = NULL; + if (deg_iter->dupli_object_current != NULL) { + dupli_parent = deg_iter->dupli_parent; + } + return rna_pointer_inherit_refine(ptr, &RNA_Object, dupli_parent); +} + +static void rna_DepsgraphIter_persistent_id_get(PointerRNA *ptr, int *persistent_id) +{ + BLI_Iterator *iterator = ptr->data; + DEGObjectsIteratorData *deg_iter = (DEGObjectsIteratorData *)iterator->data; + memcpy(persistent_id, deg_iter->dupli_object_current->persistent_id, + sizeof(deg_iter->dupli_object_current->persistent_id)); +} + +static void rna_DepsgraphIter_orco_get(PointerRNA *ptr, float *orco) +{ + BLI_Iterator *iterator = ptr->data; + DEGObjectsIteratorData *deg_iter = (DEGObjectsIteratorData *)iterator->data; + memcpy(orco, deg_iter->dupli_object_current->orco, + sizeof(deg_iter->dupli_object_current->orco)); +} + +static unsigned int rna_DepsgraphIter_random_id_get(PointerRNA *ptr) +{ + BLI_Iterator *iterator = ptr->data; + DEGObjectsIteratorData *deg_iter = (DEGObjectsIteratorData *)iterator->data; + return deg_iter->dupli_object_current->random_id; +} + +static void rna_DepsgraphIter_uv_get(PointerRNA *ptr, float *uv) +{ + BLI_Iterator *iterator = ptr->data; + DEGObjectsIteratorData *deg_iter = (DEGObjectsIteratorData *)iterator->data; + memcpy(uv, deg_iter->dupli_object_current->uv, + sizeof(deg_iter->dupli_object_current->uv)); +} + +/* **************** Depsgraph **************** */ + static void rna_Depsgraph_debug_graphviz(Depsgraph *graph, const char *filename) { FILE *f = fopen(filename, "w"); @@ -84,6 +138,8 @@ static void rna_Depsgraph_debug_stats(Depsgraph *graph, ReportList *reports) ops, rels, outer); } +/* Iteration over objects, simple version */ + static void rna_Depsgraph_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { iter->internal.custom = MEM_callocN(sizeof(BLI_Iterator), __func__); @@ -115,8 +171,93 @@ static PointerRNA rna_Depsgraph_objects_get(CollectionPropertyIterator *iter) return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ob); } +/* Iteration over objects, extended version + * + * Contains extra information about duplicator and persistent ID. + */ + +static void rna_Depsgraph_duplis_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) +{ + iter->internal.custom = MEM_callocN(sizeof(BLI_Iterator), __func__); + 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; +} + +static void rna_Depsgraph_duplis_next(CollectionPropertyIterator *iter) +{ + DEG_objects_iterator_next(iter->internal.custom); + iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid; +} + +static void rna_Depsgraph_duplis_end(CollectionPropertyIterator *iter) +{ + DEG_objects_iterator_end(iter->internal.custom); + MEM_freeN(((BLI_Iterator *)iter->internal.custom)->data); + MEM_freeN(iter->internal.custom); +} + +static PointerRNA rna_Depsgraph_duplis_get(CollectionPropertyIterator *iter) +{ + BLI_Iterator *iterator = (BLI_Iterator *)iter->internal.custom; + return rna_pointer_inherit_refine(&iter->parent, &RNA_DepsgraphIter, iterator); +} + #else +static void rna_def_depsgraph_iter(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "DepsgraphIter", NULL); + RNA_def_struct_ui_text(srna, "Dependency Graph Iterator", + "Extended information about dependency graph object iterator"); + + prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_ui_text(prop, "Object", "Object the iterator points to"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_pointer_funcs(prop, "rna_DepsgraphIter_object_get", NULL, NULL, NULL); + + prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_ui_text(prop, "Parent", "Parent of the duplication list"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_pointer_funcs(prop, "rna_DepsgraphIter_parent_get", NULL, NULL, NULL); + + prop = RNA_def_property(srna, "persistent_id", PROP_INT, PROP_NONE); + RNA_def_property_ui_text(prop, "Persistent ID", + "Persistent identifier for inter-frame matching of objects with motion blur"); + RNA_def_property_array(prop, 2*MAX_DUPLI_RECUR); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_int_funcs(prop, "rna_DepsgraphIter_persistent_id_get", NULL, NULL); + + prop = RNA_def_property(srna, "orco", PROP_FLOAT, PROP_TRANSLATION); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + /* Seems system is not smart enough to figure that getter function should return + * array for PROP_TRANSLATION. + */ + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Generated Coordinates", "Generated coordinates in parent object space"); + RNA_def_property_float_funcs(prop, "rna_DepsgraphIter_orco_get", NULL, NULL); + + prop = RNA_def_property(srna, "random_id", PROP_INT, PROP_UNSIGNED); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Dupli random id", "Random id for this dupli object"); + RNA_def_property_int_funcs(prop, "rna_DepsgraphIter_random_id_get", NULL, NULL); + + prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "UV Coordinates", "UV coordinates in parent object space"); + RNA_def_property_array(prop, 2); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_float_funcs(prop, "rna_DepsgraphIter_uv_get", NULL, NULL); +} + static void rna_def_depsgraph(BlenderRNA *brna) { StructRNA *srna; @@ -141,13 +282,27 @@ static void rna_def_depsgraph(BlenderRNA *brna) prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); RNA_def_property_struct_type(prop, "Object"); - RNA_def_property_collection_funcs(prop, "rna_Depsgraph_objects_begin", "rna_Depsgraph_objects_next", - "rna_Depsgraph_objects_end", "rna_Depsgraph_objects_get", + RNA_def_property_collection_funcs(prop, + "rna_Depsgraph_objects_begin", + "rna_Depsgraph_objects_next", + "rna_Depsgraph_objects_end", + "rna_Depsgraph_objects_get", + NULL, NULL, NULL, NULL); + + /* TODO(sergey): Find a better name. */ + prop = RNA_def_property(srna, "duplis", PROP_COLLECTION, PROP_NONE); + RNA_def_property_struct_type(prop, "DepsgraphIter"); + RNA_def_property_collection_funcs(prop, + "rna_Depsgraph_duplis_begin", + "rna_Depsgraph_duplis_next", + "rna_Depsgraph_duplis_end", + "rna_Depsgraph_duplis_get", NULL, NULL, NULL, NULL); } void RNA_def_depsgraph(BlenderRNA *brna) { + rna_def_depsgraph_iter(brna); rna_def_depsgraph(brna); }