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. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs