Changeset View
Changeset View
Standalone View
Standalone View
source/blender/nodes/geometry/nodes/node_geo_boolean.cc
| Show First 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | |||||
| #ifndef WITH_GMP | #ifndef WITH_GMP | ||||
| params.error_message_add(NodeWarningType::Error, | params.error_message_add(NodeWarningType::Error, | ||||
| TIP_("Disabled, Blender was compiled without GMP")); | TIP_("Disabled, Blender was compiled without GMP")); | ||||
| #endif | #endif | ||||
| Vector<const Mesh *> meshes; | Vector<const Mesh *> meshes; | ||||
| Vector<const float4x4 *> transforms; | Vector<const float4x4 *> transforms; | ||||
| /* For legacy reasons vertex group names have to be handled separately. The boolean code will | |||||
| * just merge vertex groups based on their index without looking at the name. */ | |||||
| const Map<std::string, int> *vertex_group_names = nullptr; | |||||
| GeometrySet set_a; | GeometrySet set_a; | ||||
| if (operation == GEO_NODE_BOOLEAN_DIFFERENCE) { | if (operation == GEO_NODE_BOOLEAN_DIFFERENCE) { | ||||
| set_a = params.extract_input<GeometrySet>("Geometry 1"); | set_a = params.extract_input<GeometrySet>("Geometry 1"); | ||||
| /* Note that it technically wouldn't be necessary to realize the instances for the first | /* Note that it technically wouldn't be necessary to realize the instances for the first | ||||
| * geometry input, but the boolean code expects the first shape for the difference operation | * geometry input, but the boolean code expects the first shape for the difference operation | ||||
| * to be a single mesh. */ | * to be a single mesh. */ | ||||
| set_a = geometry_set_realize_instances(set_a); | set_a = geometry_set_realize_instances(set_a); | ||||
| const Mesh *mesh_in_a = set_a.get_mesh_for_read(); | const MeshComponent *mesh_component = set_a.get_component_for_read<MeshComponent>(); | ||||
| if (mesh_component != nullptr) { | |||||
| const Mesh *mesh_in_a = mesh_component->get_for_read(); | |||||
| vertex_group_names = &mesh_component->vertex_group_names(); | |||||
| if (mesh_in_a != nullptr) { | if (mesh_in_a != nullptr) { | ||||
| meshes.append(mesh_in_a); | meshes.append(mesh_in_a); | ||||
| transforms.append(nullptr); | transforms.append(nullptr); | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| /* The instance transform matrices are owned by the instance group, so we have to | /* The instance transform matrices are owned by the instance group, so we have to | ||||
| * keep all of them around for use during the boolean operation. */ | * keep all of them around for use during the boolean operation. */ | ||||
| Vector<bke::GeometryInstanceGroup> set_groups; | Vector<bke::GeometryInstanceGroup> set_groups; | ||||
| Vector<GeometrySet> geometry_sets = params.extract_multi_input<GeometrySet>("Geometry 2"); | Vector<GeometrySet> geometry_sets = params.extract_multi_input<GeometrySet>("Geometry 2"); | ||||
| for (const GeometrySet &geometry_set : geometry_sets) { | for (const GeometrySet &geometry_set : geometry_sets) { | ||||
| bke::geometry_set_gather_instances(geometry_set, set_groups); | bke::geometry_set_gather_instances(geometry_set, set_groups); | ||||
| } | } | ||||
| for (const bke::GeometryInstanceGroup &set_group : set_groups) { | for (const bke::GeometryInstanceGroup &set_group : set_groups) { | ||||
| const Mesh *mesh_in = set_group.geometry_set.get_mesh_for_read(); | const MeshComponent *mesh_component = | ||||
| if (mesh_in != nullptr) { | set_group.geometry_set.get_component_for_read<MeshComponent>(); | ||||
| if (mesh_component == nullptr) { | |||||
| continue; | |||||
| } | |||||
| const Mesh *mesh_in = mesh_component->get_for_read(); | |||||
| if (mesh_in == nullptr) { | |||||
| continue; | |||||
| } | |||||
| if (vertex_group_names == nullptr) { | |||||
| if (!mesh_component->vertex_group_names().is_empty()) { | |||||
| vertex_group_names = &mesh_component->vertex_group_names(); | |||||
| } | |||||
| } | |||||
| meshes.append_n_times(mesh_in, set_group.transforms.size()); | meshes.append_n_times(mesh_in, set_group.transforms.size()); | ||||
| for (const int i : set_group.transforms.index_range()) { | for (const int i : set_group.transforms.index_range()) { | ||||
| transforms.append(set_group.transforms.begin() + i); | transforms.append(set_group.transforms.begin() + i); | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| Mesh *result = blender::meshintersect::direct_mesh_boolean( | Mesh *result = blender::meshintersect::direct_mesh_boolean( | ||||
| meshes, transforms, float4x4::identity(), {}, use_self, hole_tolerant, operation); | meshes, transforms, float4x4::identity(), {}, use_self, hole_tolerant, operation); | ||||
| params.set_output("Geometry", GeometrySet::create_with_mesh(result)); | GeometrySet output_geometry_set; | ||||
| MeshComponent &output_mesh_component = | |||||
| output_geometry_set.get_component_for_write<MeshComponent>(); | |||||
| output_mesh_component.replace(result); | |||||
| if (vertex_group_names != nullptr) { | |||||
| output_mesh_component.vertex_group_names() = *vertex_group_names; | |||||
| } | |||||
| params.set_output("Geometry", std::move(output_geometry_set)); | |||||
| } | } | ||||
| } // namespace blender::nodes | } // namespace blender::nodes | ||||
| void register_node_type_geo_boolean() | void register_node_type_geo_boolean() | ||||
| { | { | ||||
| static bNodeType ntype; | static bNodeType ntype; | ||||
| geo_node_type_base(&ntype, GEO_NODE_BOOLEAN, "Boolean", NODE_CLASS_GEOMETRY, 0); | geo_node_type_base(&ntype, GEO_NODE_BOOLEAN, "Boolean", NODE_CLASS_GEOMETRY, 0); | ||||
| node_type_socket_templates(&ntype, geo_node_boolean_in, geo_node_boolean_out); | node_type_socket_templates(&ntype, geo_node_boolean_in, geo_node_boolean_out); | ||||
| ntype.draw_buttons = geo_node_boolean_layout; | ntype.draw_buttons = geo_node_boolean_layout; | ||||
| ntype.updatefunc = geo_node_boolean_update; | ntype.updatefunc = geo_node_boolean_update; | ||||
| node_type_init(&ntype, geo_node_boolean_init); | node_type_init(&ntype, geo_node_boolean_init); | ||||
| ntype.geometry_node_execute = blender::nodes::geo_node_boolean_exec; | ntype.geometry_node_execute = blender::nodes::geo_node_boolean_exec; | ||||
| nodeRegisterType(&ntype); | nodeRegisterType(&ntype); | ||||
| } | } | ||||