[Bf-blender-cvs] [e2975cb7016] master: Geometry Nodes: add 'Intersecting Edges' output for boolean node

Philipp Oeser noreply at git.blender.org
Thu Jun 16 20:38:50 CEST 2022


Commit: e2975cb701692574504967178699c9ab083dc3f8
Author: Philipp Oeser
Date:   Mon Apr 4 12:26:50 2022 +0200
Branches: master
https://developer.blender.org/rBe2975cb701692574504967178699c9ab083dc3f8

Geometry Nodes: add 'Intersecting Edges' output for boolean node

This patch adds a 'Intersecting Edges' output with a boolean selection
that only gives you the new edges on intersections.

Will work on a couple of examples next, this should make some
interesting effects possible (including getting us closer to the "bevel-
after-boolean-usecase")

To achieve this, a Vector is passed to `direct_mesh_boolean` when the
iMesh is still available (and intersecting edges appended), then from
those edge indices a selection will be stored as attribute.

Differential Revision: https://developer.blender.org/D15151

===================================================================

M	source/blender/blenkernel/BKE_mesh_boolean_convert.hh
M	source/blender/blenkernel/intern/mesh_boolean_convert.cc
M	source/blender/modifiers/intern/MOD_boolean.cc
M	source/blender/nodes/geometry/nodes/node_geo_boolean.cc

===================================================================

diff --git a/source/blender/blenkernel/BKE_mesh_boolean_convert.hh b/source/blender/blenkernel/BKE_mesh_boolean_convert.hh
index abaf2ab0178..441783d46a1 100644
--- a/source/blender/blenkernel/BKE_mesh_boolean_convert.hh
+++ b/source/blender/blenkernel/BKE_mesh_boolean_convert.hh
@@ -23,6 +23,8 @@ namespace blender::meshintersect {
  * \param material_remaps: An array of maps from material slot numbers in the corresponding mesh
  * to the material slot in the first mesh. It is OK for material_remaps or any of its constituent
  * arrays to be empty.
+ * \param r_intersecting_edges: Array to store indices of edges on the resulting mesh in. These
+ * 'new' edges are the result of the intersections.
  */
 Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
                           Span<const float4x4 *> transforms,
@@ -30,6 +32,7 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
                           Span<Array<short>> material_remaps,
                           bool use_self,
                           bool hole_tolerant,
-                          int boolean_mode);
+                          int boolean_mode,
+                          Vector<int> *r_intersecting_edges);
 
 }  // namespace blender::meshintersect
diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
index 14bd6aa5b2f..79bdc08fe8f 100644
--- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc
@@ -791,7 +791,8 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
                           Span<Array<short>> material_remaps,
                           const bool use_self,
                           const bool hole_tolerant,
-                          const int boolean_mode)
+                          const int boolean_mode,
+                          Vector<int> *r_intersecting_edges)
 {
 #ifdef WITH_GMP
   BLI_assert(meshes.size() == transforms.size());
@@ -828,7 +829,23 @@ Mesh *direct_mesh_boolean(Span<const Mesh *> meshes,
     write_obj_mesh(m_out, "m_out");
   }
 
-  return imesh_to_mesh(&m_out, mim);
+  Mesh *result = imesh_to_mesh(&m_out, mim);
+
+  /* Store intersecting edge indices. */
+  if (r_intersecting_edges != nullptr) {
+    for (int fi : m_out.face_index_range()) {
+      const Face &face = *m_out.face(fi);
+      const MPoly &poly = result->mpoly[fi];
+      for (int corner_i : face.index_range()) {
+        if (face.is_intersect[corner_i]) {
+          int e_index = result->mloop[poly.loopstart + corner_i].e;
+          r_intersecting_edges->append(e_index);
+        }
+      }
+    }
+  }
+
+  return result;
 #else   // WITH_GMP
   UNUSED_VARS(meshes,
               transforms,
diff --git a/source/blender/modifiers/intern/MOD_boolean.cc b/source/blender/modifiers/intern/MOD_boolean.cc
index 07504d91fea..5739de1c65c 100644
--- a/source/blender/modifiers/intern/MOD_boolean.cc
+++ b/source/blender/modifiers/intern/MOD_boolean.cc
@@ -447,7 +447,8 @@ static Mesh *exact_boolean_mesh(BooleanModifierData *bmd,
                                                      material_remaps,
                                                      use_self,
                                                      hole_tolerant,
-                                                     bmd->operation);
+                                                     bmd->operation,
+                                                     nullptr);
 }
 #endif
 
diff --git a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
index e485172d3e1..daeca311e08 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_boolean.cc
@@ -20,6 +20,7 @@ static void node_declare(NodeDeclarationBuilder &b)
   b.add_input<decl::Bool>(N_("Self Intersection"));
   b.add_input<decl::Bool>(N_("Hole Tolerant"));
   b.add_output<decl::Geometry>(N_("Mesh"));
+  b.add_output<decl::Bool>(N_("Intersecting Edges")).field_source();
 }
 
 static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
@@ -27,6 +28,10 @@ static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
   uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
 }
 
+struct AttributeOutputs {
+  StrongAnonymousAttributeID intersecting_edges_id;
+};
+
 static void node_update(bNodeTree *ntree, bNode *node)
 {
   GeometryNodeBooleanOperation operation = (GeometryNodeBooleanOperation)node->custom1;
@@ -121,13 +126,21 @@ static void node_geo_exec(GeoNodeExecParams params)
     }
   }
 
-  Mesh *result = blender::meshintersect::direct_mesh_boolean(meshes,
-                                                             transforms,
-                                                             float4x4::identity(),
-                                                             material_remaps,
-                                                             use_self,
-                                                             hole_tolerant,
-                                                             operation);
+  AttributeOutputs attribute_outputs;
+  if (params.output_is_required("Intersecting Edges")) {
+    attribute_outputs.intersecting_edges_id = StrongAnonymousAttributeID("Intersecting Edges");
+  }
+
+  Vector<int> intersecting_edges;
+  Mesh *result = blender::meshintersect::direct_mesh_boolean(
+      meshes,
+      transforms,
+      float4x4::identity(),
+      material_remaps,
+      use_self,
+      hole_tolerant,
+      operation,
+      attribute_outputs.intersecting_edges_id ? &intersecting_edges : nullptr);
   if (!result) {
     params.set_default_remaining_outputs();
     return;
@@ -138,6 +151,26 @@ static void node_geo_exec(GeoNodeExecParams params)
   result->totcol = materials.size();
   MutableSpan(result->mat, result->totcol).copy_from(materials);
 
+  /* Store intersecting edges in attribute. */
+  if (attribute_outputs.intersecting_edges_id) {
+    MeshComponent mesh_component;
+    mesh_component.replace(result, GeometryOwnershipType::Editable);
+    OutputAttribute_Typed<bool> attribute = mesh_component.attribute_try_get_for_output_only<bool>(
+        attribute_outputs.intersecting_edges_id.get(), ATTR_DOMAIN_EDGE);
+    MutableSpan<bool> selection = attribute.as_span();
+    selection.fill(false);
+    for (const int i : intersecting_edges) {
+      selection[i] = true;
+    }
+
+    attribute.save();
+
+    params.set_output(
+        "Intersecting Edges",
+        AnonymousAttributeFieldInput::Create<bool>(
+            std::move(attribute_outputs.intersecting_edges_id), params.attribute_producer_name()));
+  }
+
   params.set_output("Mesh", GeometrySet::create_with_mesh(result));
 #else
   params.error_message_add(NodeWarningType::Error,



More information about the Bf-blender-cvs mailing list