[Bf-blender-cvs] [49048ce946e] soc-2021-curve-fillet: Added option to avoid overlap of curve fillet

dilithjay noreply at git.blender.org
Fri Jul 30 08:36:20 CEST 2021


Commit: 49048ce946e1856d38e62186bfe065773339620c
Author: dilithjay
Date:   Fri Jul 30 12:05:32 2021 +0530
Branches: soc-2021-curve-fillet
https://developer.blender.org/rB49048ce946e1856d38e62186bfe065773339620c

Added option to avoid overlap of curve fillet

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

M	release/datafiles/locale
M	source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc

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

diff --git a/release/datafiles/locale b/release/datafiles/locale
index 62e82958a76..ca39c1459bc 160000
--- a/release/datafiles/locale
+++ b/release/datafiles/locale
@@ -1 +1 @@
-Subproject commit 62e82958a760dad775d9b3387d7fb535fd6de4c6
+Subproject commit ca39c1459bcd99300afe3591fa5ffe40f5ba5eef
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 2fb1daf4d82..e95aa25f6f2 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_fillet.cc
@@ -29,6 +29,7 @@ static bNodeSocketTemplate geo_node_curve_fillet_in[] = {
     {SOCK_GEOMETRY, N_("Curve")},
     {SOCK_FLOAT, N_("Angle"), M_PI_2, 0.0f, 0.0f, 0.0f, 0.001f, FLT_MAX, PROP_ANGLE},
     {SOCK_INT, N_("Count"), 1, 0, 0, 0, 1, 1000},
+    {SOCK_BOOLEAN, N_("Limit Radius")},
     {SOCK_FLOAT, N_("Radius"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX, PROP_DISTANCE},
     {SOCK_STRING, N_("Radii")},
     {-1, ""},
@@ -71,6 +72,9 @@ struct FilletModeParam {
 
   GeometryNodeCurveFilletRadiusMode radius_mode{};
 
+  /* Whether or not fillets are allowed to overlap. */
+  bool limit_radius;
+
   /* The radius of the formed circle */
   std::optional<float> radius;
 
@@ -83,9 +87,7 @@ struct FilletModeParam {
 /* A data structure used to store fillet data about a vertex in the source spline. */
 struct FilletData {
   float3 prev_dir, pos, next_dir, axis;
-  float radius;
-  float angle;
-  float count;
+  float radius, angle, count;
 };
 
 static void geo_node_curve_fillet_update(bNodeTree *UNUSED(ntree), bNode *node)
@@ -102,7 +104,7 @@ static void geo_node_curve_fillet_update(bNodeTree *UNUSED(ntree), bNode *node)
   const GeometryNodeCurveFilletMode radius_mode = (GeometryNodeCurveFilletMode)
                                                       node_storage.radius_mode;
 
-  bNodeSocket *float_socket = user_socket->next;
+  bNodeSocket *float_socket = user_socket->next->next;
   bNodeSocket *attribute_socket = float_socket->next;
 
   nodeSetSocketAvailability(float_socket, radius_mode == GEO_NODE_CURVE_FILLET_RADIUS_FLOAT);
@@ -139,7 +141,8 @@ static FilletData calculate_fillet_data_per_vertex(const float3 prev_pos,
                                                    const float3 next_pos,
                                                    const std::optional<float> arc_angle,
                                                    const std::optional<int> count,
-                                                   const float radius)
+                                                   const float radius,
+                                                   const bool limit_radius)
 {
   FilletData fd{};
   float3 vec_pos2prev = prev_pos - pos;
@@ -150,11 +153,78 @@ static FilletData calculate_fillet_data_per_vertex(const float3 prev_pos,
   cross_v3_v3v3(fd.axis, vec_pos2prev, vec_pos2next);
   fd.angle = M_PI - angle_v3v3v3(prev_pos, pos, next_pos);
   fd.count = count.has_value() ? count.value() : fd.angle / arc_angle.value();
-  fd.radius = radius;
+  if (limit_radius) {
+    float max_radius = min_ff(len_v3v3(pos, prev_pos), len_v3v3(pos, next_pos)) /
+                       tanf(fd.angle / 2);
+    fd.radius = min_ff(radius, max_radius);
+  }
+  else {
+    fd.radius = radius;
+  }
 
   return fd;
 }
 
+static void limit_radii(Array<FilletData> &fds, const int size, const bool cyclic)
+{
+  int fillet_count, start = 0;
+  Array<float> max_radii(size, {-1});
+
+  /* Handle the corner cases if cyclic. */
+  if (cyclic) {
+    fillet_count = size;
+
+    float len_prev, len_next, radius, radius_next, radius_prev, max_radius_prev, max_radius_next;
+
+    /* Distance to previous and next control points. */
+    len_prev = len_v3v3(fds[0].pos, fds[size - 1].pos);
+    len_next = len_v3v3(fds[0].pos, fds[1].pos);
+
+    /* Radii of adjacent control points. */
+    radius = fds[0].radius;
+    radius_next = fds[1].radius;
+    radius_prev = fds[size - 1].radius;
+
+    /* Max distance the fillet can expand to based on radii. */
+    max_radius_prev = len_prev * radius / (radius + radius_prev);
+    max_radius_next = len_next * radius / (radius + radius_next);
+
+    /* Max radius of index 0 and 1. */
+    max_radii[0] = min_ff(max_radius_prev, max_radius_next);
+    max_radii[1] = len_next * radius_next / (radius + radius_next);
+
+    /* Max radius of index size - 2 (one before the last) */
+    float len_prev_end = len_v3v3(fds[size - 2].pos, fds[size - 1].pos);
+    float radius_prev_end = fds[size - 2].radius;
+    max_radii[size - 1] = min_ff(len_prev_end * radius_prev / (radius_prev + radius_prev_end),
+                                 len_prev * radius_prev / (radius + radius_prev));
+  }
+  else {
+    fillet_count = size - 2;
+    start = 1;
+  }
+
+  /* Max radii calculations of the remaining indices. */
+  for (const int i : IndexRange(1, fillet_count - start)) {
+    float len_next = len_v3v3(fds[i - start].pos, fds[i - start + 1].pos);
+    float radius = fds[i - start].radius;
+    float radius_next = fds[i - start + 1].radius;
+    if (max_radii[i] < 0) {
+      max_radii[i] = len_next * radius / (radius + radius_next);
+    }
+    else {
+      max_radii[i] = min_ff(max_radii[i], len_next * radius / (radius + radius_next));
+    }
+    max_radii[i + 1] = len_next * radius_next / (radius + radius_next);
+  }
+
+  /* Divide each max_radius by ran of angle/2 because the current lengths are the lengths of
+   * tangents. */
+  for (const int i : IndexRange(fillet_count)) {
+    fds[i].radius = min_ff(fds[i].radius, max_radii[start + i] / tanf(fds[i].angle / 2));
+  }
+}
+
 /* Function to calculate and obtain the fillet data for the entire spline. */
 static Array<FilletData> calculate_fillet_data(const SplinePtr &spline,
                                                const FilletModeParam &mode_param,
@@ -205,8 +275,13 @@ static Array<FilletData> calculate_fillet_data(const SplinePtr &spline,
     }
 
     /* Calculate fillet data for the vertex. */
-    fds[i] = calculate_fillet_data_per_vertex(
-        prev_pos, pos, next_pos, mode_param.angle, mode_param.count, radius);
+    fds[i] = calculate_fillet_data_per_vertex(prev_pos,
+                                              pos,
+                                              next_pos,
+                                              mode_param.angle,
+                                              mode_param.count,
+                                              radius,
+                                              mode_param.limit_radius);
 
     /* Exit from here if the radius is zero */
     if (!radius) {
@@ -471,6 +546,9 @@ static SplinePtr fillet_spline(const Spline &spline, const FilletModeParam &mode
   /* Update point_counts array and added_count. */
   Array<FilletData> fds = calculate_fillet_data(
       src_spline_ptr, mode_param, added_count, point_counts);
+  if (mode_param.limit_radius) {
+    limit_radii(fds, spline.size(), cyclic);
+  }
 
   int total_points = added_count + size;
   Array<int> dst_to_src = create_dst_to_src_map(point_counts, total_points);
@@ -571,6 +649,8 @@ static void geo_node_fillet_exec(GeoNodeExecParams params)
     mode_param.count.emplace(count);
   }
 
+  mode_param.limit_radius = params.extract_input<bool>("Limit Radius");
+
   if (radius_mode == GEO_NODE_CURVE_FILLET_RADIUS_FLOAT) {
     mode_param.radius.emplace(params.extract_input<float>("Radius"));
   }



More information about the Bf-blender-cvs mailing list