[Bf-blender-cvs] [b7ad58b945c] master: Geometry Nodes: Edge Angle Node

Johnny Matthews noreply at git.blender.org
Mon Jan 3 18:18:24 CET 2022


Commit: b7ad58b945c3779f32d2d01dd9c0e6e1bbe4e876
Author: Johnny Matthews
Date:   Mon Jan 3 11:16:50 2022 -0600
Branches: master
https://developer.blender.org/rBb7ad58b945c3779f32d2d01dd9c0e6e1bbe4e876

Geometry Nodes: Edge Angle Node

Calculates the angle in radians between two faces that meet at an edge.
0 to PI in either direction with flat being 0 and folded over on itself PI.
If there are not 2 faces on the edge, the angle will be 0.

For valid edges, the angle is the same as the 'edge angle' overlay.

For the Face and Point domain, the node uses simple interpolation to calculate a value.

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

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

M	release/scripts/startup/nodeitems_builtins.py
M	source/blender/blenkernel/BKE_node.h
M	source/blender/blenkernel/intern/node.cc
M	source/blender/nodes/NOD_geometry.h
M	source/blender/nodes/NOD_static_types.h
M	source/blender/nodes/geometry/CMakeLists.txt
A	source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc

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

diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index e7d7d7b2390..6ce11e1eace 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -150,6 +150,7 @@ def mesh_node_items(context):
     yield NodeItem("GeometryNodeSubdivisionSurface")
     yield NodeItem("GeometryNodeTriangulate")
     yield NodeItemCustom(draw=lambda self, layout, context: layout.separator())
+    yield NodeItem("GeometryNodeInputMeshEdgeAngle")
     yield NodeItem("GeometryNodeInputMeshEdgeNeighbors")
     yield NodeItem("GeometryNodeInputMeshEdgeVertices")
     yield NodeItem("GeometryNodeInputMeshFaceArea")
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 8bc4292448d..88c5fbeb60f 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1707,6 +1707,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
 #define GEO_NODE_INPUT_MESH_ISLAND 1144
 #define GEO_NODE_INPUT_SCENE_TIME 1145
 #define GEO_NODE_ACCUMULATE_FIELD 1146
+#define GEO_NODE_INPUT_MESH_EDGE_ANGLE 1147
 
 /** \} */
 
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index e61afe02f57..b6f69f9a9f7 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -4927,6 +4927,7 @@ static void registerGeometryNodes()
   register_node_type_geo_input_index();
   register_node_type_geo_input_material_index();
   register_node_type_geo_input_material();
+  register_node_type_geo_input_mesh_edge_angle();
   register_node_type_geo_input_mesh_edge_neighbors();
   register_node_type_geo_input_mesh_edge_vertices();
   register_node_type_geo_input_mesh_face_area();
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 2735dc445e2..96a5e1d87a6 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -106,6 +106,7 @@ void register_node_type_geo_input_id(void);
 void register_node_type_geo_input_index(void);
 void register_node_type_geo_input_material_index(void);
 void register_node_type_geo_input_material(void);
+void register_node_type_geo_input_mesh_edge_angle(void);
 void register_node_type_geo_input_mesh_edge_neighbors(void);
 void register_node_type_geo_input_mesh_edge_vertices(void);
 void register_node_type_geo_input_mesh_face_area(void);
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 108a37d0176..74f1531bd90 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -359,6 +359,7 @@ DefNode(GeometryNode, GEO_NODE_INPUT_ID, 0, "INPUT_ID", InputID, "ID", "")
 DefNode(GeometryNode, GEO_NODE_INPUT_INDEX, 0, "INDEX", InputIndex, "Index", "")
 DefNode(GeometryNode, GEO_NODE_INPUT_MATERIAL_INDEX, 0, "INPUT_MATERIAL_INDEX", InputMaterialIndex, "Material Index", "")
 DefNode(GeometryNode, GEO_NODE_INPUT_MATERIAL, def_geo_input_material, "INPUT_MATERIAL", InputMaterial, "Material", "")
+DefNode(GeometryNode, GEO_NODE_INPUT_MESH_EDGE_ANGLE, 0, "MESH_EDGE_ANGLE", InputMeshEdgeAngle, "Edge Angle", "")
 DefNode(GeometryNode, GEO_NODE_INPUT_MESH_EDGE_NEIGHBORS, 0, "MESH_EDGE_NEIGHBORS", InputMeshEdgeNeighbors, "Edge Neighbors", "")
 DefNode(GeometryNode, GEO_NODE_INPUT_MESH_EDGE_VERTICES, 0, "MESH_EDGE_VERTICES", InputMeshEdgeVertices, "Edge Vertices", "")
 DefNode(GeometryNode, GEO_NODE_INPUT_MESH_FACE_AREA, 0, "MESH_FACE_AREA", InputMeshFaceArea, "Face Area", "")
diff --git a/source/blender/nodes/geometry/CMakeLists.txt b/source/blender/nodes/geometry/CMakeLists.txt
index 5d45fe9021a..e0c31fad97f 100644
--- a/source/blender/nodes/geometry/CMakeLists.txt
+++ b/source/blender/nodes/geometry/CMakeLists.txt
@@ -124,6 +124,7 @@ set(SRC
   nodes/node_geo_input_index.cc
   nodes/node_geo_input_material_index.cc
   nodes/node_geo_input_material.cc
+  nodes/node_geo_input_mesh_edge_angle.cc
   nodes/node_geo_input_mesh_edge_neighbors.cc
   nodes/node_geo_input_mesh_edge_vertices.cc
   nodes/node_geo_input_mesh_face_area.cc
diff --git a/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc
new file mode 100644
index 00000000000..ec438608957
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_input_mesh_edge_angle.cc
@@ -0,0 +1,128 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_mesh.h"
+
+#include "node_geometry_util.hh"
+
+namespace blender::nodes::node_geo_input_mesh_edge_angle_cc {
+
+static void node_declare(NodeDeclarationBuilder &b)
+{
+  b.add_output<decl::Float>(N_("Angle"))
+      .field_source()
+      .description(
+          "The angle in radians between two faces where they meet at an edge. Flat edges and "
+          "Non-manifold edges have an angle of zero");
+}
+
+struct EdgeMapEntry {
+  int face_count;
+  int face_index_1;
+  int face_index_2;
+};
+
+class AngleFieldInput final : public GeometryFieldInput {
+ public:
+  AngleFieldInput() : GeometryFieldInput(CPPType::get<float>(), "Angle Field")
+  {
+    category_ = Category::Generated;
+  }
+
+  GVArray get_varray_for_context(const GeometryComponent &component,
+                                 const AttributeDomain domain,
+                                 IndexMask UNUSED(mask)) const final
+  {
+    if (component.type() != GEO_COMPONENT_TYPE_MESH) {
+      return {};
+    }
+
+    const MeshComponent &mesh_component = static_cast<const MeshComponent &>(component);
+    const Mesh *mesh = mesh_component.get_for_read();
+    if (mesh == nullptr) {
+      return {};
+    }
+
+    Span<MPoly> polys{mesh->mpoly, mesh->totpoly};
+    Span<MLoop> loops{mesh->mloop, mesh->totloop};
+    Array<EdgeMapEntry> edge_map(mesh->totedge, {0, 0, 0});
+
+    for (const int i_poly : polys.index_range()) {
+      const MPoly &mpoly = polys[i_poly];
+      for (const MLoop &loop : loops.slice(mpoly.loopstart, mpoly.totloop)) {
+        EdgeMapEntry &entry = edge_map[loop.e];
+        if (entry.face_count == 0) {
+          entry.face_index_1 = i_poly;
+        }
+        else if (entry.face_count == 1) {
+          entry.face_index_2 = i_poly;
+        }
+        entry.face_count++;
+      }
+    }
+
+    auto angle_fn = [edge_map, polys, loops, mesh](const int i) -> float {
+      if (edge_map[i].face_count == 2) {
+        const MPoly &mpoly_1 = polys[edge_map[i].face_index_1];
+        const MPoly &mpoly_2 = polys[edge_map[i].face_index_2];
+        float3 normal_1, normal_2;
+        BKE_mesh_calc_poly_normal(&mpoly_1, &loops[mpoly_1.loopstart], mesh->mvert, normal_1);
+        BKE_mesh_calc_poly_normal(&mpoly_2, &loops[mpoly_2.loopstart], mesh->mvert, normal_2);
+        return angle_normalized_v3v3(normal_1, normal_2);
+      }
+      else {
+        return 0.0f;
+      }
+    };
+
+    VArray<float> angles = VArray<float>::ForFunc(mesh->totedge, angle_fn);
+    return component.attribute_try_adapt_domain<float>(
+        std::move(angles), ATTR_DOMAIN_EDGE, domain);
+  }
+
+  uint64_t hash() const override
+  {
+    /* Some random constant hash. */
+    return 32426725235;
+  }
+
+  bool is_equal_to(const fn::FieldNode &other) const override
+  {
+    return dynamic_cast<const AngleFieldInput *>(&other) != nullptr;
+  }
+};
+
+static void node_geo_exec(GeoNodeExecParams params)
+{
+  Field<float> angle_field{std::make_shared<AngleFieldInput>()};
+  params.set_output("Angle", std::move(angle_field));
+}
+
+}  // namespace blender::nodes::node_geo_input_mesh_edge_angle_cc
+
+void register_node_type_geo_input_mesh_edge_angle()
+{
+  namespace file_ns = blender::nodes::node_geo_input_mesh_edge_angle_cc;
+
+  static bNodeType ntype;
+  geo_node_type_base(&ntype, GEO_NODE_INPUT_MESH_EDGE_ANGLE, "Edge Angle", NODE_CLASS_INPUT, 0);
+  ntype.declare = file_ns::node_declare;
+  ntype.geometry_node_execute = file_ns::node_geo_exec;
+  nodeRegisterType(&ntype);
+}



More information about the Bf-blender-cvs mailing list