diff options
author | Mattias Fredriksson <Osares> | 2022-09-18 05:53:58 +0300 |
---|---|---|
committer | Hans Goudey <h.goudey@me.com> | 2022-09-18 05:53:58 +0300 |
commit | 095516403c48ad1586d732ba2fc8d641827f7572 (patch) | |
tree | 0d6da2a3c0183407f8c43d4a2a78e3bca6a60579 /source/blender/blenkernel/intern/curve_catmull_rom.cc | |
parent | 641bbc820f94668aa0e5beb972d1368475041cc4 (diff) |
Curves: Correct and improve Catmull Rom interpolation
Correct interpolation of integer POD types for Catmull Rom
interpolation as implemented in eaf416693dcb.
**Problem description**
`attribute_math::DefaultMixer<T>::mix_in()` assumes/asserts positive
weights but the basis function for Catmull-Rom splines generates
negative weights (see image in revision). Passing negative weights will
yield correct result as sum(weights) = 1 (after multiplication by 0.5)
but the assert is still triggered in debug builds. This patch adjusts
the behavior by extending the mix functions with mix4(). The benefit
of using mix#() over a DefaultMixer is that the result no longer needs
to be divided by the weight sum, instead utilizing that the basis weight
sum is constant (see plot).
**Changes**
* Added mix4() and updated catmull_rom::interpolate() to use it.
* Removed TODOs from catmull_rom functions.
* Moved mix definitions to be ordered as 2, 3, 4 in the header.
**Implementation specifics**
`catmull_rom::interpolate()` uses a constexpr to differentiate between
POD types which multiplies the result with 0.5 after weighting the
values, this reduces the number of multiplications for 1D, 2D, 3D
vectors (https://godbolt.org/z/8M1z9Pxx6). While this could be
considered unnecessary, I didn't want to change the original behavior
as it could influence performance (did not measure performance here
as this should ensure the logic is ~identical for FP types).
Differential Revision: https://developer.blender.org/D15997
Diffstat (limited to 'source/blender/blenkernel/intern/curve_catmull_rom.cc')
-rw-r--r-- | source/blender/blenkernel/intern/curve_catmull_rom.cc | 14 |
1 files changed, 3 insertions, 11 deletions
diff --git a/source/blender/blenkernel/intern/curve_catmull_rom.cc b/source/blender/blenkernel/intern/curve_catmull_rom.cc index dac88948036..b5f1a7cc450 100644 --- a/source/blender/blenkernel/intern/curve_catmull_rom.cc +++ b/source/blender/blenkernel/intern/curve_catmull_rom.cc @@ -17,7 +17,7 @@ int calculate_evaluated_num(const int points_num, const bool cyclic, const int r } /* Adapted from Cycles #catmull_rom_basis_eval function. */ -void calculate_basis(const float parameter, float r_weights[4]) +void calculate_basis(const float parameter, float4 &r_weights) { const float t = parameter; const float s = 1.0f - parameter; @@ -139,11 +139,7 @@ void interpolate_to_evaluated(const GSpan src, { attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); - /* TODO: Use DefaultMixer or other generic mixing in the basis evaluation function to simplify - * supporting more types. */ - if constexpr (is_same_any_v<T, float, float2, float3, float4, int8_t, int, int64_t>) { - interpolate_to_evaluated(src.typed<T>(), cyclic, resolution, dst.typed<T>()); - } + interpolate_to_evaluated(src.typed<T>(), cyclic, resolution, dst.typed<T>()); }); } @@ -154,11 +150,7 @@ void interpolate_to_evaluated(const GSpan src, { attribute_math::convert_to_static_type(src.type(), [&](auto dummy) { using T = decltype(dummy); - /* TODO: Use DefaultMixer or other generic mixing in the basis evaluation function to simplify - * supporting more types. */ - if constexpr (is_same_any_v<T, float, float2, float3, float4, int8_t, int, int64_t>) { - interpolate_to_evaluated(src.typed<T>(), cyclic, evaluated_offsets, dst.typed<T>()); - } + interpolate_to_evaluated(src.typed<T>(), cyclic, evaluated_offsets, dst.typed<T>()); }); } |