From 5116b7a4c222c6f80da00afa05925a36476d4d44 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 29 Jul 2021 12:06:07 +0200 Subject: Fix Cycles crash with fluid object motion blur disabled Motion attributes expects mesh to have non-zero number of motion steps, which was violated in the case when fluid mesh had motion blur disabled. This is a bit of annoying fix, because of the order of updates. More ideal solution would be to handle cached and fluid velocities in the sync_mesh_motion() which ensures all the dependencies between settings. --- intern/cycles/blender/blender_mesh.cpp | 41 ++++++++++++++++++++++++++++++++-- intern/cycles/render/attribute.cpp | 3 +++ 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'intern') diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 11158532738..c3c6c623144 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -1055,10 +1055,45 @@ static BL::MeshSequenceCacheModifier object_mesh_cache_find(BL::Object &b_ob) 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). + * + * NOTE: This code is run prior to object motion blur initialization. so can not access properties + * set by `sync_object_motion_init()`. */ +static bool mesh_need_motion_attribute(BL::Object &b_ob, Scene *scene) +{ + const Scene::MotionType need_motion = scene->need_motion(); + if (need_motion == Scene::MOTION_NONE) { + /* Simple case: neither motion pass nor motion blur is needed, no need in the motion related + * attributes. */ + return false; + } + + if (need_motion == Scene::MOTION_BLUR) { + /* A bit tricky and implicit case: + * - Motion blur is enabled in the scene, which implies specific number of time steps for + * objects. + * - If the object has motion blur disabled on it, it will have 0 time steps. + * - Motion attribute expects non-zero time steps. + * + * Avoid adding motion attributes if the motion blur will enforce 0 motion steps. */ + PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles"); + const bool use_motion = get_boolean(cobject, "use_motion_blur"); + if (!use_motion) { + return false; + } + } + + /* Motion pass which implies 3 motion steps, or motion blur which is not disabled on object + * level. */ + return true; +} + static void sync_mesh_cached_velocities(BL::Object &b_ob, Scene *scene, Mesh *mesh) { - if (scene->need_motion() == Scene::MOTION_NONE) + if (!mesh_need_motion_attribute(b_ob, scene)) { return; + } BL::MeshSequenceCacheModifier b_mesh_cache = object_mesh_cache_find(b_ob); @@ -1102,8 +1137,10 @@ static void sync_mesh_cached_velocities(BL::Object &b_ob, Scene *scene, Mesh *me static void sync_mesh_fluid_motion(BL::Object &b_ob, Scene *scene, Mesh *mesh) { - if (scene->need_motion() == Scene::MOTION_NONE) + LOG(INFO) << b_ob.name(); + if (!mesh_need_motion_attribute(b_ob, scene)) { return; + } BL::FluidDomainSettings b_fluid_domain = object_fluid_liquid_domain_find(b_ob); diff --git a/intern/cycles/render/attribute.cpp b/intern/cycles/render/attribute.cpp index bf9d69cb47e..ea5a5f50f2d 100644 --- a/intern/cycles/render/attribute.cpp +++ b/intern/cycles/render/attribute.cpp @@ -20,6 +20,7 @@ #include "render/mesh.h" #include "util/util_foreach.h" +#include "util/util_logging.h" #include "util/util_transform.h" CCL_NAMESPACE_BEGIN @@ -208,6 +209,7 @@ size_t Attribute::element_size(Geometry *geom, AttributePrimitive prim) const case ATTR_ELEMENT_VERTEX_MOTION: if (geom->geometry_type == Geometry::MESH) { Mesh *mesh = static_cast(geom); + DCHECK_GT(mesh->get_motion_steps(), 0); size = (mesh->get_verts().size() + mesh->get_num_ngons()) * (mesh->get_motion_steps() - 1); if (prim == ATTR_PRIM_SUBD) { size -= mesh->get_num_subd_verts() * (mesh->get_motion_steps() - 1); @@ -252,6 +254,7 @@ size_t Attribute::element_size(Geometry *geom, AttributePrimitive prim) const case ATTR_ELEMENT_CURVE_KEY_MOTION: if (geom->geometry_type == Geometry::HAIR) { Hair *hair = static_cast(geom); + DCHECK_GT(hair->get_motion_steps(), 0); size = hair->get_curve_keys().size() * (hair->get_motion_steps() - 1); } break; -- cgit v1.2.3