diff options
43 files changed, 417 insertions, 56 deletions
diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index 2d48563d8a6..ee5c6157338 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -115,6 +115,16 @@ if(WITH_OPENVDB) ) endif() +if(WITH_ALEMBIC) + add_definitions(-DWITH_ALEMBIC) + list(APPEND INC_SYS + ${ALEMBIC_INCLUDE_DIRS} + ) + list(APPEND LIB + ${ALEMBIC_LIBRARIES} + ) +endif() + if(WITH_OPENIMAGEDENOISE) add_definitions(-DWITH_OPENIMAGEDENOISE) list(APPEND INC_SYS diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 10b95133912..f728050a3cf 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -61,6 +61,7 @@ class CyclesRender(bpy.types.RenderEngine): bl_use_save_buffers = True bl_use_spherical_stereo = True bl_use_custom_freestyle = True + bl_use_alembic_procedural = True def __init__(self): self.session = None diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 124223635d1..ac0aca57028 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -227,6 +227,11 @@ def update_render_passes(self, context): view_layer.update_render_passes() +def update_render_engine(self, context): + scene = context.scene + scene.update_render_engine() + + class CyclesRenderSettings(bpy.types.PropertyGroup): device: EnumProperty( @@ -240,6 +245,7 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): description="Feature set to use for rendering", items=enum_feature_set, default='SUPPORTED', + update=update_render_engine, ) shading_system: BoolProperty( name="Open Shading Language", diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index ecadc78cbbf..d1042277183 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -1038,23 +1038,6 @@ static void create_subd_mesh(Scene *scene, /* Sync */ -static BL::MeshSequenceCacheModifier object_mesh_cache_find(BL::Object &b_ob) -{ - if (b_ob.modifiers.length() > 0) { - BL::Modifier b_mod = b_ob.modifiers[b_ob.modifiers.length() - 1]; - - if (b_mod.type() == BL::Modifier::type_MESH_SEQUENCE_CACHE) { - BL::MeshSequenceCacheModifier mesh_cache = BL::MeshSequenceCacheModifier(b_mod); - - if (MeshSequenceCacheModifier_has_velocity_get(&mesh_cache.ptr)) { - return mesh_cache; - } - } - } - - return BL::MeshSequenceCacheModifier(PointerRNA_NULL); -} - /* Check whether some of "built-in" motion-related attributes are needed to be exported (includes * things like velocity from cache modifier, fluid simulation). * @@ -1095,7 +1078,7 @@ static void sync_mesh_cached_velocities(BL::Object &b_ob, Scene *scene, Mesh *me return; } - BL::MeshSequenceCacheModifier b_mesh_cache = object_mesh_cache_find(b_ob); + BL::MeshSequenceCacheModifier b_mesh_cache = object_mesh_cache_find(b_ob, true); if (!b_mesh_cache) { return; @@ -1258,7 +1241,7 @@ void BlenderSync::sync_mesh_motion(BL::Depsgraph b_depsgraph, } /* Cached motion blur already exported. */ - BL::MeshSequenceCacheModifier mesh_cache = object_mesh_cache_find(b_ob); + BL::MeshSequenceCacheModifier mesh_cache = object_mesh_cache_find(b_ob, true); if (mesh_cache) { return; } diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 4711e0cbe76..657ecdeeeb7 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include "render/alembic.h" #include "render/camera.h" #include "render/graph.h" #include "render/integrator.h" @@ -484,6 +485,64 @@ bool BlenderSync::sync_object_attributes(BL::DepsgraphObjectInstance &b_instance /* Object Loop */ +void BlenderSync::sync_procedural(BL::Object &b_ob, BL::MeshSequenceCacheModifier &b_mesh_cache) +{ +#ifdef WITH_ALEMBIC + BL::CacheFile cache_file = b_mesh_cache.cache_file(); + void *cache_file_key = cache_file.ptr.data; + + AlembicProcedural *procedural = static_cast<AlembicProcedural *>( + procedural_map.find(cache_file_key)); + + if (procedural == nullptr) { + procedural = scene->create_node<AlembicProcedural>(); + procedural_map.add(cache_file_key, procedural); + } + else { + procedural_map.used(procedural); + } + + float current_frame = b_scene.frame_current(); + if (cache_file.override_frame()) { + current_frame = cache_file.frame(); + } + + if (!cache_file.override_frame()) { + procedural->set_start_frame(b_scene.frame_start()); + procedural->set_end_frame(b_scene.frame_end()); + } + + procedural->set_frame(current_frame); + procedural->set_frame_rate(b_scene.render().fps() / b_scene.render().fps_base()); + procedural->set_frame_offset(cache_file.frame_offset()); + + string absolute_path = blender_absolute_path(b_data, b_ob, b_mesh_cache.cache_file().filepath()); + procedural->set_filepath(ustring(absolute_path)); + + procedural->set_scale(cache_file.scale()); + + /* create or update existing AlembicObjects */ + ustring object_path = ustring(b_mesh_cache.object_path()); + + AlembicObject *abc_object = procedural->get_or_create_object(object_path); + + array<Node *> used_shaders = find_used_shaders(b_ob); + abc_object->set_used_shaders(used_shaders); + + PointerRNA cobj = RNA_pointer_get(&b_ob.ptr, "cycles"); + const float subd_dicing_rate = max(0.1f, RNA_float_get(&cobj, "dicing_rate") * dicing_rate); + abc_object->set_subd_dicing_rate(subd_dicing_rate); + abc_object->set_subd_max_level(max_subdivisions); + + if (abc_object->is_modified() || procedural->is_modified()) { + procedural->tag_update(scene); + } +#else + (void)b_ob; + (void)b_mesh_cache; +#endif +} + void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, float motion_time) @@ -499,6 +558,7 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, light_map.pre_sync(); geometry_map.pre_sync(); object_map.pre_sync(); + procedural_map.pre_sync(); particle_system_map.pre_sync(); motion_times.clear(); } @@ -539,15 +599,38 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, /* Object itself. */ if (b_instance.show_self()) { - sync_object(b_depsgraph, - b_view_layer, - b_instance, - motion_time, - false, - show_lights, - culling, - &use_portal, - sync_hair ? NULL : &geom_task_pool); +#ifdef WITH_ALEMBIC + bool use_procedural = false; + BL::MeshSequenceCacheModifier b_mesh_cache(PointerRNA_NULL); + + /* Experimental as Blender does not have good support for procedurals at the moment, also + * only available in preview renders since currently do not have a good cache policy, the + * data being loaded at once for all the frames. */ + if (experimental && b_v3d) { + b_mesh_cache = object_mesh_cache_find(b_ob, false); + use_procedural = b_mesh_cache && b_mesh_cache.cache_file().use_render_procedural(); + } + + if (use_procedural) { + /* Skip in the motion case, as generating motion blur data will be handled in the + * procedural. */ + if (!motion) { + sync_procedural(b_ob, b_mesh_cache); + } + } + else +#endif + { + sync_object(b_depsgraph, + b_view_layer, + b_instance, + motion_time, + false, + show_lights, + culling, + &use_portal, + sync_hair ? NULL : &geom_task_pool); + } } /* Particle hair as separate object. */ @@ -580,6 +663,7 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph, object_map.post_sync(); geometry_map.post_sync(); particle_system_map.post_sync(); + procedural_map.post_sync(); } if (motion) diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 298353203ad..26d64b7bf85 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -59,6 +59,7 @@ BlenderSync::BlenderSync(BL::RenderEngine &b_engine, b_scene(b_scene), shader_map(scene), object_map(scene), + procedural_map(scene), geometry_map(scene), light_map(scene), particle_system_map(scene), diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 949482b1f9c..0e605fcbf16 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -151,6 +151,8 @@ class BlenderSync { TaskPool *geom_task_pool); void sync_object_motion_init(BL::Object &b_parent, BL::Object &b_ob, Object *object); + void sync_procedural(BL::Object &b_ob, BL::MeshSequenceCacheModifier &b_mesh_cache); + bool sync_object_attributes(BL::DepsgraphObjectInstance &b_instance, Object *object); /* Volume */ @@ -221,6 +223,7 @@ class BlenderSync { id_map<void *, Shader> shader_map; id_map<ObjectKey, Object> object_map; + id_map<void *, Procedural> procedural_map; id_map<GeometryKey, Geometry> geometry_map; id_map<ObjectKey, Light> light_map; id_map<ParticleSystemKey, ParticleSystem> particle_system_map; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index d441575e8af..e50b1a4760e 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -572,6 +572,35 @@ static inline BL::FluidDomainSettings object_fluid_gas_domain_find(BL::Object &b return BL::FluidDomainSettings(PointerRNA_NULL); } +static inline BL::MeshSequenceCacheModifier object_mesh_cache_find(BL::Object &b_ob, + bool check_velocity) +{ + for (int i = b_ob.modifiers.length() - 1; i >= 0; --i) { + BL::Modifier b_mod = b_ob.modifiers[i]; + + if (b_mod.type() == BL::Modifier::type_MESH_SEQUENCE_CACHE) { + BL::MeshSequenceCacheModifier mesh_cache = BL::MeshSequenceCacheModifier(b_mod); + + if (check_velocity) { + if (!MeshSequenceCacheModifier_has_velocity_get(&mesh_cache.ptr)) { + return BL::MeshSequenceCacheModifier(PointerRNA_NULL); + } + } + + return mesh_cache; + } + + /* Skip possible particles system modifiers as they do not modify the geometry. */ + if (b_mod.type() == BL::Modifier::type_PARTICLE_SYSTEM) { + continue; + } + + break; + } + + return BL::MeshSequenceCacheModifier(PointerRNA_NULL); +} + static inline Mesh::SubdivisionType object_subdivision_type(BL::Object &b_ob, bool preview, bool experimental) diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h index a6b2aa8540a..58d876b184b 100644 --- a/source/blender/blenkernel/BKE_cachefile.h +++ b/source/blender/blenkernel/BKE_cachefile.h @@ -32,6 +32,7 @@ struct CacheReader; struct Depsgraph; struct Main; struct Object; +struct Scene; void BKE_cachefiles_init(void); void BKE_cachefiles_exit(void); @@ -60,6 +61,15 @@ void BKE_cachefile_reader_open(struct CacheFile *cache_file, const char *object_path); void BKE_cachefile_reader_free(struct CacheFile *cache_file, struct CacheReader **reader); +/* Determine whether the CacheFile should use a render engine procedural. If so, data is not read + * from the file and bouding boxes are used to represent the objects in the Scene. Render engines + * will receive the bounding box as a placeholder but can instead load the data directly if they + * support it. + */ +bool BKE_cache_file_uses_render_procedural(const struct CacheFile *cache_file, + struct Scene *scene, + const int dag_eval_mode); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 0b4e1191956..c5f309570cd 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -319,8 +319,10 @@ typedef struct ModifierTypeInfo { * changes. * * This function is optional (assumes false if not present). + * + * The dag_eval_mode should be of type eEvaluationMode. */ - bool (*dependsOnTime)(struct ModifierData *md); + bool (*dependsOnTime)(struct Scene *scene, struct ModifierData *md, const int dag_eval_mode); /** * True when a deform modifier uses normals, the requiredDataMask @@ -425,7 +427,9 @@ void BKE_modifier_copydata(struct ModifierData *md, struct ModifierData *target) void BKE_modifier_copydata_ex(struct ModifierData *md, struct ModifierData *target, const int flag); -bool BKE_modifier_depends_ontime(struct ModifierData *md); +bool BKE_modifier_depends_ontime(struct Scene *scene, + struct ModifierData *md, + int dag_eval_mode); bool BKE_modifier_supports_mapping(struct ModifierData *md); bool BKE_modifier_supports_cage(struct Scene *scene, struct ModifierData *md); bool BKE_modifier_couldbe_cage(struct Scene *scene, struct ModifierData *md); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 4724e6dfab6..a823602e341 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -401,7 +401,10 @@ void BKE_object_groups_clear(struct Main *bmain, struct Scene *scene, struct Obj struct KDTree_3d *BKE_object_as_kdtree(struct Object *ob, int *r_tot); -bool BKE_object_modifier_use_time(struct Object *ob, struct ModifierData *md); +bool BKE_object_modifier_use_time(struct Scene *scene, + struct Object *ob, + struct ModifierData *md, + int dag_eval_mode); bool BKE_object_modifier_update_subframe(struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 6d58e165ea3..83ce5e72794 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -174,6 +174,10 @@ bool BKE_scene_uses_blender_eevee(const struct Scene *scene); bool BKE_scene_uses_blender_workbench(const struct Scene *scene); bool BKE_scene_uses_cycles(const struct Scene *scene); +/* Return whether the Cycles experimental feature is enabled. It is invalid to call without first + * ensuring that Cycles is the active render engine (e.g. with BKE_scene_uses_cycles). */ +bool BKE_scene_uses_cycles_experimental_features(struct Scene *scene); + void BKE_scene_copy_data_eevee(struct Scene *sce_dst, const struct Scene *sce_src); void BKE_scene_disable_color_management(struct Scene *scene); diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index 75180de94d8..8dd28c889f5 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -49,6 +49,8 @@ #include "DEG_depsgraph_query.h" +#include "RE_engine.h" + #include "BLO_read_write.h" #ifdef WITH_ALEMBIC @@ -409,3 +411,19 @@ float BKE_cachefile_time_offset(const CacheFile *cache_file, const float time, c const float frame = (cache_file->override_frame ? cache_file->frame : time); return cache_file->is_sequence ? frame : frame / fps - time_offset; } + +bool BKE_cache_file_uses_render_procedural(const CacheFile *cache_file, + Scene *scene, + const int dag_eval_mode) +{ + RenderEngineType *render_engine_type = RE_engines_find(scene->r.engine); + + if (cache_file->type != CACHEFILE_TYPE_ALEMBIC || + !RE_engine_supports_alembic_procedural(render_engine_type, scene)) { + return false; + } + + /* The render time procedural is only enabled during viewport rendering. */ + const bool is_final_render = (eEvaluationMode)dag_eval_mode == DAG_EVAL_RENDER; + return cache_file->use_render_procedural && !is_final_render; +} diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 4b26022039e..30aa22387d0 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -5430,6 +5430,11 @@ static void transformcache_evaluate(bConstraint *con, bConstraintOb *cob, ListBa return; } + /* Do not process data if using a render time procedural. */ + if (BKE_cache_file_uses_render_procedural(cache_file, scene, DEG_get_mode(cob->depsgraph))) { + return; + } + const float frame = DEG_get_ctime(cob->depsgraph); const float time = BKE_cachefile_time_offset(cache_file, frame, FPS); diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 2088c4268e6..821ca7b98b3 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -249,11 +249,11 @@ bool BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md) return false; } -bool BKE_modifier_depends_ontime(ModifierData *md) +bool BKE_modifier_depends_ontime(Scene *scene, ModifierData *md, const int dag_eval_mode) { const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - return mti->dependsOnTime && mti->dependsOnTime(md); + return mti->dependsOnTime && mti->dependsOnTime(scene, md, dag_eval_mode); } bool BKE_modifier_supports_mapping(ModifierData *md) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 23b9dca8371..86db4b6ace8 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -5411,9 +5411,12 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot) return tree; } -bool BKE_object_modifier_use_time(Object *ob, ModifierData *md) +bool BKE_object_modifier_use_time(Scene *scene, + Object *ob, + ModifierData *md, + const int dag_eval_mode) { - if (BKE_modifier_depends_ontime(md)) { + if (BKE_modifier_depends_ontime(scene, md, dag_eval_mode)) { return true; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 5ecd9b7283e..3fe00adc4d5 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -109,6 +109,8 @@ #include "RE_engine.h" +#include "RNA_access.h" + #include "SEQ_edit.h" #include "SEQ_iterator.h" #include "SEQ_modifier.h" @@ -2938,6 +2940,22 @@ bool BKE_scene_uses_cycles(const Scene *scene) return STREQ(scene->r.engine, RE_engine_id_CYCLES); } +/* This enumeration has to match the one defined in the Cycles addon. */ +typedef enum eCyclesFeatureSet { + CYCLES_FEATURES_SUPPORTED = 0, + CYCLES_FEATURES_EXPERIMENTAL = 1, +} eCyclesFeatureSet; + +/* We cannot use const as RNA_id_pointer_create is not using a const ID. */ +bool BKE_scene_uses_cycles_experimental_features(Scene *scene) +{ + BLI_assert(BKE_scene_uses_cycles(scene)); + PointerRNA scene_ptr; + RNA_id_pointer_create(&scene->id, &scene_ptr); + PointerRNA cycles_ptr = RNA_pointer_get(&scene_ptr, "cycles"); + return RNA_enum_get(&cycles_ptr, "feature_set") == CYCLES_FEATURES_EXPERIMENTAL; +} + void BKE_scene_base_flag_to_objects(ViewLayer *view_layer) { Base *base = view_layer->object_bases.first; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 7da3d2e25f0..d88e9bc9c04 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -118,6 +118,7 @@ #include "intern/node/deg_node_operation.h" #include "intern/node/deg_node_time.h" +#include "intern/depsgraph.h" #include "intern/depsgraph_relation.h" #include "intern/depsgraph_type.h" @@ -2095,7 +2096,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); mti->updateDepsgraph(md, &ctx); } - if (BKE_object_modifier_use_time(object, md)) { + if (BKE_object_modifier_use_time(scene_, object, md, graph_->mode)) { TimeSourceKey time_src_key; add_relation(time_src_key, obdata_ubereval_key, "Time Source"); } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 47ff0c9fd3c..f0d50985237 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -84,6 +84,8 @@ #include "ED_screen.h" #include "ED_undo.h" +#include "RE_engine.h" + #include "RNA_access.h" #include "WM_api.h" @@ -6463,6 +6465,29 @@ void uiTemplateCacheFile(uiLayout *layout, row = uiLayoutRow(layout, false); uiItemR(row, &fileptr, "is_sequence", 0, NULL, ICON_NONE); + /* Only enable render procedural option if the active engine supports it. */ + const struct RenderEngineType *engine_type = CTX_data_engine_type(C); + + Scene *scene = CTX_data_scene(C); + const bool engine_supports_procedural = RE_engine_supports_alembic_procedural(engine_type, scene); + + if (!engine_supports_procedural) { + row = uiLayoutRow(layout, false); + /* For Cycles, verify that experimental features are enabled. */ + if (BKE_scene_uses_cycles(scene) && !BKE_scene_uses_cycles_experimental_features(scene)) { + uiItemL(row, + "The Cycles Alembic Procedural is only available with the experimental feature set", + ICON_INFO); + } + else { + uiItemL(row, "The active render engine does not have an Alembic Procedural", ICON_INFO); + } + } + + row = uiLayoutRow(layout, false); + uiLayoutSetActive(row, engine_supports_procedural); + uiItemR(row, &fileptr, "use_render_procedural", 0, NULL, ICON_NONE); + row = uiLayoutRowWithHeading(layout, true, IFACE_("Override Frame")); sub = uiLayoutRow(row, true); uiLayoutSetPropDecorate(sub, false); diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index fb9d11feb63..6db148eb4e1 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -23,6 +23,7 @@ #include <stdlib.h> #include <string.h> +#include "DNA_cachefile_types.h" #include "DNA_light_types.h" #include "DNA_material_types.h" #include "DNA_node_types.h" @@ -204,6 +205,19 @@ void ED_render_engine_changed(Main *bmain, const bool update_scene_data) ntreeCompositUpdateRLayers(scene->nodetree); } } + + /* Update CacheFiles to ensure that procedurals are properly taken into account. */ + LISTBASE_FOREACH (CacheFile *, cachefile, &bmain->cachefiles) { + /* Only update cachefiles which are set to use a render procedural. We do not use + * BKE_cachefile_uses_render_procedural here as we need to update regardless of the current + * engine or its settings. */ + if (cachefile->use_render_procedural) { + DEG_id_tag_update(&cachefile->id, ID_RECALC_COPY_ON_WRITE); + /* Rebuild relations so that modifiers are reconnected to or disconnected from the cachefile. + */ + DEG_relations_tag_update(bmain); + } + } } void ED_render_view_layer_changed(Main *bmain, bScreen *screen) diff --git a/source/blender/makesdna/DNA_cachefile_types.h b/source/blender/makesdna/DNA_cachefile_types.h index b38c7827ea5..ae4ade49be1 100644 --- a/source/blender/makesdna/DNA_cachefile_types.h +++ b/source/blender/makesdna/DNA_cachefile_types.h @@ -87,14 +87,21 @@ typedef struct CacheFile { /** The frame offset to subtract. */ float frame_offset; + char _pad[4]; + /** Animation flag. */ short flag; - short draw_flag; /* UNUSED */ /* eCacheFileType enum. */ char type; - char _pad[2]; + /** Do not load data from the cache file and display objects in the scene as boxes, Cycles will + * load objects directly from the CacheFile. Other render engines which can load Alembic data + * directly can take care of rendering it themselves. + */ + char use_render_procedural; + + char _pad1[7]; char velocity_unit; /* Name of the velocity property in the archive. */ diff --git a/source/blender/makesrna/intern/rna_cachefile.c b/source/blender/makesrna/intern/rna_cachefile.c index b93f494072c..cb0a490417d 100644 --- a/source/blender/makesrna/intern/rna_cachefile.c +++ b/source/blender/makesrna/intern/rna_cachefile.c @@ -37,6 +37,7 @@ # include "BKE_cachefile.h" # include "DEG_depsgraph.h" +# include "DEG_depsgraph_build.h" # include "WM_api.h" # include "WM_types.h" @@ -53,6 +54,12 @@ static void rna_CacheFile_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Poin WM_main_add_notifier(NC_OBJECT | ND_DRAW, NULL); } +static void rna_CacheFile_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + rna_CacheFile_update(bmain, scene, ptr); + DEG_relations_tag_update(bmain); +} + static void rna_CacheFile_object_paths_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { CacheFile *cache_file = (CacheFile *)ptr->data; @@ -105,6 +112,16 @@ static void rna_def_cachefile(BlenderRNA *brna) prop, "Sequence", "Whether the cache is separated in a series of files"); RNA_def_property_update(prop, 0, "rna_CacheFile_update"); + prop = RNA_def_property(srna, "use_render_procedural", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_ui_text( + prop, + "Use Render Engine Procedural", + "Display boxes in the viewport as placeholders for the objects, Cycles will use a " + "procedural to load the objects during viewport rendering in experimental mode, " + "other render engines will also receive a placeholder and should take care of loading the " + "Alembic data themselves if possible"); + RNA_def_property_update(prop, 0, "rna_CacheFile_dependency_update"); + /* ----------------- For Scene time ------------------- */ prop = RNA_def_property(srna, "override_frame", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 73924c45d52..4400d198b4a 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -896,6 +896,12 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); RNA_def_property_ui_text(prop, "Use Stereo Viewport", "Support rendering stereo 3D viewport"); + prop = RNA_def_property(srna, "bl_use_alembic_procedural", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "type->flag", RE_USE_ALEMBIC_PROCEDURAL); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + RNA_def_property_ui_text( + prop, "Use Alembic Procedural", "Support loading Alembic data at render time"); + RNA_define_verify_sdna(1); } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index f0a1508fb5f..9d158761a21 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -616,6 +616,7 @@ const EnumPropertyItem rna_enum_transform_orientation_items[] = { # include "BLI_string_utils.h" # include "DNA_anim_types.h" +# include "DNA_cachefile_types.h" # include "DNA_color_types.h" # include "DNA_mesh_types.h" # include "DNA_node_types.h" @@ -1619,6 +1620,11 @@ static void rna_RenderSettings_engine_update(Main *bmain, ED_render_engine_changed(bmain, true); } +static void rna_Scene_update_render_engine(Main *bmain) +{ + ED_render_engine_changed(bmain, true); +} + static bool rna_RenderSettings_multiple_engines_get(PointerRNA *UNUSED(ptr)) { return (BLI_listbase_count(&R_engines) > 1); @@ -7836,6 +7842,10 @@ void RNA_def_scene(BlenderRNA *brna) RNA_def_property_update(prop, NC_SCENE, NULL); RNA_def_property_update(prop, NC_SCENE, "rna_Scene_volume_update"); + func = RNA_def_function(srna, "update_render_engine", "rna_Scene_update_render_engine"); + RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_MAIN); + RNA_def_function_ui_description(func, "Trigger a render engine update"); + /* Statistics */ func = RNA_def_function(srna, "statistics", "rna_Scene_statistics_string_get"); RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS); diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index 52f21e3d3d0..a344a15b0c1 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -61,7 +61,9 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(bmd, DNA_struct_default_get(BuildModifierData), modifier); } -static bool dependsOnTime(ModifierData *UNUSED(md)) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *UNUSED(md), + const int UNUSED(dag_eval_mode)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 4487adcfdda..fa2f70e1a9c 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -220,7 +220,9 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla tclmd->solver_result = NULL; } -static bool dependsOnTime(ModifierData *UNUSED(md)) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *UNUSED(md), + const int UNUSED(dag_eval_mode)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index 5dd57469914..e7d5fe056c5 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -95,7 +95,9 @@ static void freeData(ModifierData *md) } } -static bool dependsOnTime(ModifierData *UNUSED(md)) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *UNUSED(md), + const int UNUSED(dag_eval_mode)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index a7ac9f618af..07da18f990d 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -95,7 +95,9 @@ static void requiredDataMask(Object *UNUSED(ob), } } -static bool dependsOnTime(ModifierData *md) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *md, + const int UNUSED(dag_eval_mode)) { DisplaceModifierData *dmd = (DisplaceModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index 8b1d541d45d..77ae5c4b6f1 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -155,7 +155,9 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte } } -static bool dependsOnTime(ModifierData *UNUSED(md)) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *UNUSED(md), + const int UNUSED(dag_eval_mode)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index bf197dca7e5..493b59b3a1a 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -86,7 +86,9 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla temd->facepa = NULL; } -static bool dependsOnTime(ModifierData *UNUSED(md)) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *UNUSED(md), + const int UNUSED(dag_eval_mode)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c index 36d2ab2a11a..a14d582063a 100644 --- a/source/blender/modifiers/intern/MOD_fluid.c +++ b/source/blender/modifiers/intern/MOD_fluid.c @@ -132,7 +132,9 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * #endif /* WITH_FLUID */ } -static bool dependsOnTime(ModifierData *UNUSED(md)) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *UNUSED(md), + const int UNUSED(dag_eval_mode)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index e0507320628..6ef64ad8bc9 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -63,7 +63,9 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(mcmd, DNA_struct_default_get(MeshCacheModifierData), modifier); } -static bool dependsOnTime(ModifierData *md) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *md, + const int UNUSED(dag_eval_mode)) { MeshCacheModifierData *mcmd = (MeshCacheModifierData *)md; return (mcmd->play_mode == MOD_MESHCACHE_PLAY_CFEA); diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index 3e6081e0a18..2aa76c18c83 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -20,6 +20,7 @@ #include <string.h> +#include "BLI_math_vector.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -39,6 +40,8 @@ #include "BKE_cachefile.h" #include "BKE_context.h" #include "BKE_lib_query.h" +#include "BKE_mesh.h" +#include "BKE_object.h" #include "BKE_scene.h" #include "BKE_screen.h" @@ -118,6 +121,44 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return (mcmd->cache_file == NULL) || (mcmd->object_path[0] == '\0'); } +static Mesh *generate_bounding_box_mesh(Object *object, Mesh *org_mesh) +{ + BoundBox *bb = BKE_object_boundbox_get(object); + Mesh *result = BKE_mesh_new_nomain_from_template(org_mesh, 8, 0, 0, 24, 6); + + MVert *mvert = result->mvert; + for (int i = 0; i < 8; ++i) { + copy_v3_v3(mvert[i].co, bb->vec[i]); + } + + /* See DNA_object_types.h for the diagram showing the order of the vertices for a BoundBox. */ + static unsigned int loops_v[6][4] = { + {0, 4, 5, 1}, + {4, 7, 6, 5}, + {7, 3, 2, 6}, + {3, 0, 1, 2}, + {1, 5, 6, 2}, + {3, 7, 4, 0}, + }; + + MLoop *mloop = result->mloop; + for (int i = 0; i < 6; ++i) { + for (int j = 0; j < 4; ++j, ++mloop) { + mloop->v = loops_v[i][j]; + } + } + + MPoly *mpoly = result->mpoly; + for (int i = 0; i < 6; ++i) { + mpoly[i].loopstart = i * 4; + mpoly[i].totloop = 4; + } + + BKE_mesh_calc_edges(result, false, false); + + return result; +} + static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { #if defined(WITH_USD) || defined(WITH_ALEMBIC) @@ -143,6 +184,12 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * } } + /* Do not process data if using a render procedural, return a box instead for displaying in the + * viewport. */ + if (BKE_cache_file_uses_render_procedural(cache_file, scene, DEG_get_mode(ctx->depsgraph))) { + return generate_bounding_box_mesh(ctx->object, org_mesh); + } + /* If this invocation is for the ORCO mesh, and the mesh hasn't changed topology, we * must return the mesh as-is instead of deforming it. */ if (ctx->flag & MOD_APPLY_ORCO) { @@ -228,11 +275,13 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * #endif } -static bool dependsOnTime(ModifierData *md) +static bool dependsOnTime(Scene *scene, ModifierData *md, const int dag_eval_mode) { #if defined(WITH_USD) || defined(WITH_ALEMBIC) MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; - return (mcmd->cache_file != NULL); + /* Do not evaluate animations if using the render engine procedural. */ + return (mcmd->cache_file != NULL) && + !BKE_cache_file_uses_render_procedural(mcmd->cache_file, scene, dag_eval_mode); #else UNUSED_VARS(md); return false; diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c index d7d2f948955..4187f9087a0 100644 --- a/source/blender/modifiers/intern/MOD_softbody.c +++ b/source/blender/modifiers/intern/MOD_softbody.c @@ -62,7 +62,9 @@ static void deformVerts(ModifierData *UNUSED(md), ctx->depsgraph, scene, ctx->object, DEG_get_ctime(ctx->depsgraph), vertexCos, numVerts); } -static bool dependsOnTime(ModifierData *UNUSED(md)) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *UNUSED(md), + const int UNUSED(dag_eval_mode)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index bfd4cd81803..3f2d0a06db8 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -98,7 +98,9 @@ static void freeData(ModifierData *md) } } -static bool dependsOnTime(ModifierData *UNUSED(md)) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *UNUSED(md), + const int UNUSED(dag_eval_mode)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_volume_displace.cc b/source/blender/modifiers/intern/MOD_volume_displace.cc index af4b31d6bfc..dfd3fdd80f8 100644 --- a/source/blender/modifiers/intern/MOD_volume_displace.cc +++ b/source/blender/modifiers/intern/MOD_volume_displace.cc @@ -95,7 +95,7 @@ static void foreachTexLink(ModifierData *md, Object *ob, TexWalkFunc walk, void walk(userData, ob, md, "texture"); } -static bool dependsOnTime(ModifierData *md) +static bool dependsOnTime(struct Scene *UNUSED(scene), ModifierData *md, const int UNUSED(dag_eval_mode)) { VolumeDisplaceModifierData *vdmd = reinterpret_cast<VolumeDisplaceModifierData *>(md); if (vdmd->texture) { diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 3bebc52c503..25e33b22bde 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -116,7 +116,9 @@ static void matrix_from_obj_pchan(float mat[4][4], } } -static bool dependsOnTime(ModifierData *md) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *md, + const int UNUSED(dag_eval_mode)) { WarpModifierData *wmd = (WarpModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index cf4c195c66d..03f8e3a1dfb 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -70,7 +70,9 @@ static void initData(ModifierData *md) MEMCPY_STRUCT_AFTER(wmd, DNA_struct_default_get(WaveModifierData), modifier); } -static bool dependsOnTime(ModifierData *UNUSED(md)) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *UNUSED(md), + const int UNUSED(dag_eval_mode)) { return true; } diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index 093fa118ee0..a9d01c64ff1 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -112,7 +112,9 @@ static void requiredDataMask(Object *UNUSED(ob), /* No need to ask for CD_PREVIEW_MLOOPCOL... */ } -static bool dependsOnTime(ModifierData *md) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *md, + const int UNUSED(dag_eval_mode)) { WeightVGEditModifierData *wmd = (WeightVGEditModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index 7aae089fa18..b369b82ebb7 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -154,7 +154,9 @@ static void requiredDataMask(Object *UNUSED(ob), /* No need to ask for CD_PREVIEW_MLOOPCOL... */ } -static bool dependsOnTime(ModifierData *md) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *md, + const int UNUSED(dag_eval_mode)) { WeightVGMixModifierData *wmd = (WeightVGMixModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 6e78774269a..7ee19e1c537 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -362,7 +362,9 @@ static void requiredDataMask(Object *UNUSED(ob), /* No need to ask for CD_PREVIEW_MLOOPCOL... */ } -static bool dependsOnTime(ModifierData *md) +static bool dependsOnTime(struct Scene *UNUSED(scene), + ModifierData *md, + const int UNUSED(dag_eval_mode)) { WeightVGProximityModifierData *wmd = (WeightVGProximityModifierData *)md; diff --git a/source/blender/render/RE_engine.h b/source/blender/render/RE_engine.h index 6b2861bbefd..dfc0d5d0e9f 100644 --- a/source/blender/render/RE_engine.h +++ b/source/blender/render/RE_engine.h @@ -66,6 +66,7 @@ extern "C" { #define RE_USE_GPU_CONTEXT 512 #define RE_USE_CUSTOM_FREESTYLE 1024 #define RE_USE_NO_IMAGE_SAVE 2048 +#define RE_USE_ALEMBIC_PROCEDURAL 4096 /* RenderEngine.flag */ #define RE_ENGINE_ANIMATION 1 @@ -235,6 +236,12 @@ void RE_engines_register(RenderEngineType *render_type); bool RE_engine_is_opengl(RenderEngineType *render_type); +/** + * Return true if the RenderEngineType has native support for direct loading of Alembic data. For + * Cycles, this also checks that the experimental feature set is enabled. + */ +bool RE_engine_supports_alembic_procedural(const RenderEngineType *render_type, Scene *scene); + RenderEngineType *RE_engines_find(const char *idname); rcti *RE_engine_get_current_tiles(struct Render *re, int *r_total_tiles, bool *r_needs_free); diff --git a/source/blender/render/intern/engine.c b/source/blender/render/intern/engine.c index 657cd1f606b..75b3f2db249 100644 --- a/source/blender/render/intern/engine.c +++ b/source/blender/render/intern/engine.c @@ -128,6 +128,19 @@ bool RE_engine_is_opengl(RenderEngineType *render_type) return (render_type->draw_engine != NULL) && DRW_engine_render_support(render_type->draw_engine); } +bool RE_engine_supports_alembic_procedural(const RenderEngineType *render_type, Scene *scene) +{ + if ((render_type->flag & RE_USE_ALEMBIC_PROCEDURAL) == 0) { + return false; + } + + if (BKE_scene_uses_cycles(scene) && !BKE_scene_uses_cycles_experimental_features(scene)) { + return false; + } + + return true; +} + /* Create, Free */ RenderEngine *RE_engine_create(RenderEngineType *type) |