[Bf-blender-cvs] [42d0360d923] soc-2021-curve-fillet: Refactored FilletData calculation

dilithjay noreply at git.blender.org
Thu Aug 12 20:19:51 CEST 2021


Commit: 42d0360d923568a8004250441f5f0fbec9855f8b
Author: dilithjay
Date:   Thu Aug 12 15:13:59 2021 +0530
Branches: soc-2021-curve-fillet
https://developer.blender.org/rB42d0360d923568a8004250441f5f0fbec9855f8b

Refactored FilletData calculation

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

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

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

diff --git a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
index 5e4765e2545..47decf12bd2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
@@ -85,7 +85,8 @@ struct FilletModeParam {
 /* A data structure used to store fillet data about all vertices to be filleted. */
 struct FilletData {
   Array<float3> prev_dirs, positions, next_dirs, axes;
-  Array<float> radii, angles, counts;
+  Array<float> radii, angles;
+  Array<int> counts;
 
   FilletData(const int size)
   {
@@ -144,27 +145,101 @@ static float3 get_center(const float3 vec_pos2prev, const FilletData &fd, const
   return get_center(vec_pos2prev, pos, axis, angle);
 }
 
-/* Function to calculate fillet data for the specified index. */
-static FilletData calculate_fillet_data_per_vertex(FilletData &fd,
-                                                   const float3 prev_pos,
-                                                   const float3 pos,
-                                                   const float3 next_pos,
-                                                   const std::optional<float> arc_angle,
-                                                   const std::optional<int> count,
-                                                   const float radius,
-                                                   const int index)
+/* Calculate the directions to the previous vertices from each filleted vertex. */
+static Array<float3> calculate_prev_directions(const Span<float3> positions,
+                                               const bool cyclic,
+                                               const int fillet_count)
 {
-  float3 vec_pos2prev = prev_pos - pos;
-  float3 vec_pos2next = next_pos - pos;
-  fd.prev_dirs[index] = vec_pos2prev.normalized();
-  fd.next_dirs[index] = vec_pos2next.normalized();
-  fd.positions[index] = pos;
-  fd.axes[index] = float3::cross(vec_pos2prev, vec_pos2next);
-  fd.angles[index] = M_PI - angle_v3v3v3(prev_pos, pos, next_pos);
-  fd.counts[index] = count.has_value() ? count.value() : fd.angles[index] / arc_angle.value();
-  fd.radii[index] = radius;
+  Array<float3> prev_dirs(fillet_count);
+  const int size = positions.size();
+  const int start = cyclic ? 0 : 1;
 
-  return fd;
+  for (const int i : IndexRange(start, fillet_count)) {
+    const bool wrap_around = cyclic && i == 0;
+    prev_dirs[i - start] = (positions[wrap_around ? size - 1 : i - 1] - positions[i]).normalized();
+  }
+
+  return prev_dirs;
+}
+
+/* Calculate the directions to the next vertices from each filleted vertex. */
+static Array<float3> calculate_next_directions(const Span<float3> positions,
+                                               const bool cyclic,
+                                               const int fillet_count)
+{
+  Array<float3> next_dirs(fillet_count);
+  const int size = positions.size();
+  const int start = cyclic ? 0 : 1;
+
+  for (const int i : IndexRange(start, fillet_count)) {
+    const bool wrap_around = cyclic && i == size - 1;
+    next_dirs[i - start] = (positions[wrap_around ? 0 : i + 1] - positions[i]).normalized();
+  }
+
+  return next_dirs;
+}
+
+/* Calculate the axes around which the fillet is built. */
+static Array<float3> calculate_axes(const Span<float3> prev_dirs,
+                                    const Span<float3> next_dirs,
+                                    const int fillet_count)
+{
+  Array<float3> axes(fillet_count);
+
+  for (const int i : IndexRange(fillet_count)) {
+    axes[i] = float3::cross(prev_dirs[i], next_dirs[i]);
+  }
+
+  return axes;
+}
+
+/* Calculate the angle of the arc formed by the fillet. */
+static Array<float> calculate_angles(const Span<float3> prev_dirs,
+                                     const Span<float3> next_dirs,
+                                     const int fillet_count)
+{
+  Array<float> angles(fillet_count);
+
+  for (const int i : IndexRange(fillet_count)) {
+    angles[i] = M_PI - angle_v3v3(prev_dirs[i], next_dirs[i]);
+  }
+
+  return angles;
+}
+
+/* Calculate the segment count in each filleted arc. */
+static Array<int> calculate_counts(const std::optional<float> arc_angle,
+                                   const std::optional<int> count,
+                                   const Span<float> angles,
+                                   const int fillet_count)
+{
+  Array<int> counts(fillet_count);
+
+  for (const int i : IndexRange(fillet_count)) {
+    counts[i] = count.has_value() ? count.value() : ceil(angles[i] / arc_angle.value());
+  }
+
+  return counts;
+}
+
+/* Calculate the radii for the vertices to be filleted. */
+static Array<float> calculate_radii(const FilletModeParam &mode_param,
+                                    const int spline_index,
+                                    const int fillet_count)
+{
+  Array<float> radii(fillet_count, 0.0f);
+
+  for (const int i : IndexRange(fillet_count)) {
+    if (mode_param.radius_mode == GEO_NODE_CURVE_FILLET_RADIUS_FLOAT) {
+      radii[i] = mode_param.radius.value();
+    }
+    else if (mode_param.radius_mode == GEO_NODE_CURVE_FILLET_RADIUS_ATTRIBUTE &&
+             spline_index + i < mode_param.radii->size()) {
+      radii[i] = (*mode_param.radii)[spline_index + i];
+    }
+  }
+
+  return radii;
 }
 
 /* Limit the radius based on angle and radii to prevent overlap. */
@@ -241,6 +316,24 @@ static void limit_radii(FilletData &fd, const Span<float3> spline_positions, con
   }
 }
 
+static int calculate_point_counts(MutableSpan<int> point_counts,
+                                  const Span<float> radii,
+                                  const Span<int> counts,
+                                  const int fillet_count,
+                                  const int start)
+{
+  int added_count = 0;
+  for (const int i : IndexRange(fillet_count)) {
+    /* Calculate number of points to be added for the vertex. */
+    if (radii[i] != 0.0f) {
+      added_count += counts[i];
+      point_counts[i + start] = counts[i] + 1;
+    }
+  }
+
+  return added_count;
+}
+
 /* Function to calculate and obtain the fillet data for the entire spline. */
 static FilletData calculate_fillet_data(const Spline &spline,
                                         const FilletModeParam &mode_param,
@@ -262,52 +355,15 @@ static FilletData calculate_fillet_data(const Spline &spline,
   }
 
   FilletData fd(fillet_count);
-
-  for (const int i : IndexRange(start, fillet_count)) {
-    /* Find the positions of the adjacent vertices. */
-    float3 prev_pos, pos, next_pos;
-    if (cyclic) {
-      prev_pos = spline.positions()[i == 0 ? spline.size() - 1 : i - 1];
-      pos = spline.positions()[i];
-      next_pos = spline.positions()[i == spline.size() - 1 ? 0 : i + 1];
-    }
-    else {
-      prev_pos = spline.positions()[i - 1];
-      pos = spline.positions()[i];
-      next_pos = spline.positions()[i + 1];
-    }
-
-    /* Define the radius. */
-    float radius = 0.0f;
-    if (mode_param.radius_mode == GEO_NODE_CURVE_FILLET_RADIUS_FLOAT) {
-      radius = mode_param.radius.value();
-    }
-    else if (mode_param.radius_mode == GEO_NODE_CURVE_FILLET_RADIUS_ATTRIBUTE &&
-             spline_index + i < mode_param.radii->size()) {
-      radius = (*mode_param.radii)[spline_index + i];
-    }
-
-    /* Calculate fillet data for the vertex. */
-    calculate_fillet_data_per_vertex(
-        fd, prev_pos, pos, next_pos, mode_param.angle, mode_param.count, radius, i - start);
-
-    /* Exit from here if the radius is zero */
-    if (radius == 0.0f) {
-      continue;
-    }
-
-    /* Calculate number of points to be added for the vertex. */
-    int count = 0;
-    if (mode_param.mode == GEO_NODE_CURVE_FILLET_ADAPTIVE) {
-      count = ceil(fd.angles[i - start] / mode_param.angle.value());
-    }
-    else if (mode_param.mode == GEO_NODE_CURVE_FILLET_USER_DEFINED) {
-      count = mode_param.count.value();
-    }
-
-    added_count += count;
-    point_counts[i] = count + 1;
-  }
+  fd.prev_dirs = calculate_prev_directions(spline.positions(), spline.is_cyclic(), fillet_count);
+  fd.next_dirs = calculate_next_directions(spline.positions(), spline.is_cyclic(), fillet_count);
+  fd.positions = spline.positions().slice(IndexRange(start, fillet_count));
+  fd.axes = calculate_axes(fd.prev_dirs, fd.next_dirs, fillet_count);
+  fd.angles = calculate_angles(fd.prev_dirs, fd.next_dirs, fillet_count);
+  fd.counts = calculate_counts(mode_param.angle, mode_param.count, fd.angles, fillet_count);
+  fd.radii = calculate_radii(mode_param, spline_index, fillet_count);
+
+  added_count = calculate_point_counts(point_counts, fd.radii, fd.counts, fillet_count, start);
 
   return fd;
 }



More information about the Bf-blender-cvs mailing list