diff options
author | Jacques Lucke <jacques@blender.org> | 2021-02-17 14:27:32 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2021-02-17 14:28:00 +0300 |
commit | 96da8e9ca302b8d879744318c5ad12c64a5b3c2c (patch) | |
tree | 266e920cdfcbaa3959375c6eb5ad68dd8868655a /source | |
parent | 3a6d6299d7a0f2a6a156bce6731a0b29804d911d (diff) |
Geometry Nodes: realize instances before passing geometry to constructive mesh modifier
Previously, when the output of a Geometry Nodes modifier would
contain instances, those could not be accessed by other existing
modifiers (e.g. the Array modifier). That is because those modifiers
don't know about instances.
Upcoming commits will improve an this in two ways:
* Also realize instances before deform modifiers.
* Convert a point cloud in the geometry to mesh vertices so that
they can be accessed as well.
Note, making instances real can result in loosing some information
that we do not support in Geometry Nodes yet. That includes some
special builtin attributes like bevel weights.
Ref T85281.
Differential Revision: https://developer.blender.org/D10432
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/intern/DerivedMesh.cc | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc index ecc41e3f0df..3aef53de64e 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.cc +++ b/source/blender/blenkernel/intern/DerivedMesh.cc @@ -51,6 +51,7 @@ #include "BKE_deform.h" #include "BKE_editmesh.h" #include "BKE_geometry_set.hh" +#include "BKE_geometry_set_instances.hh" #include "BKE_key.h" #include "BKE_layer.h" #include "BKE_lib_id.h" @@ -883,6 +884,32 @@ void BKE_mesh_wrapper_deferred_finalize(Mesh *me_eval, } /** + * Some modifiers don't work on geometry sets directly, but expect a single mesh as input. + * Therefore, we convert data from the geometry set into a single mesh, so that those + * modifiers can work on it as well. + */ +static Mesh *prepare_geometry_set_for_mesh_modifier(Mesh *mesh, GeometrySet &r_geometry_set) +{ + if (!r_geometry_set.has_instances()) { + return mesh; + } + + { + /* Add the mesh to the geometry set. */ + MeshComponent &mesh_component = r_geometry_set.get_component_for_write<MeshComponent>(); + mesh_component.replace_mesh_but_keep_vertex_group_names(mesh, GeometryOwnershipType::Editable); + } + { + /* Combine mesh and all instances into a single mesh that can be passed to the modifier. */ + GeometrySet new_geometry_set = blender::bke::geometry_set_realize_instances(r_geometry_set); + MeshComponent &mesh_component = new_geometry_set.get_component_for_write<MeshComponent>(); + Mesh *new_mesh = mesh_component.release(); + r_geometry_set = new_geometry_set; + return new_mesh; + } +} + +/** * Modifies the given mesh and geometry set. The mesh is not passed as part of the mesh component * in the \a geometry_set input, it is only passed in \a input_mesh and returned in the return * value. @@ -898,7 +925,14 @@ static Mesh *modifier_modify_mesh_and_geometry_set(ModifierData *md, 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); + Mesh *new_input_mesh = prepare_geometry_set_for_mesh_modifier(input_mesh, geometry_set); + mesh_output = BKE_modifier_modify_mesh(md, &mectx, new_input_mesh); + + /* The caller is responsible for freeing `input_mesh` and `mesh_output`. The intermediate + * `new_input_mesh` has to be freed here. */ + if (!ELEM(new_input_mesh, input_mesh, mesh_output)) { + BKE_id_free(nullptr, new_input_mesh); + } } else { /* For performance reasons, this should be called by the modifier and/or nodes themselves at |