[Bf-blender-cvs] [a0a793c9df4] blender-v3.2-release: Curves: Use copied original data for invalid NURBS curves

Hans Goudey noreply at git.blender.org
Wed Jun 22 13:03:00 CEST 2022


Commit: a0a793c9df47a7b5a1be793bfc01f041c3f3a2ad
Author: Hans Goudey
Date:   Wed May 4 10:27:46 2022 +0200
Branches: blender-v3.2-release
https://developer.blender.org/rBa0a793c9df47a7b5a1be793bfc01f041c3f3a2ad

Curves: Use copied original data for invalid NURBS curves

NURBS curves can be invalid when the order is less than the number
of points, or in a few other situations. Currently the evaluated data of
an invalid NURBS curve is empty. This is inconvenient because it
requires checking for empty curves when it otherwise wouldn't be
necessary. This patch replaces that fallback with copying the original
data to the evaluated points. This makes conceptual sense too, as if
the curve couldn't be evaluated-- which wouldn't necessarily delete it.

Usually the UI protects against this happening, but it's currently
possible to create an invalid curve with some operations like the
delete geometry node.

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

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

M	source/blender/blenkernel/BKE_curves.hh
M	source/blender/blenkernel/intern/curve_nurbs.cc
M	source/blender/blenkernel/intern/curves_geometry.cc

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

diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index 1e96c0e4c41..c125c347071 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -48,6 +48,13 @@ struct BasisCache {
    * In other words, the index of the first control point that influences this evaluated point.
    */
   Vector<int> start_indices;
+
+  /**
+   * The result of #check_valid_size_and_order, to avoid retrieving its inputs later on.
+   * If this is true, the data above will be invalid, and original data should be copied
+   * to the evaluated result.
+   */
+  bool invalid = false;
 };
 
 }  // namespace curves::nurbs
@@ -760,7 +767,7 @@ inline IndexRange CurvesGeometry::lengths_range_for_curve(const int curve_index,
   BLI_assert(cyclic == this->cyclic()[curve_index]);
   const IndexRange points = this->evaluated_points_for_curve(curve_index);
   const int start = points.start() + curve_index;
-  return {start, points.is_empty() ? 0 : curves::curve_segment_size(points.size(), cyclic)};
+  return {start, curves::curve_segment_size(points.size(), cyclic)};
 }
 
 inline Span<float> CurvesGeometry::evaluated_lengths_for_curve(const int curve_index,
@@ -775,8 +782,7 @@ inline float CurvesGeometry::evaluated_length_total_for_curve(const int curve_in
                                                               const bool cyclic) const
 {
   const Span<float> lengths = this->evaluated_lengths_for_curve(curve_index, cyclic);
-  /* Check for curves that have no evaluated segments. */
-  return lengths.is_empty() ? 0.0f : lengths.last();
+  return lengths.last();
 }
 
 /** \} */
diff --git a/source/blender/blenkernel/intern/curve_nurbs.cc b/source/blender/blenkernel/intern/curve_nurbs.cc
index 0114c0b45f4..45440358221 100644
--- a/source/blender/blenkernel/intern/curve_nurbs.cc
+++ b/source/blender/blenkernel/intern/curve_nurbs.cc
@@ -36,7 +36,7 @@ int calculate_evaluated_size(const int points_num,
                              const KnotsMode knots_mode)
 {
   if (!check_valid_size_and_order(points_num, order, cyclic, knots_mode)) {
-    return 0;
+    return points_num;
   }
   return resolution * curve_segment_size(points_num, cyclic);
 }
@@ -232,8 +232,12 @@ void interpolate_to_evaluated(const BasisCache &basis_cache,
                               const GSpan src,
                               GMutableSpan dst)
 {
-  BLI_assert(dst.size() == basis_cache.start_indices.size());
+  if (basis_cache.invalid) {
+    dst.copy_from(src);
+    return;
+  }
 
+  BLI_assert(dst.size() == basis_cache.start_indices.size());
   attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
     using T = decltype(dummy);
     if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index 7a09b87490b..3ec5ee928f4 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -577,6 +577,11 @@ void CurvesGeometry::ensure_nurbs_basis_cache() const
         const bool is_cyclic = cyclic[curve_index];
         const KnotsMode mode = KnotsMode(knots_modes[curve_index]);
 
+        if (!curves::nurbs::check_valid_size_and_order(points.size(), order, is_cyclic, mode)) {
+          basis_caches[curve_index].invalid = true;
+          continue;
+        }
+
         const int knots_size = curves::nurbs::knots_size(points.size(), order, is_cyclic);
         Array<float> knots(knots_size);
         curves::nurbs::calculate_knots(points.size(), mode, order, is_cyclic, knots);
@@ -696,9 +701,6 @@ Span<float3> CurvesGeometry::evaluated_tangents() const
     threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) {
       for (const int curve_index : curves_range) {
         const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
-        if (UNLIKELY(evaluated_points.is_empty())) {
-          continue;
-        }
         curves::poly::calculate_tangents(evaluated_positions.slice(evaluated_points),
                                          cyclic[curve_index],
                                          tangents.slice(evaluated_points));
@@ -773,9 +775,6 @@ Span<float3> CurvesGeometry::evaluated_normals() const
 
       for (const int curve_index : curves_range) {
         const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
-        if (UNLIKELY(evaluated_points.is_empty())) {
-          continue;
-        }
         switch (normal_mode[curve_index]) {
           case NORMAL_MODE_Z_UP:
             curves::poly::calculate_normals_z_up(evaluated_tangents.slice(evaluated_points),
@@ -916,9 +915,6 @@ void CurvesGeometry::ensure_evaluated_lengths() const
       for (const int curve_index : curves_range) {
         const bool cyclic = curves_cyclic[curve_index];
         const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
-        if (UNLIKELY(evaluated_points.is_empty())) {
-          continue;
-        }
         const IndexRange lengths_range = this->lengths_range_for_curve(curve_index, cyclic);
         length_parameterize::accumulate_lengths(evaluated_positions.slice(evaluated_points),
                                                 cyclic,



More information about the Bf-blender-cvs mailing list