[Bf-blender-cvs] [301119619c9] master: Curves: Remove attribute retrieval, deduplicate evaluation logic

Hans Goudey noreply at git.blender.org
Tue Jan 17 22:00:13 CET 2023


Commit: 301119619c96aac2c6c3ec3a83bc16c5b3110469
Author: Hans Goudey
Date:   Tue Jan 17 14:40:01 2023 -0600
Branches: master
https://developer.blender.org/rB301119619c96aac2c6c3ec3a83bc16c5b3110469

Curves: Remove attribute retrieval, deduplicate evaluation logic

Avoid calling `interpolate_to_evaluate` while evaluating normals,
which has to look up attributes by name for every curve. Also avoid
duplicating the curve type switch in a few functions. I didn't observe
a performance difference, but theoretically this could reduce
overhead for many small curves.

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

M	source/blender/blenkernel/intern/curves_geometry.cc

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

diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index 0dc6a24fd9e..133521bc298 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -716,14 +716,57 @@ static void rotate_directions_around_axes(MutableSpan<float3> directions,
   }
 }
 
+static void evaluate_generic_data_for_curve(
+    const int curve_index,
+    const IndexRange points,
+    const VArray<int8_t> &types,
+    const VArray<bool> &cyclic,
+    const VArray<int> &resolution,
+    const Span<int> bezier_evaluated_offsets,
+    const Span<curves::nurbs::BasisCache> nurbs_basis_cache,
+    const VArray<int8_t> &nurbs_orders,
+    const Span<float> nurbs_weights,
+    const GSpan src,
+    GMutableSpan dst)
+{
+  switch (types[curve_index]) {
+    case CURVE_TYPE_CATMULL_ROM:
+      curves::catmull_rom::interpolate_to_evaluated(
+          src, cyclic[curve_index], resolution[curve_index], dst);
+      break;
+    case CURVE_TYPE_POLY:
+      dst.copy_from(src);
+      break;
+    case CURVE_TYPE_BEZIER:
+      curves::bezier::interpolate_to_evaluated(src, bezier_evaluated_offsets.slice(points), dst);
+      break;
+    case CURVE_TYPE_NURBS:
+      curves::nurbs::interpolate_to_evaluated(nurbs_basis_cache[curve_index],
+                                              nurbs_orders[curve_index],
+                                              nurbs_weights.slice_safe(points),
+                                              src,
+                                              dst);
+      break;
+  }
+}
+
 Span<float3> CurvesGeometry::evaluated_normals() const
 {
   this->runtime->normal_cache_mutex.ensure([&]() {
-    const Span<float3> evaluated_tangents = this->evaluated_tangents();
+    const VArray<int8_t> types = this->curve_types();
     const VArray<bool> cyclic = this->cyclic();
     const VArray<int8_t> normal_mode = this->normal_mode();
-    const VArray<int8_t> types = this->curve_types();
+    const VArray<int> resolution = this->resolution();
+    const VArray<int8_t> nurbs_orders = this->nurbs_orders();
+    const Span<float> nurbs_weights = this->nurbs_weights();
+
+    const Span<float3> evaluated_tangents = this->evaluated_tangents();
     const VArray<float> tilt = this->tilt();
+    VArraySpan<float> tilt_span;
+    const bool use_tilt = !(tilt.is_single() && tilt.get_internal_single() == 0.0f);
+    if (use_tilt) {
+      tilt_span = tilt;
+    }
 
     this->runtime->evaluated_normal_cache.resize(this->evaluated_points_num());
     MutableSpan<float3> evaluated_normals = this->runtime->evaluated_normal_cache;
@@ -748,19 +791,26 @@ Span<float3> CurvesGeometry::evaluated_normals() const
 
         /* If the "tilt" attribute exists, rotate the normals around the tangents by the
          * evaluated angles. We can avoid copying the tilts to evaluate them for poly curves. */
-        if (!(tilt.is_single() && tilt.get_internal_single() == 0.0f)) {
+        if (use_tilt) {
           const IndexRange points = this->points_for_curve(curve_index);
-          Span<float> curve_tilt = tilt.get_internal_span().slice(points);
           if (types[curve_index] == CURVE_TYPE_POLY) {
             rotate_directions_around_axes(evaluated_normals.slice(evaluated_points),
                                           evaluated_tangents.slice(evaluated_points),
-                                          curve_tilt);
+                                          tilt_span.slice(points));
           }
           else {
-            evaluated_tilts.clear();
-            evaluated_tilts.resize(evaluated_points.size());
-            this->interpolate_to_evaluated(
-                curve_index, curve_tilt, evaluated_tilts.as_mutable_span());
+            evaluated_tilts.reinitialize(evaluated_points.size());
+            evaluate_generic_data_for_curve(curve_index,
+                                            points,
+                                            types,
+                                            cyclic,
+                                            resolution,
+                                            this->runtime->bezier_evaluated_offsets.as_span(),
+                                            this->runtime->nurbs_basis_cache.as_span(),
+                                            nurbs_orders,
+                                            nurbs_weights,
+                                            tilt_span.slice(points),
+                                            evaluated_tilts.as_mutable_span());
             rotate_directions_around_axes(evaluated_normals.slice(evaluated_points),
                                           evaluated_tangents.slice(evaluated_points),
                                           evaluated_tilts.as_span());
@@ -781,27 +831,17 @@ void CurvesGeometry::interpolate_to_evaluated(const int curve_index,
   const IndexRange points = this->points_for_curve(curve_index);
   BLI_assert(src.size() == points.size());
   BLI_assert(dst.size() == this->evaluated_points_for_curve(curve_index).size());
-  switch (this->curve_types()[curve_index]) {
-    case CURVE_TYPE_CATMULL_ROM:
-      curves::catmull_rom::interpolate_to_evaluated(
-          src, this->cyclic()[curve_index], this->resolution()[curve_index], dst);
-      return;
-    case CURVE_TYPE_POLY:
-      dst.type().copy_assign_n(src.data(), dst.data(), src.size());
-      return;
-    case CURVE_TYPE_BEZIER:
-      curves::bezier::interpolate_to_evaluated(
-          src, this->runtime->bezier_evaluated_offsets.as_span().slice(points), dst);
-      return;
-    case CURVE_TYPE_NURBS:
-      curves::nurbs::interpolate_to_evaluated(this->runtime->nurbs_basis_cache[curve_index],
-                                              this->nurbs_orders()[curve_index],
-                                              this->nurbs_weights().slice_safe(points),
-                                              src,
-                                              dst);
-      return;
-  }
-  BLI_assert_unreachable();
+  evaluate_generic_data_for_curve(curve_index,
+                                  points,
+                                  this->curve_types(),
+                                  this->cyclic(),
+                                  this->resolution(),
+                                  this->runtime->bezier_evaluated_offsets.as_span(),
+                                  this->runtime->nurbs_basis_cache.as_span(),
+                                  this->nurbs_orders(),
+                                  this->nurbs_weights(),
+                                  src,
+                                  dst);
 }
 
 void CurvesGeometry::interpolate_to_evaluated(const GSpan src, GMutableSpan dst) const
@@ -818,30 +858,17 @@ void CurvesGeometry::interpolate_to_evaluated(const GSpan src, GMutableSpan dst)
     for (const int curve_index : curves_range) {
       const IndexRange points = this->points_for_curve(curve_index);
       const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
-      switch (types[curve_index]) {
-        case CURVE_TYPE_CATMULL_ROM:
-          curves::catmull_rom::interpolate_to_evaluated(src.slice(points),
-                                                        cyclic[curve_index],
-                                                        resolution[curve_index],
-                                                        dst.slice(evaluated_points));
-          continue;
-        case CURVE_TYPE_POLY:
-          dst.slice(evaluated_points).copy_from(src.slice(points));
-          continue;
-        case CURVE_TYPE_BEZIER:
-          curves::bezier::interpolate_to_evaluated(
-              src.slice(points),
-              this->runtime->bezier_evaluated_offsets.as_span().slice(points),
-              dst.slice(evaluated_points));
-          continue;
-        case CURVE_TYPE_NURBS:
-          curves::nurbs::interpolate_to_evaluated(this->runtime->nurbs_basis_cache[curve_index],
-                                                  nurbs_orders[curve_index],
-                                                  nurbs_weights.slice_safe(points),
-                                                  src.slice(points),
-                                                  dst.slice(evaluated_points));
-          continue;
-      }
+      evaluate_generic_data_for_curve(curve_index,
+                                      points,
+                                      types,
+                                      cyclic,
+                                      resolution,
+                                      this->runtime->bezier_evaluated_offsets,
+                                      this->runtime->nurbs_basis_cache,
+                                      nurbs_orders,
+                                      nurbs_weights,
+                                      src.slice(points),
+                                      dst.slice(evaluated_points));
     }
   });
 }



More information about the Bf-blender-cvs mailing list