Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMattias Fredriksson <Osares>2022-09-18 05:53:58 +0300
committerHans Goudey <h.goudey@me.com>2022-09-18 05:53:58 +0300
commit095516403c48ad1586d732ba2fc8d641827f7572 (patch)
tree0d6da2a3c0183407f8c43d4a2a78e3bca6a60579 /source/blender/blenkernel/BKE_curves.hh
parent641bbc820f94668aa0e5beb972d1368475041cc4 (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/BKE_curves.hh')
-rw-r--r--source/blender/blenkernel/BKE_curves.hh21
1 files changed, 7 insertions, 14 deletions
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index b1581e93491..0d67152dec8 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -709,7 +709,7 @@ void interpolate_to_evaluated(const GSpan src,
const Span<int> evaluated_offsets,
GMutableSpan dst);
-void calculate_basis(const float parameter, float r_weights[4]);
+void calculate_basis(const float parameter, float4 &r_weights);
/**
* Interpolate the control point values for the given parameter on the piecewise segment.
@@ -720,22 +720,15 @@ void calculate_basis(const float parameter, float r_weights[4]);
template<typename T>
T interpolate(const T &a, const T &b, const T &c, const T &d, const float parameter)
{
- float n[4];
+ BLI_assert(0.0f <= parameter && parameter <= 1.0f);
+ float4 n;
calculate_basis(parameter, n);
- /* 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>) {
- T return_value;
- attribute_math::DefaultMixer<T> mixer({&return_value, 1});
- mixer.mix_in(0, a, n[0] * 0.5f);
- mixer.mix_in(0, b, n[1] * 0.5f);
- mixer.mix_in(0, c, n[2] * 0.5f);
- mixer.mix_in(0, d, n[3] * 0.5f);
- mixer.finalize();
- return return_value;
+ 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);
}
else {
- return 0.5f * (a * n[0] + b * n[1] + c * n[2] + d * n[3]);
+ return attribute_math::mix4<T>(n * 0.5f, a, b, c, d);
}
}