[Bf-blender-cvs] [2e70af5cd52] blender-v3.2-release: Fix T97761: incorrect mixing of integers

Jacques Lucke noreply at git.blender.org
Wed May 18 17:02:52 CEST 2022


Commit: 2e70af5cd527e2c1f40e6f3af22adc3337714744
Author: Jacques Lucke
Date:   Wed May 18 17:00:19 2022 +0200
Branches: blender-v3.2-release
https://developer.blender.org/rB2e70af5cd527e2c1f40e6f3af22adc3337714744

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

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

M	source/blender/blenkernel/BKE_attribute_math.hh
M	source/blender/blenlib/BLI_math_base.hh

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

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<typename T> 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<int8_t>(weights.x * v0 + weights.y * v1 + weights.z * v2);
+  return static_cast<int8_t>(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<int>(weights.x * v0 + weights.y * v1 + weights.z * v2);
+  return static_cast<int>(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<int8_t>((1.0f - factor) * a + factor * b);
+  return static_cast<int8_t>(std::round((1.0f - factor) * a + factor * b));
 }
 
 template<> inline int mix2(const float factor, const int &a, const int &b)
 {
-  return static_cast<int>((1.0f - factor) * a + factor * b);
+  return static_cast<int>(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<ColorGeometry4b> {
 template<> struct DefaultMixerStruct<int> {
   static int double_to_int(const double &value)
   {
-    return static_cast<int>(value);
+    return static_cast<int>(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<bool> {
 template<> struct DefaultMixerStruct<int8_t> {
   static int8_t float_to_int8_t(const float &value)
   {
-    return static_cast<int8_t>(value);
+    return static_cast<int8_t>(std::round(value));
   }
   /* Store interpolated 8 bit integers in a float temporarily to increase accuracy. */
   using type = SimpleMixerWithAccumulationType<int8_t, float, float_to_int8_t>;
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<typename T,
          BLI_ENABLE_IF((is_math_float_type<FactorT>))>
 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<T> && std::is_floating_point_v<FactorT>) {
+    result = std::round(result);
+  }
+  return result;
 }
 
 template<typename T> 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<T>) {
+    result = std::round(result);
+  }
+  return result;
 }
 
 }  // namespace blender::math



More information about the Bf-blender-cvs mailing list