[Bf-blender-cvs] [93e0559f54c] microfacet_hair: WIP: calculate normals aligned with the curvature vector Only works for Catmull-Rom and poly curve types for now

Weizhen Huang noreply at git.blender.org
Mon Jan 2 15:50:54 CET 2023


Commit: 93e0559f54c087a64121b4b30708be096a3d7c3e
Author: Weizhen Huang
Date:   Mon Jan 2 15:49:28 2023 +0100
Branches: microfacet_hair
https://developer.blender.org/rB93e0559f54c087a64121b4b30708be096a3d7c3e

WIP: calculate normals aligned with the curvature vector
Only works for Catmull-Rom and poly curve types for now

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

M	release/datafiles/locale
M	release/scripts/addons
M	release/scripts/addons_contrib
M	source/blender/blenkernel/BKE_curves.hh
M	source/blender/blenkernel/intern/curve_catmull_rom.cc
M	source/blender/blenkernel/intern/curve_legacy_convert.cc
M	source/blender/blenkernel/intern/curve_poly.cc
M	source/blender/blenkernel/intern/curves_geometry.cc
M	source/blender/blenkernel/intern/geometry_component_curves.cc
M	source/blender/geometry/intern/add_curves_on_mesh.cc
M	source/blender/geometry/intern/trim_curves.cc
M	source/blender/makesdna/DNA_curves_types.h
M	source/blender/makesrna/intern/rna_curves.c
M	source/tools

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

diff --git a/release/datafiles/locale b/release/datafiles/locale
index e398d3c4969..7084c4ecd97 160000
--- a/release/datafiles/locale
+++ b/release/datafiles/locale
@@ -1 +1 @@
-Subproject commit e398d3c4969a37ae2ecff388344dd780bc1cfe82
+Subproject commit 7084c4ecd97d93459d9d23fd90f81589b09be5df
diff --git a/release/scripts/addons b/release/scripts/addons
index 90c87dd771e..042c799b7ae 160000
--- a/release/scripts/addons
+++ b/release/scripts/addons
@@ -1 +1 @@
-Subproject commit 90c87dd771e027e0ffa157a0e294399bfd605d99
+Subproject commit 042c799b7aef9634a33d24e78d4922706aca9a2b
diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib
index 96143b1a8b0..bdcfdd47ec3 160000
--- a/release/scripts/addons_contrib
+++ b/release/scripts/addons_contrib
@@ -1 +1 @@
-Subproject commit 96143b1a8b037ea3c81f065f557025db9fe1ace3
+Subproject commit bdcfdd47ec3451822b21d1cff2ea2db751093c9a
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index 9382a912c02..44d0dd132aa 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -520,6 +520,13 @@ void calculate_tangents(Span<float3> positions, bool is_cyclic, MutableSpan<floa
  */
 void calculate_normals_minimum(Span<float3> tangents, bool cyclic, MutableSpan<float3> normals);
 
+/**
+ * Calculate curvature vectors. TODO: more description. */
+void calculate_curvature_vectors(Span<float3> positions,
+                                 Span<float3> tangents,
+                                 bool cyclic,
+                                 MutableSpan<float3> normals);
+
 /**
  * Calculate a vector perpendicular to every tangent on the X-Y plane (unless the tangent is
  * vertical, in that case use the X direction).
@@ -696,6 +703,16 @@ void interpolate_to_evaluated(GSpan src, Span<int> evaluated_offsets, GMutableSp
 
 namespace catmull_rom {
 
+void calculate_tangents(Span<float3> positions,
+                        bool is_cyclic,
+                        int resolution,
+                        MutableSpan<float3> tangents);
+void calculate_normals(Span<float3> positions,
+                       bool is_cyclic,
+                       int resolution,
+                       Span<float3> tangents,
+                       MutableSpan<float3> normals);
+
 /**
  * Calculate the number of evaluated points that #interpolate_to_evaluated is expected to produce.
  * \param points_num: The number of points in the curve.
@@ -719,6 +736,8 @@ void interpolate_to_evaluated(const GSpan src,
                               GMutableSpan dst);
 
 void calculate_basis(const float parameter, float4 &r_weights);
+void calculate_basis_derivative(const float parameter, float4 &r_weights);
+void calculate_basis_derivative2(const float parameter, float4 &r_weights);
 
 /**
  * Interpolate the control point values for the given parameter on the piecewise segment.
@@ -727,11 +746,24 @@ void calculate_basis(const float parameter, float4 &r_weights);
  * \param parameter: Parameter in range [0, 1] to compute the interpolation for.
  */
 template<typename T>
-T interpolate(const T &a, const T &b, const T &c, const T &d, const float parameter)
+T interpolate(
+    const int order, const T &a, const T &b, const T &c, const T &d, const float parameter)
 {
   BLI_assert(0.0f <= parameter && parameter <= 1.0f);
   float4 n;
-  calculate_basis(parameter, n);
+
+  switch (order) {
+    case 1:
+      calculate_basis_derivative(parameter, n);
+      break;
+    case 2:
+      calculate_basis_derivative2(parameter, n);
+      break;
+    default:
+      calculate_basis(parameter, n);
+      break;
+  }
+
   if constexpr (is_same_any_v<T, float, float2, float3>) {
     /* Save multiplications by adjusting weights after mix. */
     return 0.5f * attribute_math::mix4<T>(n, a, b, c, d);
diff --git a/source/blender/blenkernel/intern/curve_catmull_rom.cc b/source/blender/blenkernel/intern/curve_catmull_rom.cc
index 8247d9451e4..7bd5db488f4 100644
--- a/source/blender/blenkernel/intern/curve_catmull_rom.cc
+++ b/source/blender/blenkernel/intern/curve_catmull_rom.cc
@@ -31,13 +31,37 @@ void calculate_basis(const float parameter, float4 &r_weights)
   r_weights[3] = -s * t * t;
 }
 
+/* Adapted from Cycles #catmull_rom_basis_derivative function. */
+void calculate_basis_derivative(const float parameter, float4 &r_weights)
+{
+  const float t = parameter;
+  const float s = 1.0f - parameter;
+  r_weights[0] = s * (2.0f * t - s);
+  r_weights[1] = t * (9.0f * t - 10.0f);
+  r_weights[2] = -s * (9.0f * s - 10.0f);
+  r_weights[3] = t * (t - 2.0f * s);
+}
+
+/* Adapted from Cycles #catmull_rom_basis_derivative2 function. */
+void calculate_basis_derivative2(const float parameter, float4 &r_weights)
+{
+  const float t = parameter;
+  const float s = 1.0f - parameter;
+  r_weights[0] = -6.0f * t + 4.0f;
+  r_weights[1] = 18.0f * t - 10.0f;
+  r_weights[2] = 18.0f * s - 10.0f;
+  r_weights[3] = 6.0f * t - 2.0f;
+}
+
 template<typename T>
-static void evaluate_segment(const T &a, const T &b, const T &c, const T &d, MutableSpan<T> dst)
+static void evaluate_segment(
+    const int order, const T &a, const T &b, const T &c, const T &d, MutableSpan<T> dst)
 {
   const float step = 1.0f / dst.size();
   dst.first() = b;
-  for (const int i : dst.index_range().drop_front(1)) {
-    dst[i] = interpolate<T>(a, b, c, d, i * step);
+  IndexRange index_range = (order == 0) ? dst.index_range().drop_front(1) : dst.index_range();
+  for (const int i : index_range) {
+    dst[i] = interpolate(order, a, b, c, d, i * step);
   }
 }
 
@@ -45,9 +69,11 @@ static void evaluate_segment(const T &a, const T &b, const T &c, const T &d, Mut
  * \param range_fn: Returns an index range describing where in the #dst span each segment should be
  * evaluated to, and how many points to add to it. This is used to avoid the need to allocate an
  * actual offsets array in typical evaluation use cases where the resolution is per-curve.
+ * \param order: The order of the derivative. order == 0 is the default.
  */
 template<typename T, typename RangeForSegmentFn>
-static void interpolate_to_evaluated(const Span<T> src,
+static void interpolate_to_evaluated(const int order,
+                                     const Span<T> src,
                                      const bool cyclic,
                                      const RangeForSegmentFn &range_fn,
                                      MutableSpan<T> dst)
@@ -59,20 +85,30 @@ static void interpolate_to_evaluated(const Span<T> src,
    * - Finally evaluate all of the segments in the middle in parallel. */
 
   if (src.size() == 1) {
-    dst.first() = src.first();
+    switch (order) {
+      case 1:
+        dst.first() = float3(0.0f, 0.0f, 1.0f);
+        break;
+      case 2:
+        dst.first() = float3(1.0f, 0.0f, 0.0f);
+        break;
+      default:
+        dst.first() = src.first();
+        break;
+    }
     return;
   }
 
   const IndexRange first = range_fn(0);
 
   if (src.size() == 2) {
-    evaluate_segment(src.first(), src.first(), src.last(), src.last(), dst.slice(first));
+    evaluate_segment(order, src.first(), src.first(), src.last(), src.last(), dst.slice(first));
     if (cyclic) {
       const IndexRange last = range_fn(1);
-      evaluate_segment(src.last(), src.last(), src.first(), src.first(), dst.slice(last));
+      evaluate_segment(order, src.last(), src.last(), src.first(), src.first(), dst.slice(last));
     }
     else {
-      dst.last() = src.last();
+      dst.last() = interpolate(order, src.first(), src.first(), src.last(), src.last(), 1);
     }
     return;
   }
@@ -80,17 +116,19 @@ static void interpolate_to_evaluated(const Span<T> src,
   const IndexRange second_to_last = range_fn(src.index_range().last(1));
   const IndexRange last = range_fn(src.index_range().last());
   if (cyclic) {
-    evaluate_segment(src.last(), src[0], src[1], src[2], dst.slice(first));
-    evaluate_segment(src.last(2), src.last(1), src.last(), src.first(), dst.slice(second_to_last));
-    evaluate_segment(src.last(1), src.last(), src[0], src[1], dst.slice(last));
+    evaluate_segment(order, src.last(), src[0], src[1], src[2], dst.slice(first));
+    evaluate_segment(
+        order, src.last(2), src.last(1), src.last(), src.first(), dst.slice(second_to_last));
+    evaluate_segment(order, src.last(1), src.last(), src[0], src[1], dst.slice(last));
   }
   else {
-    evaluate_segment(src[0], src[0], src[1], src[2], dst.slice(first));
-    evaluate_segment(src.last(2), src.last(1), src.last(), src.last(), dst.slice(second_to_last));
+    evaluate_segment(order, src[0], src[0], src[1], src[2], dst.slice(first));
+    evaluate_segment(
+        order, src.last(2), src.last(1), src.last(), src.last(), dst.slice(second_to_last));
     /* For non-cyclic curves, the last segment should always just have a single point. We could
      * assert that the size of the provided range is 1 here, but that would require specializing
      * the #range_fn implementation for the last point, which may have a performance cost. */
-    dst.last() = src.last();
+    dst.last() = interpolate(order, src.last(2), src.last(1), src.last(), src.last(), 1);
   }
 
   /* Evaluate every segment that isn't the first or last. */
@@ -98,7 +136,7 @@ static void interpolate_to_evaluated(const Span<T> src,
   threading::parallel_for(inner_range, 512, [&](IndexRange range) {
     for (const int i : range) {
       const IndexRange segment = range_fn(i);
-      evaluate_segment(src[i - 1], src[i], src[i + 1], src[i + 2], dst.slice(segment));
+      evaluate_segment(order, src[i - 1], src[i], src[i + 1], src[i + 2], dst.slice(segment));
     }
   });
 }
@@ -112,6 +150,7 @@ static void interpolate_to_evaluated(const Span<T> src,
 {
   BLI_assert(dst.size() == calculate_evaluated_num(src.size(), cyclic, resolution));
   interpolate_to_evaluated(
+      0,
       src,
       cyclic,
       [resolution](const int segment_i) -> IndexRange {
@@ -128,6 +167,7 @@ static void interpolate_to_evaluated(const Span<T> src,
 
 {
   interpolate_to_evaluated(
+      0,
       src,
       cyclic,
       [evaluated_offsets](const int segment_i) -> IndexRange {
@@ -158,4 +198,76

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list