[Bf-blender-cvs] [75a92d451ea] geometry-nodes: Geometry Nodes: new Join node

Jacques Lucke noreply at git.blender.org
Mon Nov 23 19:13:33 CET 2020


Commit: 75a92d451ea24ff6f8174f26163b08088122ed3e
Author: Jacques Lucke
Date:   Mon Nov 23 19:13:25 2020 +0100
Branches: geometry-nodes
https://developer.blender.org/rB75a92d451ea24ff6f8174f26163b08088122ed3e

Geometry Nodes: new Join node

This node creates a new geometry based on two incoming geometries.
In the future the node ui can be extended to support more than two inputs.

The output geometry will have all the attributes of the inputs.
If both inputs have non-matching set of attributes, missing data is either
interpolated, type cast or zeroed.

Ref T82786.

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

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

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

diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index 8ab872b83c7..9791b0dbdd5 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -497,6 +497,7 @@ geometry_node_categories = [
     GeometryNodeCategory("GEO_GEOMETRY", "Geometry", items=[
         NodeItem("GeometryNodeTransform"),
         NodeItem("GeometryNodeBoolean"),
+        NodeItem("GeometryNodeJoin"),
     ]),
     GeometryNodeCategory("GEO_INPUT", "Input", items=[
         NodeItem("GeometryNodeObjectInfo"),
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 1cee60fe87d..23893d3d6b6 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -1347,6 +1347,7 @@ int ntreeTexExecTree(struct bNodeTree *ntree,
 #define GEO_NODE_OBJECT_INFO 1007
 #define GEO_NODE_RANDOM_ATTRIBUTE 1008
 #define GEO_NODE_ATTRIBUTE_MATH 1009
+#define GEO_NODE_JOIN 1010
 
 /** \} */
 
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index ebdfb3c6cc0..a5df5df7f77 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -4692,6 +4692,7 @@ static void registerGeometryNodes(void)
   register_node_type_geo_object_info();
   register_node_type_geo_random_attribute();
   register_node_type_geo_attribute_math();
+  register_node_type_geo_join();
 }
 
 static void registerFunctionNodes(void)
diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt
index 3585703fb7d..cb95b09135f 100644
--- a/source/blender/nodes/CMakeLists.txt
+++ b/source/blender/nodes/CMakeLists.txt
@@ -142,6 +142,7 @@ set(SRC
   geometry/nodes/node_geo_common.cc
   geometry/nodes/node_geo_boolean.cc
   geometry/nodes/node_geo_edge_split.cc
+  geometry/nodes/node_geo_join.cc
   geometry/nodes/node_geo_object_info.cc
   geometry/nodes/node_geo_subdivision_surface.cc
   geometry/nodes/node_geo_point_distribute.cc
diff --git a/source/blender/nodes/NOD_geometry.h b/source/blender/nodes/NOD_geometry.h
index 102e370e132..122b9a7cd17 100644
--- a/source/blender/nodes/NOD_geometry.h
+++ b/source/blender/nodes/NOD_geometry.h
@@ -36,6 +36,7 @@ void register_node_type_geo_point_instance(void);
 void register_node_type_geo_object_info(void);
 void register_node_type_geo_random_attribute(void);
 void register_node_type_geo_attribute_math(void);
+void register_node_type_geo_join(void);
 
 #ifdef __cplusplus
 }
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 170fecb256d..49a761a45b5 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -276,6 +276,7 @@ DefNode(GeometryNode, GEO_NODE_POINT_INSTANCE, 0, "POINT_INSTANCE", PointInstanc
 DefNode(GeometryNode, GEO_NODE_OBJECT_INFO, 0, "OBJECT_INFO", ObjectInfo, "Object Info", "")
 DefNode(GeometryNode, GEO_NODE_RANDOM_ATTRIBUTE, def_geo_random_attribute, "RANDOM_ATTRIBUTE", RandomAttribute, "Random Attribute", "")
 DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_MATH, def_geo_attribute_math, "ATTRIBUTE_MATH", AttributeMath, "Attribute Math", "")
+DefNode(GeometryNode, GEO_NODE_JOIN, 0, "JOIN", Join, "Join", "")
 
 /* undefine macros */
 #undef DefNode
diff --git a/source/blender/nodes/geometry/nodes/node_geo_join.cc b/source/blender/nodes/geometry/nodes/node_geo_join.cc
new file mode 100644
index 00000000000..f402ed4542a
--- /dev/null
+++ b/source/blender/nodes/geometry/nodes/node_geo_join.cc
@@ -0,0 +1,266 @@
+/*
+ * 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 "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_pointcloud.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "node_geometry_util.hh"
+
+static bNodeSocketTemplate geo_node_join_in[] = {
+    {SOCK_GEOMETRY, N_("Geometry")},
+    {SOCK_GEOMETRY, N_("Geometry")},
+    {-1, ""},
+};
+
+static bNodeSocketTemplate geo_node_join_out[] = {
+    {SOCK_GEOMETRY, N_("Geometry")},
+    {-1, ""},
+};
+
+namespace blender::nodes {
+
+static Mesh *join_mesh_topologies(Span<const MeshComponent *> src_components)
+{
+  int totverts = 0;
+  int totloops = 0;
+  int totedges = 0;
+  int totpolys = 0;
+
+  for (const MeshComponent *mesh_component : src_components) {
+    const Mesh *mesh = mesh_component->get_for_read();
+    if (mesh == nullptr) {
+      continue;
+    }
+
+    totverts += mesh->totvert;
+    totloops += mesh->totloop;
+    totedges += mesh->totedge;
+    totpolys += mesh->totpoly;
+  }
+
+  Mesh *new_mesh = BKE_mesh_new_nomain(totverts, totedges, 0, totloops, totpolys);
+
+  int vert_offset = 0;
+  int loop_offset = 0;
+  int edge_offset = 0;
+  int poly_offset = 0;
+  for (const MeshComponent *mesh_component : src_components) {
+    const Mesh *mesh = mesh_component->get_for_read();
+    if (mesh == nullptr) {
+      continue;
+    }
+
+    for (const int i : IndexRange(mesh->totedge)) {
+      const MEdge &old_edge = mesh->medge[i];
+      MEdge &new_edge = new_mesh->medge[edge_offset + i];
+      new_edge.v1 = old_edge.v1 + vert_offset;
+      new_edge.v2 = old_edge.v2 + vert_offset;
+    }
+    for (const int i : IndexRange(mesh->totloop)) {
+      const MLoop &old_loop = mesh->mloop[i];
+      MLoop &new_loop = new_mesh->mloop[loop_offset + i];
+      new_loop.v = old_loop.v + vert_offset;
+      new_loop.e = old_loop.e + edge_offset;
+    }
+    for (const int i : IndexRange(mesh->totpoly)) {
+      const MPoly &old_poly = mesh->mpoly[i];
+      MPoly &new_poly = new_mesh->mpoly[poly_offset + i];
+      new_poly.loopstart = old_poly.loopstart + loop_offset;
+      new_poly.totloop = old_poly.totloop;
+    }
+
+    vert_offset += mesh->totvert;
+    loop_offset += mesh->totloop;
+    edge_offset += mesh->totedge;
+    poly_offset += mesh->totpoly;
+  }
+
+  return new_mesh;
+}
+
+template<typename Component>
+static Array<const GeometryComponent *> to_base_components(Span<const Component *> components)
+{
+  return components;
+}
+
+static Set<std::string> find_all_attribute_names(Span<const GeometryComponent *> components)
+{
+  Set<std::string> attribute_names;
+  for (const GeometryComponent *component : components) {
+    Set<std::string> names = component->attribute_names();
+    for (const std::string &name : names) {
+      attribute_names.add(name);
+    }
+  }
+  return attribute_names;
+}
+
+static void determine_final_data_type_and_domain(Span<const GeometryComponent *> components,
+                                                 StringRef attribute_name,
+                                                 CustomDataType *r_type,
+                                                 AttributeDomain *r_domain)
+{
+  for (const GeometryComponent *component : components) {
+    ReadAttributePtr attribute = component->attribute_try_get_for_read(attribute_name);
+    if (attribute) {
+      /* TODO: Use data type with most information. */
+      *r_type = bke::cpp_type_to_custom_data_type(attribute->cpp_type());
+      /* TODO: Use highest priority domain. */
+      *r_domain = attribute->domain();
+      return;
+    }
+  }
+  BLI_assert(false);
+}
+
+static void fill_new_attribute(Span<const GeometryComponent *> src_components,
+                               StringRef attribute_name,
+                               const CustomDataType data_type,
+                               const AttributeDomain domain,
+                               WriteAttributePtr &output_attribute)
+{
+  const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(data_type);
+  BLI_assert(cpp_type != nullptr);
+
+  int offset = 0;
+  for (const GeometryComponent *component : src_components) {
+    const int domain_size = component->attribute_domain_size(domain);
+    ReadAttributePtr read_attribute = component->attribute_get_for_read(
+        attribute_name, domain, data_type, nullptr);
+
+    AlignedBuffer<64, 64> buffer;
+    BLI_assert(64 >= cpp_type->size());
+    for (const int i : IndexRange(domain_size)) {
+      read_attribute->get(i, buffer.ptr());
+      output_attribute->set(offset + i, buffer.ptr());
+      cpp_type->destruct(buffer.ptr());
+    }
+
+    offset += domain_size;
+  }
+}
+
+static void join_attributes(Span<const GeometryComponent *> src_components,
+                            GeometryComponent &result)
+{
+  Set<std::string> attribute_names = find_all_attribute_names(src_components);
+
+  for (const std::string &attribute_name : attribute_names) {
+    CustomDataType data_type;
+    AttributeDomain domain;
+    determine_final_data_type_and_domain(src_components, attribute_name, &data_type, &domain);
+
+    result.attribute_try_create(attribute_name, domain, data_type);
+    WriteAttributePtr write_attribute = result.attribute_try_get_for_write(attribute_name);
+    if (!write_attribute ||
+        &write_attribute->cpp_type() != bke::custom_data_type_to_cpp_type(data_type) ||
+        write_attribute->domain() != domain) {
+      continue;
+    }
+    fill_new_attribute(src_components, attribute_name, data_type, domain, write_attribute);
+  }
+}
+
+static void join_components(Span<const MeshComponent *> src_components, GeometrySet &result)
+{
+  Mesh *new_mesh = join_mesh_topologies(src_components);
+
+  MeshComponent &dst_component = result.get_component_for_write<MeshComponent>();
+  dst_component.replace(new_mesh);
+
+  join_attributes(to_base_components(src_components), dst_component);
+}
+
+static void join_comp

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list