[Bf-blender-cvs] [f81bacd6f0f] master: Geometry Nodes: Transfer attributes in the curve to mesh node

Hans Goudey noreply at git.blender.org
Thu Sep 16 19:26:14 CEST 2021


Commit: f81bacd6f0fc8d9afb46570e1a66c4469185d8a5
Author: Hans Goudey
Date:   Thu Sep 16 12:25:26 2021 -0500
Branches: master
https://developer.blender.org/rBf81bacd6f0fc8d9afb46570e1a66c4469185d8a5

Geometry Nodes: Transfer attributes in the curve to mesh node

This patch allows point and spline attributes to be transferred to the
mesh generated by the curve to mesh node. All dynamic named and
anonymous attributes are transferred. So a user-created attribute will
be transferred, but "radius", "tilt" or the handle position attributes
won't be transferred by default and will need to be copied first.
This trade-off is made for performance, since most of the time, users
won't need these attributes copied.

Generally, attributes are transferred to the point/vertex domain.
However, if they have the same name as a built-in mesh attribute that
only exists on a different domain, like "shade_smooth", then they can
be transferred directly to that domain as well. Conversion directly to
the face corner domain is not necessary because there are no builtin
face corner attributes. I see this conversion directly to other domains
as an optimization we could use behind the scenes in the future as well,
when named attributes are less common.

For performance, I haven't tested which of the following is better:
```
for each spline combination:
    for each attribute:

for each attribute:
    for each spline combination:
```
For now I used the existing loop to avoid more threading overhead.

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

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

M	source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc

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

diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
index 2eae11d1705..f46440fd949 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_to_mesh.cc
@@ -39,6 +39,20 @@ static void geo_node_curve_to_mesh_declare(NodeDeclarationBuilder &b)
   b.add_output<decl::Geometry>("Mesh");
 }
 
+/** Information about the creation of one curve spline and profile spline combination. */
+struct ResultInfo {
+  const Spline &spline;
+  const Spline &profile;
+  int vert_offset;
+  int edge_offset;
+  int loop_offset;
+  int poly_offset;
+  int spline_vert_len;
+  int spline_edge_len;
+  int profile_vert_len;
+  int profile_edge_len;
+};
+
 static void vert_extrude_to_mesh_data(const Spline &spline,
                                       const float3 profile_vert,
                                       MutableSpan<MVert> r_verts,
@@ -75,44 +89,33 @@ static void mark_edges_sharp(MutableSpan<MEdge> edges)
   }
 }
 
-static void spline_extrude_to_mesh_data(const Spline &spline,
-                                        const Spline &profile_spline,
-                                        const int vert_offset,
-                                        const int edge_offset,
-                                        const int loop_offset,
-                                        const int poly_offset,
+static void spline_extrude_to_mesh_data(const ResultInfo &info,
                                         MutableSpan<MVert> r_verts,
                                         MutableSpan<MEdge> r_edges,
                                         MutableSpan<MLoop> r_loops,
                                         MutableSpan<MPoly> r_polys)
 {
-  const int spline_vert_len = spline.evaluated_points_size();
-  const int spline_edge_len = spline.evaluated_edges_size();
-  const int profile_vert_len = profile_spline.evaluated_points_size();
-  const int profile_edge_len = profile_spline.evaluated_edges_size();
-  if (spline_vert_len == 0) {
-    return;
-  }
-
-  if (profile_vert_len == 1) {
+  const Spline &spline = info.spline;
+  const Spline &profile = info.profile;
+  if (info.profile_vert_len == 1) {
     vert_extrude_to_mesh_data(spline,
-                              profile_spline.evaluated_positions()[0],
+                              profile.evaluated_positions()[0],
                               r_verts,
                               r_edges,
-                              vert_offset,
-                              edge_offset);
+                              info.vert_offset,
+                              info.edge_offset);
     return;
   }
 
   /* Add the edges running along the length of the curve, starting at each profile vertex. */
-  const int spline_edges_start = edge_offset;
-  for (const int i_profile : IndexRange(profile_vert_len)) {
-    const int profile_edge_offset = spline_edges_start + i_profile * spline_edge_len;
-    for (const int i_ring : IndexRange(spline_edge_len)) {
-      const int i_next_ring = (i_ring == spline_vert_len - 1) ? 0 : i_ring + 1;
+  const int spline_edges_start = info.edge_offset;
+  for (const int i_profile : IndexRange(info.profile_vert_len)) {
+    const int profile_edge_offset = spline_edges_start + i_profile * info.spline_edge_len;
+    for (const int i_ring : IndexRange(info.spline_edge_len)) {
+      const int i_next_ring = (i_ring == info.spline_vert_len - 1) ? 0 : i_ring + 1;
 
-      const int ring_vert_offset = vert_offset + profile_vert_len * i_ring;
-      const int next_ring_vert_offset = vert_offset + profile_vert_len * i_next_ring;
+      const int ring_vert_offset = info.vert_offset + info.profile_vert_len * i_ring;
+      const int next_ring_vert_offset = info.vert_offset + info.profile_vert_len * i_next_ring;
 
       MEdge &edge = r_edges[profile_edge_offset + i_ring];
       edge.v1 = ring_vert_offset + i_profile;
@@ -122,13 +125,14 @@ static void spline_extrude_to_mesh_data(const Spline &spline,
   }
 
   /* Add the edges running along each profile ring. */
-  const int profile_edges_start = spline_edges_start + profile_vert_len * spline_edge_len;
-  for (const int i_ring : IndexRange(spline_vert_len)) {
-    const int ring_vert_offset = vert_offset + profile_vert_len * i_ring;
+  const int profile_edges_start = spline_edges_start +
+                                  info.profile_vert_len * info.spline_edge_len;
+  for (const int i_ring : IndexRange(info.spline_vert_len)) {
+    const int ring_vert_offset = info.vert_offset + info.profile_vert_len * i_ring;
 
-    const int ring_edge_offset = profile_edges_start + i_ring * profile_edge_len;
-    for (const int i_profile : IndexRange(profile_edge_len)) {
-      const int i_next_profile = (i_profile == profile_vert_len - 1) ? 0 : i_profile + 1;
+    const int ring_edge_offset = profile_edges_start + i_ring * info.profile_edge_len;
+    for (const int i_profile : IndexRange(info.profile_edge_len)) {
+      const int i_next_profile = (i_profile == info.profile_vert_len - 1) ? 0 : i_profile + 1;
 
       MEdge &edge = r_edges[ring_edge_offset + i_profile];
       edge.v1 = ring_vert_offset + i_profile;
@@ -138,24 +142,25 @@ static void spline_extrude_to_mesh_data(const Spline &spline,
   }
 
   /* Calculate poly and corner indices. */
-  for (const int i_ring : IndexRange(spline_edge_len)) {
-    const int i_next_ring = (i_ring == spline_vert_len - 1) ? 0 : i_ring + 1;
+  for (const int i_ring : IndexRange(info.spline_edge_len)) {
+    const int i_next_ring = (i_ring == info.spline_vert_len - 1) ? 0 : i_ring + 1;
 
-    const int ring_vert_offset = vert_offset + profile_vert_len * i_ring;
-    const int next_ring_vert_offset = vert_offset + profile_vert_len * i_next_ring;
+    const int ring_vert_offset = info.vert_offset + info.profile_vert_len * i_ring;
+    const int next_ring_vert_offset = info.vert_offset + info.profile_vert_len * i_next_ring;
 
-    const int ring_edge_start = profile_edges_start + profile_edge_len * i_ring;
-    const int next_ring_edge_offset = profile_edges_start + profile_edge_len * i_next_ring;
+    const int ring_edge_start = profile_edges_start + info.profile_edge_len * i_ring;
+    const int next_ring_edge_offset = profile_edges_start + info.profile_edge_len * i_next_ring;
 
-    const int ring_poly_offset = poly_offset + i_ring * profile_edge_len;
-    const int ring_loop_offset = loop_offset + i_ring * profile_edge_len * 4;
+    const int ring_poly_offset = info.poly_offset + i_ring * info.profile_edge_len;
+    const int ring_loop_offset = info.loop_offset + i_ring * info.profile_edge_len * 4;
 
-    for (const int i_profile : IndexRange(profile_edge_len)) {
+    for (const int i_profile : IndexRange(info.profile_edge_len)) {
       const int ring_segment_loop_offset = ring_loop_offset + i_profile * 4;
-      const int i_next_profile = (i_profile == profile_vert_len - 1) ? 0 : i_profile + 1;
+      const int i_next_profile = (i_profile == info.profile_vert_len - 1) ? 0 : i_profile + 1;
 
-      const int spline_edge_start = spline_edges_start + spline_edge_len * i_profile;
-      const int next_spline_edge_start = spline_edges_start + spline_edge_len * i_next_profile;
+      const int spline_edge_start = spline_edges_start + info.spline_edge_len * i_profile;
+      const int next_spline_edge_start = spline_edges_start +
+                                         info.spline_edge_len * i_next_profile;
 
       MPoly &poly = r_polys[ring_poly_offset + i_profile];
       poly.loopstart = ring_segment_loop_offset;
@@ -181,29 +186,30 @@ static void spline_extrude_to_mesh_data(const Spline &spline,
   Span<float3> positions = spline.evaluated_positions();
   Span<float3> tangents = spline.evaluated_tangents();
   Span<float3> normals = spline.evaluated_normals();
-  Span<float3> profile_positions = profile_spline.evaluated_positions();
+  Span<float3> profile_positions = profile.evaluated_positions();
 
   GVArray_Typed<float> radii = spline.interpolate_to_evaluated(spline.radii());
-  for (const int i_ring : IndexRange(spline_vert_len)) {
+  for (const int i_ring : IndexRange(info.spline_vert_len)) {
     float4x4 point_matrix = float4x4::from_normalized_axis_data(
         positions[i_ring], normals[i_ring], tangents[i_ring]);
     point_matrix.apply_scale(radii[i_ring]);
 
-    const int ring_vert_start = vert_offset + i_ring * profile_vert_len;
-    for (const int i_profile : IndexRange(profile_vert_len)) {
+    const int ring_vert_start = info.vert_offset + i_ring * info.profile_vert_len;
+    for (const int i_profile : IndexRange(info.profile_vert_len)) {
       MVert &vert = r_verts[ring_vert_start + i_profile];
       copy_v3_v3(vert.co, point_matrix * profile_positions[i_profile]);
     }
   }
 
   /* Mark edge loops from sharp vector control points sharp. */
-  if (profile_spline.type() == Spline::Type::Bezier) {
-    const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(profile_spline);
+  if (profile.type() == Spline::Type::Bezier) {
+    const BezierSpline &bezier_spline = static_cast<const BezierSpline &>(profile);
     Span<int> control_point_offsets = bezier_spline.control_point_offsets();
     for (const int i : IndexRange(bezier_spline.size())) {
       if (bezier_spline.point_is_sharp(i)) {
-        mark_edges_sharp(r_edges.slice(
-            spline_edges_start + spline_edge_len * control_point_offsets[i], spline_edge_len));
+        mark_edges_sharp(
+            r_edges.slice(spline_edges_start + info.spline_edge_len * control_point_offsets[i],
+                          info.spline_edge_len));
       }
     }
   }
@@ -272,6 +278,372 @@ static ResultOffsets calculate_result_offsets(Span<SplinePtr> profiles, Span<Spl
   return {std::move(vert), std::move(edge), std::move(loop), std::move(poly)};
 }
 
+static AttributeDomain get_result_attribute_domain(const MeshComponent &component,
+                                                   const AttributeIDRef &attribute_id)
+{
+  /* Only use a different domain if it is builtin and must only exist on one domain. */
+  if (!component.attribute_is_builtin(attribute_id)) {
+    return ATTR

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list