From 243296db6a55d43e39a028a2478359de4dc18dab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 10 Jan 2022 19:20:59 +0100 Subject: Rework macro name and add manhattan distance & Length functions --- source/blender/blenlib/BLI_math_vec_types.hh | 150 +++++++++++++-------------- source/blender/blenlib/BLI_math_vector.hh | 104 ++++++++++++------- 2 files changed, 144 insertions(+), 110 deletions(-) diff --git a/source/blender/blenlib/BLI_math_vec_types.hh b/source/blender/blenlib/BLI_math_vec_types.hh index 9ba29d41684..ae8cb0056bb 100644 --- a/source/blender/blenlib/BLI_math_vec_types.hh +++ b/source/blender/blenlib/BLI_math_vec_types.hh @@ -93,22 +93,22 @@ template struct vec_base : public vec_struct_base } /* Workaround issue with template. */ -#define BLI_VEC_ENABLE_IF(_size, _test) int S = _size, BLI_ENABLE_IF((S _test)) +#define BLI_ENABLE_IF_VEC(_size, _test) int S = _size, BLI_ENABLE_IF((S _test)) - template vec_base(T _x, T _y) + template vec_base(T _x, T _y) { (*this)[0] = _x; (*this)[1] = _y; } - template vec_base(T _x, T _y, T _z) + template vec_base(T _x, T _y, T _z) { (*this)[0] = _x; (*this)[1] = _y; (*this)[2] = _z; } - template vec_base(T _x, T _y, T _z, T _w) + template vec_base(T _x, T _y, T _z, T _w) { (*this)[0] = _x; (*this)[1] = _y; @@ -118,52 +118,52 @@ template struct vec_base : public vec_struct_base /** Mixed scalar-vector constructors. */ - template + template constexpr vec_base(const vec_base &xy, T z) : vec_base(static_cast(xy.x), static_cast(xy.y), z) { } - template + template constexpr vec_base(T x, const vec_base &yz) : vec_base(x, static_cast(yz.x), static_cast(yz.y)) { } - template + template vec_base(vec_base xyz, T w) : vec_base( static_cast(xyz.x), static_cast(xyz.y), static_cast(xyz.z), static_cast(w)) { } - template + template vec_base(T x, vec_base yzw) : vec_base( static_cast(x), static_cast(yzw.x), static_cast(yzw.y), static_cast(yzw.z)) { } - template + template vec_base(vec_base xy, vec_base zw) : vec_base( static_cast(xy.x), static_cast(xy.y), static_cast(zw.x), static_cast(zw.y)) { } - template + template vec_base(vec_base xy, T z, T w) : vec_base(static_cast(xy.x), static_cast(xy.y), static_cast(z), static_cast(w)) { } - template + template vec_base(T x, vec_base yz, T w) : vec_base(static_cast(x), static_cast(yz.x), static_cast(yz.y), static_cast(w)) { } - template + template vec_base(T x, T y, vec_base zw) : vec_base(static_cast(x), static_cast(y), static_cast(zw.x), static_cast(zw.y)) { @@ -171,17 +171,17 @@ template struct vec_base : public vec_struct_base /** Masking. */ - template= 3)> explicit operator vec_base() const + template= 3)> explicit operator vec_base() const { return vec_base(UNPACK2(*this)); } - template= 4)> explicit operator vec_base() const + template= 4)> explicit operator vec_base() const { return vec_base(UNPACK3(*this)); } -#undef BLI_VEC_ENABLE_IF +#undef BLI_ENABLE_IF_VEC /** Conversion from pointers (from C-style vectors). */ @@ -235,16 +235,16 @@ template struct vec_base : public vec_struct_base /** Internal Operators Macro. */ -#define VEC_INT_OP(_T) template))> +#define BLI_INT_OP(_T) template))> -#define BLI_VEC_OP(_result, _i, _op) \ +#define BLI_VEC_OP_IMPL(_result, _i, _op) \ vec_base _result; \ for (int _i = 0; _i < Size; _i++) { \ _op; \ } \ return _result; -#define BLI_VEC_OP_SELF(_i, _op) \ +#define BLI_VEC_OP_IMPL_SELF(_i, _op) \ for (int _i = 0; _i < Size; _i++) { \ _op; \ } \ @@ -254,12 +254,12 @@ template struct vec_base : public vec_struct_base friend vec_base operator+(const vec_base &a, const vec_base &b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] + b[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] + b[i]); } friend vec_base operator+(const vec_base &a, const T &b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] + b); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] + b); } friend vec_base operator+(const T &a, const vec_base &b) @@ -269,52 +269,52 @@ template struct vec_base : public vec_struct_base vec_base &operator+=(const vec_base &b) { - BLI_VEC_OP_SELF(i, (*this)[i] += b[i]); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] += b[i]); } vec_base &operator+=(const T &b) { - BLI_VEC_OP_SELF(i, (*this)[i] += b); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] += b); } friend vec_base operator-(const vec_base &a) { - BLI_VEC_OP(ret, i, ret[i] = -a[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = -a[i]); } friend vec_base operator-(const vec_base &a, const vec_base &b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] - b[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] - b[i]); } friend vec_base operator-(const vec_base &a, const T &b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] - b); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] - b); } friend vec_base operator-(const T &a, const vec_base &b) { - BLI_VEC_OP(ret, i, ret[i] = a - b[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a - b[i]); } vec_base &operator-=(const vec_base &b) { - BLI_VEC_OP_SELF(i, (*this)[i] -= b[i]); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] -= b[i]); } vec_base &operator-=(const T &b) { - BLI_VEC_OP_SELF(i, (*this)[i] -= b); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] -= b); } friend vec_base operator*(const vec_base &a, const vec_base &b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] * b[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] * b[i]); } friend vec_base operator*(const vec_base &a, T b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] * b); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] * b); } friend vec_base operator*(T a, const vec_base &b) @@ -324,146 +324,146 @@ template struct vec_base : public vec_struct_base vec_base &operator*=(T b) { - BLI_VEC_OP_SELF(i, (*this)[i] *= b); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] *= b); } vec_base &operator*=(const vec_base &b) { - BLI_VEC_OP_SELF(i, (*this)[i] *= b[i]); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] *= b[i]); } friend vec_base operator/(const vec_base &a, const vec_base &b) { BLI_assert(!b.is_any_zero()); - BLI_VEC_OP(ret, i, ret[i] = a[i] / b[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] / b[i]); } friend vec_base operator/(const vec_base &a, T b) { BLI_assert(b != T(0)); - BLI_VEC_OP(ret, i, ret[i] = a[i] / b); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] / b); } friend vec_base operator/(T a, const vec_base &b) { BLI_assert(!b.is_any_zero()); - BLI_VEC_OP(ret, i, ret[i] = a / b[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a / b[i]); } vec_base &operator/=(T b) { BLI_assert(b != T(0)); - BLI_VEC_OP_SELF(i, (*this)[i] /= b); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] /= b); } vec_base &operator/=(const vec_base &b) { BLI_assert(!b.is_any_zero()); - BLI_VEC_OP_SELF(i, (*this)[i] /= b[i]); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] /= b[i]); } /** Binary operators. */ - VEC_INT_OP(T) friend vec_base operator&(const vec_base &a, const vec_base &b) + BLI_INT_OP(T) friend vec_base operator&(const vec_base &a, const vec_base &b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] & b[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] & b[i]); } - VEC_INT_OP(T) friend vec_base operator&(const vec_base &a, T b) + BLI_INT_OP(T) friend vec_base operator&(const vec_base &a, T b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] & b); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] & b); } - VEC_INT_OP(T) friend vec_base operator&(T a, const vec_base &b) + BLI_INT_OP(T) friend vec_base operator&(T a, const vec_base &b) { return b & a; } - VEC_INT_OP(T) vec_base &operator&=(T b) + BLI_INT_OP(T) vec_base &operator&=(T b) { - BLI_VEC_OP_SELF(i, (*this)[i] &= b); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] &= b); } - VEC_INT_OP(T) vec_base &operator&=(const vec_base &b) + BLI_INT_OP(T) vec_base &operator&=(const vec_base &b) { - BLI_VEC_OP_SELF(i, (*this)[i] &= b[i]); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] &= b[i]); } - VEC_INT_OP(T) friend vec_base operator|(const vec_base &a, const vec_base &b) + BLI_INT_OP(T) friend vec_base operator|(const vec_base &a, const vec_base &b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] | b[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] | b[i]); } - VEC_INT_OP(T) friend vec_base operator|(const vec_base &a, T b) + BLI_INT_OP(T) friend vec_base operator|(const vec_base &a, T b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] | b); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] | b); } - VEC_INT_OP(T) friend vec_base operator|(T a, const vec_base &b) + BLI_INT_OP(T) friend vec_base operator|(T a, const vec_base &b) { return b | a; } - VEC_INT_OP(T) vec_base &operator|=(T b) + BLI_INT_OP(T) vec_base &operator|=(T b) { - BLI_VEC_OP_SELF(i, (*this)[i] |= b); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] |= b); } - VEC_INT_OP(T) vec_base &operator|=(const vec_base &b) + BLI_INT_OP(T) vec_base &operator|=(const vec_base &b) { - BLI_VEC_OP_SELF(i, (*this)[i] |= b[i]); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] |= b[i]); } - VEC_INT_OP(T) friend vec_base operator^(const vec_base &a, const vec_base &b) + BLI_INT_OP(T) friend vec_base operator^(const vec_base &a, const vec_base &b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] ^ b[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] ^ b[i]); } - VEC_INT_OP(T) friend vec_base operator^(const vec_base &a, T b) + BLI_INT_OP(T) friend vec_base operator^(const vec_base &a, T b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] ^ b); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] ^ b); } - VEC_INT_OP(T) friend vec_base operator^(T a, const vec_base &b) + BLI_INT_OP(T) friend vec_base operator^(T a, const vec_base &b) { return b ^ a; } - VEC_INT_OP(T) vec_base &operator^=(T b) + BLI_INT_OP(T) vec_base &operator^=(T b) { - BLI_VEC_OP_SELF(i, (*this)[i] ^= b); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] ^= b); } - VEC_INT_OP(T) vec_base &operator^=(const vec_base &b) + BLI_INT_OP(T) vec_base &operator^=(const vec_base &b) { - BLI_VEC_OP_SELF(i, (*this)[i] ^= b[i]); + BLI_VEC_OP_IMPL_SELF(i, (*this)[i] ^= b[i]); } - VEC_INT_OP(T) friend vec_base operator~(const vec_base &a) + BLI_INT_OP(T) friend vec_base operator~(const vec_base &a) { - BLI_VEC_OP(ret, i, ret[i] = ~a[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = ~a[i]); } /** Modulo operators. */ - VEC_INT_OP(T) friend vec_base operator%(const vec_base &a, const vec_base &b) + BLI_INT_OP(T) friend vec_base operator%(const vec_base &a, const vec_base &b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] % b[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] % b[i]); } - VEC_INT_OP(T) friend vec_base operator%(const vec_base &a, T b) + BLI_INT_OP(T) friend vec_base operator%(const vec_base &a, T b) { - BLI_VEC_OP(ret, i, ret[i] = a[i] % b); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a[i] % b); } - VEC_INT_OP(T) friend vec_base operator%(T a, const vec_base &b) + BLI_INT_OP(T) friend vec_base operator%(T a, const vec_base &b) { - BLI_VEC_OP(ret, i, ret[i] = a % b[i]); + BLI_VEC_OP_IMPL(ret, i, ret[i] = a % b[i]); } -#undef VEC_INT_OP -#undef BLI_VEC_OP -#undef BLI_VEC_OP_SELF +#undef BLI_INT_OP +#undef BLI_VEC_OP_IMPL +#undef BLI_VEC_OP_IMPL_SELF /** Compare. */ diff --git a/source/blender/blenlib/BLI_math_vector.hh b/source/blender/blenlib/BLI_math_vector.hh index 2d486783624..c547110a3de 100644 --- a/source/blender/blenlib/BLI_math_vector.hh +++ b/source/blender/blenlib/BLI_math_vector.hh @@ -33,6 +33,8 @@ # include "BLI_math_mpq.hh" #endif +namespace blender::math { + #ifndef NDEBUG # define BLI_ASSERT_UNIT(v) \ { \ @@ -45,19 +47,18 @@ # define BLI_ASSERT_UNIT(v) (void)(v) #endif -namespace blender::math { - #define bT typename T::base_type #ifdef WITH_GMP -# define BLI_IS_FLT_VEC(T) \ +# define BLI_ENABLE_IF_FLT_VEC(T) \ BLI_ENABLE_IF((std::disjunction_v, \ std::is_same>)) #else -# define BLI_IS_FLT_VEC(T) BLI_ENABLE_IF((std::is_floating_point::value)) +# define BLI_ENABLE_IF_FLT_VEC(T) \ + BLI_ENABLE_IF((std::is_floating_point::value)) #endif -#define BLI_IS_INT_VEC BLI_ENABLE_IF((std::is_integral::value)) +#define BLI_ENABLE_IF_INT_VEC(T) BLI_ENABLE_IF((std::is_integral::value)) template inline T abs(const T &a) { @@ -86,8 +87,27 @@ template inline T max(const T &a, const T &b) return result; } -/* Always safe. */ -template inline T mod(const T &a, const T &b) +template inline T mod(const T &a, const T &b) +{ + T result; + for (int i = 0; i < T::type_length; i++) { + BLI_assert(b[i] != 0); + result[i] = std::fmod(a[i], b[i]); + } + return result; +} + +template inline T mod(const T &a, bT b) +{ + BLI_assert(b != 0); + T result; + for (int i = 0; i < T::type_length; i++) { + result[i] = std::fmod(a[i], b); + } + return result; +} + +template inline T safe_mod(const T &a, const T &b) { T result; for (int i = 0; i < T::type_length; i++) { @@ -96,8 +116,7 @@ template inline T mod(const T &a, const T &b) return result; } -/* Always safe. */ -template inline T mod(const T &a, bT b) +template inline T safe_mod(const T &a, bT b) { if (b == 0) { return T(0.0f); @@ -115,7 +134,7 @@ template inline void min_max(const T &vector, T &min_vec, T &max_vec max_vec = max(vector, max_vec); } -template inline T safe_divide(const T &a, const T &b) +template inline T safe_divide(const T &a, const T &b) { T result; for (int i = 0; i < T::type_length; i++) { @@ -124,12 +143,12 @@ template inline T safe_divide(const T &a, const T return result; } -template inline T safe_divide(const T &a, const bT b) +template inline T safe_divide(const T &a, const bT b) { return (b != 0) ? a / b : T(0.0f); } -template inline T floor(const T &a) +template inline T floor(const T &a) { T result; for (int i = 0; i < T::type_length; i++) { @@ -138,7 +157,7 @@ template inline T floor(const T &a) return result; } -template inline T ceil(const T &a) +template inline T ceil(const T &a) { T result; for (int i = 0; i < T::type_length; i++) { @@ -147,7 +166,7 @@ template inline T ceil(const T &a) return result; } -template inline T fract(const T &a) +template inline T fract(const T &a) { T result; for (int i = 0; i < T::type_length; i++) { @@ -156,7 +175,7 @@ template inline T fract(const T &a) return result; } -template inline bT dot(const T &a, const T &b) +template inline bT dot(const T &a, const T &b) { bT result = a[0] * b[0]; for (int i = 1; i < T::type_length; i++) { @@ -165,22 +184,36 @@ template inline bT dot(const T &a, const T &b) return result; } -template inline bT length_squared(const T &a) +template inline bT length_manhattan(const T &a) +{ + bT result = std::abs(a[0]); + for (int i = 1; i < T::type_length; i++) { + result += std::abs(a[i]); + } + return result; +} + +template inline bT length_squared(const T &a) { return dot(a, a); } -template inline bT length(const T &a) +template inline bT length(const T &a) { return std::sqrt(length_squared(a)); } -template inline bT distance_squared(const T &a, const T &b) +template inline bT distance_manhattan(const T &a, const T &b) +{ + return length_manhattan(a - b); +} + +template inline bT distance_squared(const T &a, const T &b) { return length_squared(a - b); } -template inline bT distance(const T &a, const T &b) +template inline bT distance(const T &a, const T &b) { return length(a - b); } @@ -203,13 +236,13 @@ template uint64_t vector_hash(const T &vec) return result; } -template inline T reflect(const T &incident, const T &normal) +template inline T reflect(const T &incident, const T &normal) { BLI_ASSERT_UNIT(normal); return incident - 2.0 * dot(normal, incident) * normal; } -template +template inline T refract(const T &incident, const T &normal, const bT eta) { float dot_ni = dot(normal, incident); @@ -220,7 +253,7 @@ inline T refract(const T &incident, const T &normal, const bT eta) return eta * incident - (eta * dot_ni + sqrt(k)) * normal; } -template inline T project(const T &p, const T &v_proj) +template inline T project(const T &p, const T &v_proj) { if (UNLIKELY(v_proj.is_zero())) { return T(0.0f); @@ -228,12 +261,12 @@ template inline T project(const T &p, const T &v_ return v_proj * (dot(p, v_proj) / dot(v_proj, v_proj)); } -template +template inline T normalize_and_get_length(const T &v, bT &out_length) { out_length = length_squared(v); /* A larger value causes normalize errors in a scaled down models with camera extreme close. */ - constexpr bT threshold = std::is_same::value ? 1.0e-70 : 1.0e-35f; + constexpr bT threshold = std::is_same_v ? 1.0e-70 : 1.0e-35f; if (out_length > threshold) { out_length = sqrt(out_length); return v / out_length; @@ -243,33 +276,34 @@ inline T normalize_and_get_length(const T &v, bT &out_length) return T(0.0); } -template inline T normalize(const T &v) +template inline T normalize(const T &v) { bT len; return normalize_and_get_length(v, len); } -template inline T cross(const T &a, const T &b) +template +inline T cross(const T &a, const T &b) { - BLI_STATIC_ASSERT(T::type_length == 3, ""); return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x}; } -template))> +template)), + BLI_ENABLE_IF((T::type_length == 3))> inline T cross_high_precision(const T &a, const T &b) { - BLI_STATIC_ASSERT(T::type_length == 3, ""); return {(float)((double)a.y * b.z - (double)a.z * b.y), (float)((double)a.z * b.x - (double)a.x * b.z), (float)((double)a.x * b.y - (double)a.y * b.x)}; } -template inline T interpolate(const T &a, const T &b, bT t) +template inline T interpolate(const T &a, const T &b, bT t) { return a * (1 - t) + b * t; } -template +template inline T faceforward(const T &vector, const T &incident, const T &reference) { return (dot(reference, incident) < 0) ? vector : -vector; @@ -283,7 +317,7 @@ template inline int dominant_axis(const T &a) /** Intersections. */ -template struct isect_result { +template struct isect_result { enum { LINE_LINE_COLINEAR = -1, LINE_LINE_NONE = 0, @@ -293,11 +327,11 @@ template struct isect_result { bT lambda; }; -template +template isect_result isect_seg_seg(const T &v1, const T &v2, const T &v3, const T &v4); -#undef BLI_IS_FLT_VEC -#undef BLI_IS_INT_VEC +#undef BLI_ENABLE_IF_FLT_VEC +#undef BLI_ENABLE_IF_INT_VEC #undef bT } // namespace blender::math -- cgit v1.2.3