[Bf-blender-cvs] [8d7e8c04469] temp-geometry-nodes-instances-api-v2: Add implicit make instances real operation for "write" nodes

Hans Goudey noreply at git.blender.org
Sat Feb 6 00:56:21 CET 2021


Commit: 8d7e8c04469059597d87db7d8a602ae4e62e8a65
Author: Hans Goudey
Date:   Fri Feb 5 17:56:04 2021 -0600
Branches: temp-geometry-nodes-instances-api-v2
https://developer.blender.org/rB8d7e8c04469059597d87db7d8a602ae4e62e8a65

Add implicit make instances real operation for "write" nodes

Other nodes that create new geometry instead of modifying existing geometry
should read the geometry like the point distribute node does in this branch.

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

M	source/blender/blenkernel/intern/geometry_set.cc
M	source/blender/nodes/geometry/node_geometry_util.cc
M	source/blender/nodes/geometry/node_geometry_util.hh
M	source/blender/nodes/geometry/nodes/node_geo_align_rotation_to_vector.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_color_ramp.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_compare.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_fill.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_math.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_mix.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_proximity.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_randomize.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_sample_texture.cc
M	source/blender/nodes/geometry/nodes/node_geo_attribute_vector_math.cc
M	source/blender/nodes/geometry/nodes/node_geo_edge_split.cc
M	source/blender/nodes/geometry/nodes/node_geo_point_distribute.cc
M	source/blender/nodes/geometry/nodes/node_geo_point_rotate.cc
M	source/blender/nodes/geometry/nodes/node_geo_point_scale.cc
M	source/blender/nodes/geometry/nodes/node_geo_point_translate.cc
M	source/blender/nodes/geometry/nodes/node_geo_subdivision_surface.cc
M	source/blender/nodes/geometry/nodes/node_geo_triangulate.cc

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

diff --git a/source/blender/blenkernel/intern/geometry_set.cc b/source/blender/blenkernel/intern/geometry_set.cc
index f1f156de531..351bfa3c6dc 100644
--- a/source/blender/blenkernel/intern/geometry_set.cc
+++ b/source/blender/blenkernel/intern/geometry_set.cc
@@ -15,7 +15,10 @@
  */
 
 #include "BLI_listbase_wrapper.hh" /* TODO: Couldn't figure this out yet. */
+#include "BLI_map.hh"
 
+#include "BKE_attribute.h"
+#include "BKE_attribute_access.hh"
 #include "BKE_geometry_set.hh"
 #include "BKE_lib_id.h"
 #include "BKE_mesh.h"
@@ -32,6 +35,7 @@
 using blender::float3;
 using blender::float4x4;
 using blender::ListBaseWrapper;
+using blender::Map;
 using blender::MutableSpan;
 using blender::Span;
 using blender::StringRef;
@@ -730,18 +734,19 @@ static void collect_geometry_set_recursive(const GeometrySet &geometry_set,
     Span<InstancedData> instances = instances_component.instanced_data();
     for (const int i : instances.index_range()) {
       const InstancedData &data = instances[i];
-      const float4x4 &transform = transforms[i];
+      const float4x4 &instance_transform = transforms[i];
 
       if (data.type == INSTANCE_DATA_TYPE_OBJECT) {
         BLI_assert(data.data.object != nullptr);
         const Object &object = *data.data.object;
+        const float4x4 object_transform = transform * instance_transform * object.obmat;
         GeometrySet instance_geometry_set = object_get_geometry_set_for_read(object);
-        collect_geometry_set_recursive(instance_geometry_set, transform, r_sets);
+        collect_geometry_set_recursive(instance_geometry_set, object_transform, r_sets);
       }
       else if (data.type == INSTANCE_DATA_TYPE_COLLECTION) {
         BLI_assert(data.data.collection != nullptr);
         const Collection &collection = *data.data.collection;
-        collect_collection_geometry_set_recursive(collection, transform, r_sets);
+        collect_collection_geometry_set_recursive(collection, instance_transform, r_sets);
       }
     }
   }
diff --git a/source/blender/nodes/geometry/node_geometry_util.cc b/source/blender/nodes/geometry/node_geometry_util.cc
index daaccf4450b..5b3da930abb 100644
--- a/source/blender/nodes/geometry/node_geometry_util.cc
+++ b/source/blender/nodes/geometry/node_geometry_util.cc
@@ -17,8 +17,239 @@
 #include "node_geometry_util.hh"
 #include "node_util.h"
 
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BKE_mesh.h"
+#include "BKE_mesh_runtime.h"
+#include "BKE_pointcloud.h"
+
 namespace blender::nodes {
 
+template<typename Component>
+Map<std::string, AttributeInfo> gather_attribute_info(Span<GeometryInstanceGroup> geometry_sets)
+{
+  Map<std::string, AttributeInfo> attribute_info;
+  for (const GeometryInstanceGroup &set_group : geometry_sets) {
+    const GeometrySet &set = set_group.geometry_set;
+    if (set.has<Component>()) {
+      const Component &component = *set.get_component_for_read<Component>();
+      for (const std::string &name : component.attribute_names()) {
+        ReadAttributePtr attribute = component.attribute_try_get_for_read(name);
+        BLI_assert(attribute);
+        const CustomDataType data_type = attribute->custom_data_type();
+        const AttributeDomain domain = attribute->domain();
+        if (attribute_info.contains(name)) {
+          AttributeInfo &info = attribute_info.lookup(name);
+          info.data_type = attribute_data_type_highest_complexity({info.data_type, data_type});
+          info.domain = domain; /* TODO: Use domain priority. */
+        }
+        else {
+          attribute_info.add(name, {data_type});
+        }
+      }
+    }
+  }
+  return attribute_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];
+
+          const float3 new_position = transform * float3(old_vert.co);
+          copy_v3_v3(new_vert.co, new_position);
+
+          new_vert = old_vert;
+        }
+        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;
+}
+
+template<typename Component>
+static void join_attributes(Span<GeometryInstanceGroup> set_groups,
+                            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>()) {
+        const GeometryComponent &component = *set.get_component_for_read<Component>();
+        const int domain_size = component.attribute_domain_size(domain_output);
+        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_components_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<MeshComponent>(set_groups);
+  attributes.remove("position");
+  join_attributes<MeshComponent>(
+      set_groups, attributes, static_cast<GeometryComponent &>(dst_component));
+}
+
+static void join_components_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 PointCloudComponent &component = *set.get_component_for_read<PointCloudComponent>();
+      totpoint += component.attribute_domain_size(ATTR_DOMAIN_POINT);
+    }
+  }
+
+  PointCloudComponent &dst_component = result.get_component_for_write<PointCloudCompon

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list