diff options
Diffstat (limited to 'source/blender/blenkernel/intern/DerivedMesh.cc')
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.cc | 99 |
1 files changed, 89 insertions, 10 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index 78d4ad6fe19..b8219dcf7ac 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -50,6 +50,7 @@ #include "BKE_colorband.h" #include "BKE_deform.h" #include "BKE_editmesh.h" +#include "BKE_geometry_set.hh" #include "BKE_key.h" #include "BKE_layer.h" #include "BKE_lib_id.h" @@ -881,6 +882,56 @@ void BKE_mesh_wrapper_deferred_finalize(Mesh *me_eval, BLI_assert(me_eval->runtime.wrapper_type_finalize == 0); } +/** + * Modifies the given mesh and geometry set. The geometry set is expect to have NO mesh component. + * After this function ends, the geometry set will still have NO mesh component. Instead, an input + * mesh is passed separately and is returned separately. + * + * The purpose of the geometry set is to store all non-mesh geometry components that are generated + * by modifiers. + */ +static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md, + const ModifierEvalContext &mectx, + Object *ob, + Mesh *input_mesh, + GeometrySet &geometry_set) +{ + Mesh *mesh_output = nullptr; + const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); + if (mti->modifyGeometrySet == nullptr) { + mesh_output = BKE_modifier_modify_mesh(md, &mectx, input_mesh); + } + else { + /* For performance reasons, this should be called by the modifier and/or nodes themselves at + * some point. */ + BKE_mesh_wrapper_ensure_mdata(input_mesh); + + /* Adds a new mesh component to the geometry set based on the #input_mesh. */ + BLI_assert(!geometry_set.has<MeshComponent>()); + MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); + mesh_component.replace(input_mesh, GeometryOwnershipType::Editable); + mesh_component.copy_vertex_group_names_from_object(*ob); + + /* Let the modifier change the geometry set. */ + mti->modifyGeometrySet(md, &mectx, &geometry_set); + + /* Release the mesh from the geometry set again. */ + if (geometry_set.has<MeshComponent>()) { + MeshComponent &mesh_component = geometry_set.get_component_for_write<MeshComponent>(); + mesh_output = mesh_component.release(); + geometry_set.remove<MeshComponent>(); + } + + /* Return an empty mesh instead of null. */ + if (mesh_output == nullptr) { + mesh_output = BKE_mesh_new_nomain(0, 0, 0, 0, 0); + BKE_mesh_copy_settings(mesh_output, input_mesh); + } + } + + return mesh_output; +} + static void mesh_calc_modifiers(struct Depsgraph *depsgraph, Scene *scene, Object *ob, @@ -892,7 +943,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, const bool allow_shared_mesh, /* return args */ Mesh **r_deform, - Mesh **r_final) + Mesh **r_final, + GeometrySet **r_geometry_set) { /* Input and final mesh. Final mesh is only created the moment the first * constructive modifier is executed, or a deform modifier needs normals @@ -900,6 +952,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, Mesh *mesh_input = (Mesh *)ob->data; Mesh *mesh_final = nullptr; Mesh *mesh_deform = nullptr; + /* This geometry set contains the non-mesh data that might be generated by modifiers. */ + GeometrySet geometry_set_final; BLI_assert((mesh_input->id.tag & LIB_TAG_COPIED_ON_WRITE_EVAL_RESULT) == 0); /* Deformed vertex locations array. Deform only modifier need this type of @@ -1197,7 +1251,8 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, } } - Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final); + Mesh *mesh_next = modifier_modify_mesh_and_geometry_set( + md, mectx, ob, mesh_final, geometry_set_final); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { @@ -1375,6 +1430,9 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, if (r_deform) { *r_deform = mesh_deform; } + if (r_geometry_set) { + *r_geometry_set = new GeometrySet(std::move(geometry_set_final)); + } } float (*editbmesh_vert_coords_alloc(BMEditMesh *em, int *r_vert_len))[3] @@ -1483,7 +1541,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, const CustomData_MeshMasks *dataMask, /* return args */ Mesh **r_cage, - Mesh **r_final) + Mesh **r_final, + GeometrySet **r_geometry_set) { /* Input and final mesh. Final mesh is only created the moment the first * constructive modifier is executed, or a deform modifier needs normals @@ -1491,6 +1550,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, Mesh *mesh_input = (Mesh *)ob->data; Mesh *mesh_final = nullptr; Mesh *mesh_cage = nullptr; + /* This geometry set contains the non-mesh data that might be generated by modifiers. */ + GeometrySet geometry_set_final; /* Deformed vertex locations array. Deform only modifier need this type of * float array rather than MVert*. Tracked along with mesh_final as an @@ -1655,7 +1716,8 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, } } - Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final); + Mesh *mesh_next = modifier_modify_mesh_and_geometry_set( + md, mectx, ob, mesh_final, geometry_set_final); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { @@ -1757,6 +1819,9 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, if (r_cage) { *r_cage = mesh_cage; } + if (r_geometry_set) { + *r_geometry_set = new GeometrySet(std::move(geometry_set_final)); + } } static void mesh_build_extra_data(struct Depsgraph *depsgraph, Object *ob, Mesh *mesh_eval) @@ -1803,6 +1868,7 @@ static void mesh_build_data(struct Depsgraph *depsgraph, #endif Mesh *mesh_eval = nullptr, *mesh_deform_eval = nullptr; + GeometrySet *geometry_set_eval = nullptr; mesh_calc_modifiers(depsgraph, scene, ob, @@ -1813,7 +1879,8 @@ static void mesh_build_data(struct Depsgraph *depsgraph, true, true, &mesh_deform_eval, - &mesh_eval); + &mesh_eval, + &geometry_set_eval); /* The modifier stack evaluation is storing result in mesh->runtime.mesh_eval, but this result * is not guaranteed to be owned by object. @@ -1825,6 +1892,12 @@ static void mesh_build_data(struct Depsgraph *depsgraph, const bool is_mesh_eval_owned = (mesh_eval != mesh->runtime.mesh_eval); BKE_object_eval_assign_data(ob, &mesh_eval->id, is_mesh_eval_owned); + /* Add the final mesh as read-only non-owning component to the geometry set. */ + BLI_assert(!geometry_set_eval->has<MeshComponent>()); + MeshComponent &mesh_component = geometry_set_eval->get_component_for_write<MeshComponent>(); + mesh_component.replace(mesh_eval, GeometryOwnershipType::ReadOnly); + ob->runtime.geometry_set_eval = geometry_set_eval; + ob->runtime.mesh_deform_eval = mesh_deform_eval; ob->runtime.last_data_mask = *dataMask; ob->runtime.last_need_mapping = need_mapping; @@ -1864,11 +1937,14 @@ static void editbmesh_build_data(struct Depsgraph *depsgraph, Mesh *me_cage; Mesh *me_final; + GeometrySet *non_mesh_components; - editbmesh_calc_modifiers(depsgraph, scene, obedit, em, dataMask, &me_cage, &me_final); + editbmesh_calc_modifiers( + depsgraph, scene, obedit, em, dataMask, &me_cage, &me_final, &non_mesh_components); em->mesh_eval_final = me_final; em->mesh_eval_cage = me_cage; + obedit->runtime.geometry_set_eval = non_mesh_components; BKE_object_boundbox_calc_from_mesh(obedit, em->mesh_eval_final); @@ -2020,7 +2096,8 @@ Mesh *mesh_create_eval_final(Depsgraph *depsgraph, { Mesh *final; - mesh_calc_modifiers(depsgraph, scene, ob, 1, false, dataMask, -1, false, false, nullptr, &final); + mesh_calc_modifiers( + depsgraph, scene, ob, 1, false, dataMask, -1, false, false, nullptr, &final, nullptr); return final; } @@ -2034,7 +2111,7 @@ Mesh *mesh_create_eval_final_index_render(Depsgraph *depsgraph, Mesh *final; mesh_calc_modifiers( - depsgraph, scene, ob, 1, false, dataMask, index, false, false, nullptr, &final); + depsgraph, scene, ob, 1, false, dataMask, index, false, false, nullptr, &final, nullptr); return final; } @@ -2046,7 +2123,8 @@ Mesh *mesh_create_eval_no_deform(Depsgraph *depsgraph, { Mesh *final; - mesh_calc_modifiers(depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final); + mesh_calc_modifiers( + depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final, nullptr); return final; } @@ -2058,7 +2136,8 @@ Mesh *mesh_create_eval_no_deform_render(Depsgraph *depsgraph, { Mesh *final; - mesh_calc_modifiers(depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final); + mesh_calc_modifiers( + depsgraph, scene, ob, 0, false, dataMask, -1, false, false, nullptr, &final, nullptr); return final; } |