Geometry Nodes: Propagate vertex groups in join / realize instances nodes

Currently the realize instances code (which is also used by the join
geometry node) always creates generic attributes instead of vertex
groups. The expectation was that vertex groups would be replaced
by some form of generic attribute sooner rather than later. However,
it's clear that won't happen for some time, and this issue causes users
a lot of trouble. This commit preserves the vertex groups through the
operation. Any attribute name that was a vertex group on any of the
input meshes will become a vertex group in the result.

In the code this is a simple change because the attribute writer
abstraction allows writing to vertex groups as if the were just like
other contiguous arrays. In the future we could optimize the code
specifically for vertex groups.

This resolves the "bug" part of #99197 where the nodes remove vertex
groups. However, this doesn't change the fact that generating
primitive meshes in geometry nodes won't create vertex groups.
In general the property editor settings on the original mesh have
no effect on meshes created from scratch in geometry nodes.

Pull Request: https://projects.blender.org/blender/blender/pulls/131692
This commit is contained in:
Hans Goudey
2024-12-11 01:17:23 +01:00
committed by Hans Goudey
parent f8da7ecfe1
commit 84c7684871

View File

@@ -1526,6 +1526,25 @@ static void execute_realize_mesh_task(const RealizeInstancesOptions &options,
dst_attribute_writers);
}
static void copy_vertex_group_names(Mesh &dst_mesh, const Span<const Mesh *> src_meshes)
{
Set<StringRef> existing_names;
LISTBASE_FOREACH (const bDeformGroup *, defgroup, &dst_mesh.vertex_group_names) {
existing_names.add(defgroup->name);
}
for (const Mesh *mesh : src_meshes) {
LISTBASE_FOREACH (const bDeformGroup *, src, &mesh->vertex_group_names) {
const StringRef src_name = src->name;
if (existing_names.contains(src_name)) {
continue;
}
bDeformGroup *dst = MEM_cnew<bDeformGroup>(__func__);
src_name.copy(dst->name);
BLI_addtail(&dst_mesh.vertex_group_names, dst);
}
}
}
static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options,
const AllMeshesInfo &all_meshes_info,
const Span<RealizeMeshTask> tasks,
@@ -1570,9 +1589,11 @@ static void execute_realize_mesh_tasks(const RealizeInstancesOptions &options,
const RealizeMeshTask &first_task = tasks.first();
const Mesh &first_mesh = *first_task.mesh_info->mesh;
BKE_mesh_copy_parameters_for_eval(dst_mesh, &first_mesh);
/* The above line also copies vertex group names. We don't want that here because the new
* attributes are added explicitly below. */
BLI_freelistN(&dst_mesh->vertex_group_names);
BLI_assert(BLI_listbase_count(&dst_mesh->vertex_group_names) ==
BLI_listbase_count(&first_mesh.vertex_group_names));
copy_vertex_group_names(*dst_mesh, all_meshes_info.order.as_span().drop_front(1));
dst_mesh->vertex_group_active_index = first_mesh.vertex_group_active_index;
/* Add materials. */
for (const int i : IndexRange(ordered_materials.size())) {