Geometry Nodes: Support top-level instance meshes in boolean node #114632

Merged
Hans Goudey merged 3 commits from HooglyBoogly/blender:fix-boolean-bad-4.0 into blender-v4.0-release 2023-11-09 11:54:51 +01:00
2 changed files with 46 additions and 23 deletions

View File

@ -455,15 +455,6 @@ static void version_movieclips_legacy_camera_object(Main *bmain)
}
}
static void version_geometry_nodes_add_realize_instance_nodes(bNodeTree *ntree)
{
LISTBASE_FOREACH_MUTABLE (bNode *, node, &ntree->nodes) {
if (STREQ(node->idname, "GeometryNodeMeshBoolean")) {
add_realize_instances_before_socket(ntree, node, nodeFindSocket(node, SOCK_IN, "Mesh 2"));
}
}
}
/* Version VertexWeightEdit modifier to make existing weights exclusive of the threshold. */
static void version_vertex_weight_edit_preserve_threshold_exclusivity(Main *bmain)
{
@ -1300,14 +1291,6 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
}
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 3)) {
LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
if (ntree->type == NTREE_GEOMETRY) {
version_geometry_nodes_add_realize_instance_nodes(ntree);
}
}
}
/* 400 4 did not require any do_version here. */
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 400, 5)) {

View File

@ -3,6 +3,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BKE_geometry_set_instances.hh"
#include "BKE_instances.hh"
#include "BKE_mesh_boolean_convert.hh"
#include "DNA_mesh_types.h"
@ -65,6 +66,16 @@ static void node_init(bNodeTree * /*tree*/, bNode *node)
node->custom1 = GEO_NODE_BOOLEAN_DIFFERENCE;
}
static Array<short> calc_mesh_material_map(const Mesh &mesh, VectorSet<Material *> &all_materials)
{
Array<short> map(mesh.totcol);
for (const int i : IndexRange(mesh.totcol)) {
Material *material = mesh.mat[i];
map[i] = material ? all_materials.index_of_or_add(material) : -1;
}
return map;
}
static void node_geo_exec(GeoNodeExecParams params)
{
#ifdef WITH_GMP
@ -73,6 +84,7 @@ static void node_geo_exec(GeoNodeExecParams params)
const bool hole_tolerant = params.get_input<bool>("Hole Tolerant");
Vector<const Mesh *> meshes;
Vector<float4x4> transforms;
VectorSet<Material *> materials;
Vector<Array<short>> material_remaps;
@ -84,6 +96,7 @@ static void node_geo_exec(GeoNodeExecParams params)
* to be a single mesh. */
if (const Mesh *mesh_in_a = set_a.get_mesh()) {
meshes.append(mesh_in_a);
transforms.append(float4x4::identity());
if (mesh_in_a->totcol == 0) {
/* Necessary for faces using the default material when there are no material slots. */
materials.add(nullptr);
@ -100,12 +113,39 @@ static void node_geo_exec(GeoNodeExecParams params)
for (const GeometrySet &geometry : geometry_sets) {
if (const Mesh *mesh = geometry.get_mesh()) {
meshes.append(mesh);
Array<short> map(mesh->totcol);
for (const int i : IndexRange(mesh->totcol)) {
Material *material = mesh->mat[i];
map[i] = material ? materials.index_of_or_add(material) : -1;
transforms.append(float4x4::identity());
material_remaps.append(calc_mesh_material_map(*mesh, materials));
}
if (const bke::Instances *instances = geometry.get_instances()) {
const Span<bke::InstanceReference> references = instances->references();
const Span<int> handles = instances->reference_handles();
const Span<float4x4> instance_transforms = instances->transforms();
for (const int i : handles.index_range()) {
const bke::InstanceReference &reference = references[handles[i]];
switch (reference.type()) {
case bke::InstanceReference::Type::Object: {
const GeometrySet object_geometry = bke::object_get_evaluated_geometry_set(
reference.object());
if (const Mesh *mesh = object_geometry.get_mesh()) {
meshes.append(mesh);
transforms.append(instance_transforms[i]);
material_remaps.append(calc_mesh_material_map(*mesh, materials));
}
break;
}
case bke::InstanceReference::Type::GeometrySet: {
if (const Mesh *mesh = reference.geometry_set().get_mesh()) {
meshes.append(mesh);
transforms.append(instance_transforms[i]);
material_remaps.append(calc_mesh_material_map(*mesh, materials));
}
break;
}
case bke::InstanceReference::Type::None:
case bke::InstanceReference::Type::Collection:
break;
}
}
material_remaps.append(std::move(map));
}
}
@ -116,7 +156,7 @@ static void node_geo_exec(GeoNodeExecParams params)
Vector<int> intersecting_edges;
Mesh *result = blender::meshintersect::direct_mesh_boolean(
meshes,
{},
transforms,
float4x4::identity(),
material_remaps,
use_self,