[Bf-blender-cvs] [0602852860d] master: Curve: Improve NURBS knot generation modes

Laurynas Duburas noreply at git.blender.org
Fri Mar 11 01:39:30 CET 2022


Commit: 0602852860dda7dfc0ea20c72e03b7f96c981f1a
Author: Laurynas Duburas
Date:   Thu Mar 10 18:34:27 2022 -0600
Branches: master
https://developer.blender.org/rB0602852860dda7dfc0ea20c72e03b7f96c981f1a

Curve: Improve NURBS knot generation modes

This patch enables all 8 combinations of Nurbs modes: Cyclic,
Bezier and Endpoint. Also removes restriction on Bezier Nurbs order.

The most significant changes are mode combinations bringing new
meaning. In D13891 is a scheme showing NURBS with same control
points in a modes, and also further description of each possible case.

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

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

M	release/scripts/startup/bl_ui/properties_data_curve.py
M	source/blender/blenkernel/BKE_blender_version.h
M	source/blender/blenkernel/BKE_curve.h
M	source/blender/blenkernel/BKE_spline.hh
M	source/blender/blenkernel/intern/curve.cc
M	source/blender/blenkernel/intern/curve_eval.cc
M	source/blender/blenkernel/intern/spline_nurbs.cc
M	source/blender/blenloader/intern/versioning_300.c
M	source/blender/editors/curve/editcurve.c
M	source/blender/editors/curve/editcurve_add.c
M	source/blender/makesrna/intern/rna_curve.c
M	source/blender/nodes/geometry/nodes/node_geo_curve_spline_type.cc

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

diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py
index 26e5cfaae60..2ad6e5bae8a 100644
--- a/release/scripts/startup/bl_ui/properties_data_curve.py
+++ b/release/scripts/startup/bl_ui/properties_data_curve.py
@@ -289,7 +289,6 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
 
                 if is_surf:
                     subsub = sub.column()
-                    subsub.active = (not act_spline.use_cyclic_v)
                     subsub.prop(act_spline, "use_bezier_v", text="V")
 
                 sub = col.column(heading="Endpoint", align=True)
@@ -297,7 +296,6 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
 
                 if is_surf:
                     subsub = sub.column()
-                    subsub.active = (not act_spline.use_cyclic_v)
                     subsub.prop(act_spline, "use_endpoint_v", text="V")
 
                 sub = col.column(align=True)
@@ -322,6 +320,18 @@ class DATA_PT_active_spline(CurveButtonsPanelActive, Panel):
                 col.prop(act_spline, "radius_interpolation", text="Radius")
 
             layout.prop(act_spline, "use_smooth")
+            if act_spline.type == 'NURBS':
+                messages = [act_spline.valid_message_u]
+                if is_surf and act_spline.point_count_v > 1:
+                    messages.append(act_spline.valid_message_v)
+
+                messages = list(filter(None, messages))
+
+                if len(messages) > 0:
+                    layout.separator()
+                    col = layout.column(align=True)
+                    for message in messages:
+                        col.label(text=message, icon='INFO')
 
 
 class DATA_PT_font(CurveButtonsPanelText, Panel):
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index a8a851bb228..1639a564508 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -25,7 +25,7 @@ extern "C" {
 
 /* Blender file format version. */
 #define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 5
+#define BLENDER_FILE_SUBVERSION 6
 
 /* Minimum Blender version that supports reading file written with the current
  * version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 3f65ce83b3f..394d97223e3 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -269,6 +269,14 @@ void BKE_nurb_knot_calc_v(struct Nurb *nu);
 bool BKE_nurb_check_valid_u(const struct Nurb *nu);
 bool BKE_nurb_check_valid_v(const struct Nurb *nu);
 bool BKE_nurb_check_valid_uv(const struct Nurb *nu);
+bool BKE_nurb_valid_message(int pnts,
+                            short order,
+                            short flag,
+                            short type,
+                            bool is_surf,
+                            const char *dir,
+                            char *message_dst,
+                            size_t maxncpy);
 
 bool BKE_nurb_order_clamp_u(struct Nurb *nu);
 bool BKE_nurb_order_clamp_v(struct Nurb *nu);
diff --git a/source/blender/blenkernel/BKE_spline.hh b/source/blender/blenkernel/BKE_spline.hh
index 42b4702ee44..ed9b743b524 100644
--- a/source/blender/blenkernel/BKE_spline.hh
+++ b/source/blender/blenkernel/BKE_spline.hh
@@ -453,6 +453,7 @@ class NURBSpline final : public Spline {
     Normal,
     EndPoint,
     Bezier,
+    EndPointBezier,
   };
 
   /** Method used to recalculate the knots vector when points are added or removed. */
diff --git a/source/blender/blenkernel/intern/curve.cc b/source/blender/blenkernel/intern/curve.cc
index 6b7f7af44e8..0b619c1a969 100644
--- a/source/blender/blenkernel/intern/curve.cc
+++ b/source/blender/blenkernel/intern/curve.cc
@@ -17,8 +17,8 @@
 #include "BLI_index_range.hh"
 #include "BLI_math.h"
 #include "BLI_math_vec_types.hh"
+#include "BLI_string.h"
 #include "BLI_utildefines.h"
-
 #include "BLT_translation.h"
 
 /* Allow using deprecated functionality for .blend file I/O. */
@@ -1156,12 +1156,13 @@ void BKE_nurb_bpoint_calc_plane(struct Nurb *nu, BPoint *bp, float r_plane[3])
 static void calcknots(float *knots, const int pnts, const short order, const short flag)
 {
   const bool is_cyclic = flag & CU_NURB_CYCLIC;
-  const bool is_bezier = flag & CU_NURB_BEZIER && !(flag & CU_NURB_ENDPOINT);
-  const bool is_end_point = flag & CU_NURB_ENDPOINT && !(flag & CU_NURB_BEZIER);
+  const bool is_bezier = flag & CU_NURB_BEZIER;
+  const bool is_end_point = flag & CU_NURB_ENDPOINT;
   /* Inner knots are always repeated once except on Bezier case. */
   const int repeat_inner = is_bezier ? order - 1 : 1;
   /* How many times to repeat 0.0 at the beginning of knot. */
-  const int head = is_end_point && !is_cyclic ? order : (is_bezier ? order / 2 : 1);
+  const int head = is_end_point ? (order - (is_cyclic ? 1 : 0)) :
+                                  (is_bezier ? min_ii(2, repeat_inner) : 1);
   /* Number of knots replicating widths of the starting knots.
    * Covers both Cyclic and EndPoint cases. */
   const int tail = is_cyclic ? 2 * order - 1 : (is_end_point ? order : 0);
@@ -1171,11 +1172,17 @@ static void calcknots(float *knots, const int pnts, const short order, const sho
   int r = head;
   float current = 0.0f;
 
-  for (const int i : IndexRange(knot_count - tail)) {
+  const int offset = is_end_point && is_cyclic ? 1 : 0;
+  if (offset) {
+    knots[0] = current;
+    current += 1.0f;
+  }
+
+  for (const int i : IndexRange(offset, knot_count - offset - tail)) {
     knots[i] = current;
     r--;
     if (r == 0) {
-      current += 1.0;
+      current += 1.0f;
       r = repeat_inner;
     }
   }
@@ -4693,59 +4700,56 @@ void BKE_curve_nurbs_key_vert_tilts_apply(ListBase *lb, const float *key)
   }
 }
 
-bool BKE_nurb_check_valid_u(const Nurb *nu)
+bool BKE_nurb_valid_message(const int pnts,
+                            const short order,
+                            const short flag,
+                            const short type,
+                            const bool is_surf,
+                            const char *dir,
+                            char *message_dst,
+                            const size_t maxncpy)
 {
-  if (nu->pntsu <= 1) {
-    return false;
-  }
-  if (nu->type != CU_NURBS) {
-    return true; /* not a nurb, lets assume its valid */
-  }
+  const char *msg_template = "";
+  uint16_t points_needed = 0;
 
-  if (nu->pntsu < nu->orderu) {
-    return false;
+  if (pnts <= 1) {
+    msg_template = TIP_("At least two points required.");
   }
-  if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) {
-    /* Bezier U Endpoints */
-    if (nu->orderu == 4) {
-      if (nu->pntsu < 5) {
-        return false; /* bezier with 4 orderu needs 5 points */
-      }
+  else if (type == CU_NURBS) {
+    if (pnts < order) {
+      msg_template = TIP_("Must have more control points than Order");
     }
-    else {
-      if (nu->orderu != 3) {
-        return false; /* order must be 3 or 4 */
+    else if (flag & CU_NURB_BEZIER) {
+      if (flag & CU_NURB_CYCLIC) {
+        const uint16_t remainder = pnts % (order - 1);
+        points_needed = remainder > 0 ? order - 1 - remainder : 0;
+      }
+      else if (((flag & CU_NURB_ENDPOINT) == 0) && pnts <= order) {
+        points_needed = order + 1 - pnts;
+      }
+      if (points_needed) {
+        msg_template = is_surf ? TIP_("%d more %s row(s) needed for Bezier") :
+                                 TIP_("%d more point(s) needed for Bezier");
       }
     }
   }
-  return true;
+
+  if (message_dst) {
+    BLI_snprintf(message_dst, maxncpy, msg_template, points_needed, dir);
+  }
+  return msg_template[0];
 }
-bool BKE_nurb_check_valid_v(const Nurb *nu)
+
+bool BKE_nurb_check_valid_u(const Nurb *nu)
 {
-  if (nu->pntsv <= 1) {
-    return false;
-  }
-  if (nu->type != CU_NURBS) {
-    return true; /* not a nurb, lets assume its valid */
-  }
+  return !BKE_nurb_valid_message(
+      nu->pntsu, nu->orderu, nu->flagu, nu->type, nu->pntsv > 1, "U", nullptr, 0);
+}
 
-  if (nu->pntsv < nu->orderv) {
-    return false;
-  }
-  if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) {
-    /* Bezier V Endpoints */
-    if (nu->orderv == 4) {
-      if (nu->pntsv < 5) {
-        return false; /* bezier with 4 orderu needs 5 points */
-      }
-    }
-    else {
-      if (nu->orderv != 3) {
-        return false; /* order must be 3 or 4 */
-      }
-    }
-  }
-  return true;
+bool BKE_nurb_check_valid_v(const Nurb *nu)
+{
+  return !BKE_nurb_valid_message(
+      nu->pntsv, nu->orderv, nu->flagv, nu->type, nu->pntsv > 1, "V", nullptr, 0);
 }
 
 bool BKE_nurb_check_valid_uv(const Nurb *nu)
@@ -4767,10 +4771,6 @@ bool BKE_nurb_order_clamp_u(struct Nurb *nu)
     nu->orderu = max_ii(2, nu->pntsu);
     changed = true;
   }
-  if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) {
-    CLAMP(nu->orderu, 3, 4);
-    changed = true;
-  }
   return changed;
 }
 
@@ -4781,10 +4781,6 @@ bool BKE_nurb_order_clamp_v(struct Nurb *nu)
     nu->orderv = max_ii(2, nu->pntsv);
     changed = true;
   }
-  if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) {
-    CLAMP(nu->orderv, 3, 4);
-    changed = true;
-  }
   return changed;
 }
 
diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc
index 1ffbed39216..59c2155255b 100644
--- a/source/blender/blenkernel/intern/curve_eval.cc
+++ b/source/blender/blenkernel/intern/curve_eval.cc
@@ -210,6 +210,8 @@ static NURBSpline::KnotsMode knots_mode_from_dna_nurb(const short flag)
       return NURBSpline::KnotsMode::EndPoint;
     case CU_NURB_BEZIER:
       return NURBSpline::KnotsMode::Bezier;
+    case CU_NURB_ENDPOINT | CU_NURB_BEZIER:
+      return NURBSpline::KnotsMode::EndPointBezier;
     default:
       return NURBSpline::KnotsMode::Normal;
   }
diff --git a/source/blender/blenkernel/intern/spline_nurbs.cc b/source/blender/blenkernel/intern/spline_nurbs.cc
in

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list