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
This commit is contained in:
Jacques Lucke 2021-02-17 12:27:32 +01:00
parent 3a6d6299d7
commit 96da8e9ca3
Notes: blender-bot 2023-02-14 00:13:36 +01:00
Referenced by commit 55a69d5707, Geometry Nodes: realize instances before deform modifier
Referenced by issue #85281, Support piping legacy modifiers with the geometry nodes modifiers
1 changed files with 35 additions and 1 deletions

View File

@ -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"
@ -882,6 +883,32 @@ void BKE_mesh_wrapper_deferred_finalize(Mesh *me_eval,
BLI_assert(me_eval->runtime.wrapper_type_finalize == 0);
}
/**
* 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
@ -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