[Bf-blender-cvs] [5688f791f51] master: Geometry Nodes: move realize-instances code to blenkernel

Jacques Lucke noreply at git.blender.org
Tue Feb 16 12:31:27 CET 2021


Commit: 5688f791f51827d77f4479bee90c4e88add72ce6
Author: Jacques Lucke
Date:   Tue Feb 16 12:30:42 2021 +0100
Branches: master
https://developer.blender.org/rB5688f791f51827d77f4479bee90c4e88add72ce6

Geometry Nodes: move realize-instances code to blenkernel

I need to access this functionality from modifier code. Therefore it should
not be in the nodes module.

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

M	source/blender/blenkernel/BKE_geometry_set_instances.hh
M	source/blender/blenkernel/intern/geometry_set_instances.cc
M	source/blender/nodes/NOD_geometry_exec.hh
M	source/blender/nodes/geometry/node_geometry_util.cc
M	source/blender/nodes/geometry/node_geometry_util.hh

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

diff --git a/source/blender/blenkernel/BKE_geometry_set_instances.hh b/source/blender/blenkernel/BKE_geometry_set_instances.hh
index 11725d75df9..4f3c9c65203 100644
--- a/source/blender/blenkernel/BKE_geometry_set_instances.hh
+++ b/source/blender/blenkernel/BKE_geometry_set_instances.hh
@@ -14,6 +14,8 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
+#pragma once
+
 #include "BKE_geometry_set.hh"
 
 namespace blender::bke {
@@ -39,4 +41,21 @@ struct GeometryInstanceGroup {
 
 Vector<GeometryInstanceGroup> geometry_set_gather_instances(const GeometrySet &geometry_set);
 
+GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set);
+
+struct AttributeInfo {
+  CustomDataType data_type;
+  AttributeDomain domain;
+};
+
+/**
+ * Add information about all the attributes on every component of the type. The resulting info
+ * will contain the highest complexity data type and the highest priority domain among every
+ * attribute with the given name on all of the input components.
+ */
+void gather_attribute_info(Map<std::string, AttributeInfo> &attributes,
+                           const GeometryComponentType component_type,
+                           Span<bke::GeometryInstanceGroup> set_groups,
+                           const Set<std::string> &ignored_attributes);
+
 }  // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/geometry_set_instances.cc b/source/blender/blenkernel/intern/geometry_set_instances.cc
index 6410aeb49fa..8e9edc86bca 100644
--- a/source/blender/blenkernel/intern/geometry_set_instances.cc
+++ b/source/blender/blenkernel/intern/geometry_set_instances.cc
@@ -15,10 +15,14 @@
  */
 
 #include "BKE_geometry_set_instances.hh"
+#include "BKE_mesh.h"
 #include "BKE_mesh_wrapper.h"
 #include "BKE_modifier.h"
+#include "BKE_pointcloud.h"
 
 #include "DNA_collection_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
 #include "DNA_object_types.h"
 
 namespace blender::bke {
@@ -160,4 +164,247 @@ Vector<GeometryInstanceGroup> geometry_set_gather_instances(const GeometrySet &g
   return result_vector;
 }
 
+void gather_attribute_info(Map<std::string, AttributeInfo> &attributes,
+                           const GeometryComponentType component_type,
+                           Span<GeometryInstanceGroup> set_groups,
+                           const Set<std::string> &ignored_attributes)
+{
+  for (const GeometryInstanceGroup &set_group : set_groups) {
+    const GeometrySet &set = set_group.geometry_set;
+    if (!set.has(component_type)) {
+      continue;
+    }
+    const GeometryComponent &component = *set.get_component_for_read(component_type);
+
+    for (const std::string &name : component.attribute_names()) {
+      if (ignored_attributes.contains(name)) {
+        continue;
+      }
+      const ReadAttributePtr read_attribute = component.attribute_try_get_for_read(name);
+      if (!read_attribute) {
+        continue;
+      }
+      const AttributeDomain domain = read_attribute->domain();
+      const CustomDataType data_type = read_attribute->custom_data_type();
+
+      auto add_info = [&, data_type, domain](AttributeInfo *info) {
+        info->domain = domain;
+        info->data_type = data_type;
+      };
+      auto modify_info = [&, data_type, domain](AttributeInfo *info) {
+        info->domain = domain; /* TODO: Use highest priority domain. */
+        info->data_type = bke::attribute_data_type_highest_complexity(
+            {info->data_type, data_type});
+      };
+
+      attributes.add_or_modify(name, add_info, modify_info);
+    }
+  }
+}
+
+static Mesh *join_mesh_topology_and_builtin_attributes(Span<GeometryInstanceGroup> set_groups)
+{
+  int totverts = 0;
+  int totloops = 0;
+  int totedges = 0;
+  int totpolys = 0;
+  int64_t cd_dirty_vert = 0;
+  int64_t cd_dirty_poly = 0;
+  int64_t cd_dirty_edge = 0;
+  int64_t cd_dirty_loop = 0;
+  for (const GeometryInstanceGroup &set_group : set_groups) {
+    const GeometrySet &set = set_group.geometry_set;
+    if (set.has_mesh()) {
+      const Mesh &mesh = *set.get_mesh_for_read();
+      totverts += mesh.totvert * set_group.transforms.size();
+      totloops += mesh.totloop * set_group.transforms.size();
+      totedges += mesh.totedge * set_group.transforms.size();
+      totpolys += mesh.totpoly * set_group.transforms.size();
+      cd_dirty_vert |= mesh.runtime.cd_dirty_vert;
+      cd_dirty_poly |= mesh.runtime.cd_dirty_poly;
+      cd_dirty_edge |= mesh.runtime.cd_dirty_edge;
+      cd_dirty_loop |= mesh.runtime.cd_dirty_loop;
+    }
+  }
+
+  Mesh *new_mesh = BKE_mesh_new_nomain(totverts, totedges, 0, totloops, totpolys);
+  /* Copy settings from the first input geometry set with a mesh. */
+  for (const GeometryInstanceGroup &set_group : set_groups) {
+    const GeometrySet &set = set_group.geometry_set;
+    if (set.has_mesh()) {
+      const Mesh &mesh = *set.get_mesh_for_read();
+      BKE_mesh_copy_settings(new_mesh, &mesh);
+      break;
+    }
+  }
+  new_mesh->runtime.cd_dirty_vert = cd_dirty_vert;
+  new_mesh->runtime.cd_dirty_poly = cd_dirty_poly;
+  new_mesh->runtime.cd_dirty_edge = cd_dirty_edge;
+  new_mesh->runtime.cd_dirty_loop = cd_dirty_loop;
+
+  int vert_offset = 0;
+  int loop_offset = 0;
+  int edge_offset = 0;
+  int poly_offset = 0;
+  for (const GeometryInstanceGroup &set_group : set_groups) {
+    const GeometrySet &set = set_group.geometry_set;
+    if (set.has_mesh()) {
+      const Mesh &mesh = *set.get_mesh_for_read();
+      for (const float4x4 &transform : set_group.transforms) {
+        for (const int i : IndexRange(mesh.totvert)) {
+          const MVert &old_vert = mesh.mvert[i];
+          MVert &new_vert = new_mesh->mvert[vert_offset + i];
+
+          new_vert = old_vert;
+
+          const float3 new_position = transform * float3(old_vert.co);
+          copy_v3_v3(new_vert.co, new_position);
+        }
+        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 = old_edge;
+          new_edge.v1 += vert_offset;
+          new_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 = old_loop;
+          new_loop.v += vert_offset;
+          new_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 = old_poly;
+          new_poly.loopstart += loop_offset;
+        }
+
+        vert_offset += mesh.totvert;
+        loop_offset += mesh.totloop;
+        edge_offset += mesh.totedge;
+        poly_offset += mesh.totpoly;
+      }
+    }
+  }
+
+  return new_mesh;
+}
+
+static void join_attributes(Span<GeometryInstanceGroup> set_groups,
+                            const GeometryComponentType component_type,
+                            const Map<std::string, AttributeInfo> &attribute_info,
+                            GeometryComponent &result)
+{
+  for (Map<std::string, AttributeInfo>::Item entry : attribute_info.items()) {
+    StringRef name = entry.key;
+    const AttributeDomain domain_output = entry.value.domain;
+    const CustomDataType data_type_output = entry.value.data_type;
+    const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(data_type_output);
+    BLI_assert(cpp_type != nullptr);
+
+    result.attribute_try_create(entry.key, domain_output, data_type_output);
+    WriteAttributePtr write_attribute = result.attribute_try_get_for_write(name);
+    if (!write_attribute || &write_attribute->cpp_type() != cpp_type ||
+        write_attribute->domain() != domain_output) {
+      continue;
+    }
+    fn::GMutableSpan dst_span = write_attribute->get_span_for_write_only();
+
+    int offset = 0;
+    for (const GeometryInstanceGroup &set_group : set_groups) {
+      const GeometrySet &set = set_group.geometry_set;
+      if (set.has(component_type)) {
+        const GeometryComponent &component = *set.get_component_for_read(component_type);
+        const int domain_size = component.attribute_domain_size(domain_output);
+        if (domain_size == 0) {
+          continue; /* Domain size is 0, so no need to increment the offset. */
+        }
+        ReadAttributePtr source_attribute = component.attribute_try_get_for_read(
+            name, domain_output, data_type_output);
+
+        if (source_attribute) {
+          fn::GSpan src_span = source_attribute->get_span();
+          const void *src_buffer = src_span.data();
+          for (const int UNUSED(i) : set_group.transforms.index_range()) {
+            void *dst_buffer = dst_span[offset];
+            cpp_type->copy_to_initialized_n(src_buffer, dst_buffer, domain_size);
+            offset += domain_size;
+          }
+        }
+        else {
+          offset += domain_size * set_group.transforms.size();
+        }
+      }
+    }
+
+    write_attribute->apply_span();
+  }
+}
+
+static void join_instance_groups_mesh(Span<GeometryInstanceGroup> set_groups, GeometrySet &result)
+{
+  Mesh *new_mesh = join_mesh_topology_and_builtin_attributes(set_groups);
+
+  MeshComponent &dst_component = result.get_component_for_write<MeshComponent>();
+  dst_component.replace(new_mesh);
+
+  /* The position attribute is handled above already. */
+  Map<std::string, AttributeInfo> attributes;
+  gather_attribute_info(attributes, GeometryComponentType::Mesh, set_groups, {"position"});
+  join_attributes(set_groups,
+                  GeometryComponentType::Mesh,
+                  attributes,
+                  static_cast<GeometryComponent &>(dst_component));
+}
+
+static void join_instance_groups_pointcloud(Span<GeometryInstanceGroup> set_groups,
+                                            GeometrySet &result)
+{
+  int totpoint = 0;
+  for (const GeometryInstanceGroup &set_group : set_groups) {
+    const GeometrySet &set = set_group.geometry_set;
+    if (set.has<PointCloudComponent>()) {
+      const PointCloudCo

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list