From 2e70af5cd527e2c1f40e6f3af22adc3337714744 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Wed, 18 May 2022 17:00:19 +0200 Subject: Fix T97761: incorrect mixing of integers Sometimes integers are mixed using float weights. In those cases the mixed result has to be converted from into float again. Previously, this was done using a simple cast, which was unexpected because e.g. 14.999 would be cast to 14 instead of 15. Now, the values are rounded properly. This can affect existing files unfortunately without a good option for versioning. Gladly, very few files seem to depend on the details of the old behavior. Differential Revision: https://developer.blender.org/D14892 --- source/blender/blenkernel/BKE_attribute_math.hh | 12 ++++++------ source/blender/blenlib/BLI_math_base.hh | 12 ++++++++++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh index 4482e13e1cf..3d194ba77dc 100644 --- a/source/blender/blenkernel/BKE_attribute_math.hh +++ b/source/blender/blenkernel/BKE_attribute_math.hh @@ -56,7 +56,7 @@ template T mix3(const float3 &weights, const T &v0, const T &v1, con template<> inline int8_t mix3(const float3 &weights, const int8_t &v0, const int8_t &v1, const int8_t &v2) { - return static_cast(weights.x * v0 + weights.y * v1 + weights.z * v2); + return static_cast(std::round(weights.x * v0 + weights.y * v1 + weights.z * v2)); } template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2) @@ -66,7 +66,7 @@ template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v template<> inline int mix3(const float3 &weights, const int &v0, const int &v1, const int &v2) { - return static_cast(weights.x * v0 + weights.y * v1 + weights.z * v2); + return static_cast(std::round(weights.x * v0 + weights.y * v1 + weights.z * v2)); } template<> @@ -131,12 +131,12 @@ template<> inline bool mix2(const float factor, const bool &a, const bool &b) template<> inline int8_t mix2(const float factor, const int8_t &a, const int8_t &b) { - return static_cast((1.0f - factor) * a + factor * b); + return static_cast(std::round((1.0f - factor) * a + factor * b)); } template<> inline int mix2(const float factor, const int &a, const int &b) { - return static_cast((1.0f - factor) * a + factor * b); + return static_cast(std::round((1.0f - factor) * a + factor * b)); } template<> inline float mix2(const float factor, const float &a, const float &b) @@ -356,7 +356,7 @@ template<> struct DefaultMixerStruct { template<> struct DefaultMixerStruct { static int double_to_int(const double &value) { - return static_cast(value); + return static_cast(std::round(value)); } /* Store interpolated ints in a double temporarily, so that weights are handled correctly. It * uses double instead of float so that it is accurate for all 32 bit integers. */ @@ -375,7 +375,7 @@ template<> struct DefaultMixerStruct { template<> struct DefaultMixerStruct { static int8_t float_to_int8_t(const float &value) { - return static_cast(value); + return static_cast(std::round(value)); } /* Store interpolated 8 bit integers in a float temporarily to increase accuracy. */ using type = SimpleMixerWithAccumulationType; diff --git a/source/blender/blenlib/BLI_math_base.hh b/source/blender/blenlib/BLI_math_base.hh index 81f5343056e..034c6968c94 100644 --- a/source/blender/blenlib/BLI_math_base.hh +++ b/source/blender/blenlib/BLI_math_base.hh @@ -108,12 +108,20 @@ template))> inline T interpolate(const T &a, const T &b, const FactorT &t) { - return a * (1 - t) + b * t; + auto result = a * (1 - t) + b * t; + if constexpr (std::is_integral_v && std::is_floating_point_v) { + result = std::round(result); + } + return result; } template inline T midpoint(const T &a, const T &b) { - return (a + b) * T(0.5); + auto result = (a + b) * T(0.5); + if constexpr (std::is_integral_v) { + result = std::round(result); + } + return result; } } // namespace blender::math -- cgit v1.2.3