Commit 52848dbf by David Flynn

maths: allow the usual numeric conversions between Vec3<T> and Vec3<U>

```This makes Vec3<T> perform more like the usual arithmetic types, in
order to avoid having to explicitly perform element wise conversions
when two Vec3<>s have different numeric types.

For instance:
_i = int16_t() + int()                // typeof(_i) == int
vi = Vec3<int16_t>() + Vec3<int>()    // typeof(vi) == Vec3<int>

_d = 1 + 2.0                          // typeof(_d) == double
vd = Vec3<int>(1) + Vec3<double>(2.0) // typeof(vd) == Vec3<double>

vi = Vec3<int>(Vec3<double>())        // typeof(vi) == Vec3<int>
vd = Vec3<double>(Vec3<int>())        // typeof(vd) == Vec3<double>

Be aware, however, that the usual implicit conversions can result
in a loss of precision:

int _i = 1 + 1.5                          // _i == 2;
Vec3<int> vi = Vec3<int>(1) + Vec3<double>(1.5) // vi == Vec3<int>(2)```
parent 6dcd6f29
 ... @@ -42,6 +42,7 @@ ... @@ -42,6 +42,7 @@ #include #include #include #include #include #include #include #include "PCCMisc.h" #include "PCCMisc.h" #include "tables.h" #include "tables.h" ... @@ -89,34 +90,43 @@ public: ... @@ -89,34 +90,43 @@ public: memcpy(data, rhs.data, sizeof(data)); memcpy(data, rhs.data, sizeof(data)); return *this; return *this; } } Vec3& operator+=(const Vec3& rhs) template Vec3& operator+=(const typename pcc::Vec3& rhs) { { data[0] += rhs[0]; data[0] += rhs[0]; data[1] += rhs[1]; data[1] += rhs[1]; data[2] += rhs[2]; data[2] += rhs[2]; return *this; return *this; } } Vec3& operator-=(const Vec3& rhs) template Vec3& operator-=(const typename pcc::Vec3& rhs) { { data[0] -= rhs[0]; data[0] -= rhs[0]; data[1] -= rhs[1]; data[1] -= rhs[1]; data[2] -= rhs[2]; data[2] -= rhs[2]; return *this; return *this; } } Vec3& operator-=(const T a) template Vec3& operator-=(U a) { { data[0] -= a; data[0] -= a; data[1] -= a; data[1] -= a; data[2] -= a; data[2] -= a; return *this; return *this; } } Vec3& operator+=(const T a) template Vec3& operator+=(U a) { { data[0] += a; data[0] += a; data[1] += a; data[1] += a; data[2] += a; data[2] += a; return *this; return *this; } } Vec3& operator<<=(int val) Vec3& operator<<=(int val) { { data[0] <<= val; data[0] <<= val; ... @@ -124,6 +134,7 @@ public: ... @@ -124,6 +134,7 @@ public: data[2] <<= val; data[2] <<= val; return *this; return *this; } } Vec3& operator>>=(int val) Vec3& operator>>=(int val) { { data[0] >>= val; data[0] >>= val; ... @@ -131,7 +142,9 @@ public: ... @@ -131,7 +142,9 @@ public: data[2] >>= val; data[2] >>= val; return *this; return *this; } } Vec3& operator/=(const T a) template Vec3& operator/=(U a) { { assert(a != 0); assert(a != 0); data[0] /= a; data[0] /= a; ... @@ -139,77 +152,141 @@ public: ... @@ -139,77 +152,141 @@ public: data[2] /= a; data[2] /= a; return *this; return *this; } } Vec3& operator*=(const T a) template Vec3& operator*=(U a) { { data[0] *= a; data[0] *= a; data[1] *= a; data[1] *= a; data[2] *= a; data[2] *= a; return *this; return *this; } } Vec3& operator=(const T a) template Vec3& operator=(const U a) { { data[0] = a; data[0] = a; data[1] = a; data[1] = a; data[2] = a; data[2] = a; return *this; return *this; } } Vec3& operator=(const T* const rhs) template Vec3& operator=(const U* rhs) { { data[0] = rhs[0]; data[0] = rhs[0]; data[1] = rhs[1]; data[1] = rhs[1]; data[2] = rhs[2]; data[2] = rhs[2]; return *this; return *this; } } T operator*(const Vec3& rhs) const Vec3 operator-() const { return Vec3(-data[0], -data[1], -data[2]); } template friend Vec3::type> operator+(const Vec3& lhs, const typename pcc::Vec3& rhs) { { return (data[0] * rhs[0] + data[1] * rhs[1] + data[2] * rhs[2]); return Vec3::type>( lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2]); } } Vec3 operator-() const { return Vec3(-data[0], -data[1], -data[2]); } friend Vec3 operator+(const Vec3& lhs, const Vec3& rhs) template friend Vec3::value, typename std::common_type::type>::type> operator+(const U lhs, const Vec3& rhs) { { return Vec3(lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2]); return Vec3::type>( lhs + rhs[0], lhs + rhs[1], lhs + rhs[2]); } } friend Vec3 operator+(const T lhs, const Vec3& rhs) template friend Vec3::value, typename std::common_type::type>::type> operator+(const Vec3& lhs, const U rhs) { { return Vec3(lhs + rhs[0], lhs + rhs[1], lhs + rhs[2]); return Vec3::type>( lhs[0] + rhs, lhs[1] + rhs, lhs[2] + rhs); } } friend Vec3 operator+(const Vec3& lhs, const T rhs) template friend Vec3::type> operator-(const Vec3& lhs, const typename pcc::Vec3& rhs) { { return Vec3(lhs[0] + rhs, lhs[1] + rhs, lhs[2] + rhs); return Vec3::type>( lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]); } } friend Vec3 operator-(const Vec3& lhs, const Vec3& rhs) template friend Vec3::value, typename std::common_type::type>::type> operator-(const U lhs, const Vec3& rhs) { { return Vec3(lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]); return Vec3::type>( lhs - rhs[0], lhs - rhs[1], lhs - rhs[2]); } } friend Vec3 operator-(const T lhs, const Vec3& rhs) template friend Vec3::value, typename std::common_type::type>::type> operator-(const Vec3& lhs, const U rhs) { { return Vec3(lhs - rhs[0], lhs - rhs[1], lhs - rhs[2]); return Vec3::type>( lhs[0] - rhs, lhs[1] - rhs, lhs[2] - rhs); } } friend Vec3 operator-(const Vec3& lhs, const T rhs) template friend Vec3::value, typename std::common_type::type>::type> operator*(const U lhs, const Vec3& rhs) { { return Vec3(lhs[0] - rhs, lhs[1] - rhs, lhs[2] - rhs); return Vec3::type>( lhs * rhs[0], lhs * rhs[1], lhs * rhs[2]); } } friend Vec3 operator*(const T lhs, const Vec3& rhs) // todo(df): make this elementwise? template friend typename std::common_type::type operator*(pcc::Vec3 lhs, const pcc::Vec3& rhs) { { return Vec3(lhs * rhs[0], lhs * rhs[1], lhs * rhs[2]); return (lhs[0] * rhs[0] + lhs[1] * rhs[1] + lhs[2] * rhs[2]); } } friend Vec3 operator*(const Vec3& lhs, const T rhs) template friend Vec3::value, typename std::common_type::type>::type> operator*(const Vec3& lhs, const U rhs) { { return Vec3(lhs[0] * rhs, lhs[1] * rhs, lhs[2] * rhs); return Vec3::type>( lhs[0] * rhs, lhs[1] * rhs, lhs[2] * rhs); } } friend Vec3 operator/(const Vec3& lhs, const T rhs) template friend Vec3::value, typename std::common_type::type>::type> operator/(const Vec3& lhs, const U rhs) { { assert(rhs != 0); assert(rhs != 0); return Vec3(lhs[0] / rhs, lhs[1] / rhs, lhs[2] / rhs); return Vec3::type>( lhs[0] / rhs, lhs[1] / rhs, lhs[2] / rhs); } } friend Vec3 operator<<(const Vec3& lhs, int val) friend Vec3 operator<<(const Vec3& lhs, int val) { { return Vec3(lhs[0] << val, lhs[1] << val, lhs[2] << val); return Vec3(lhs[0] << val, lhs[1] << val, lhs[2] << val); } } friend Vec3 operator>>(const Vec3& lhs, int val) friend Vec3 operator>>(const Vec3& lhs, int val) { { return Vec3(lhs[0] >> val, lhs[1] >> val, lhs[2] >> val); return Vec3(lhs[0] >> val, lhs[1] >> val, lhs[2] >> val); } } bool operator<(const Vec3& rhs) const bool operator<(const Vec3& rhs) const { { if (data[0] == rhs[0]) { if (data[0] == rhs[0]) { ... @@ -220,6 +297,7 @@ public: ... @@ -220,6 +297,7 @@ public: } } return (data[0] < rhs[0]); return (data[0] < rhs[0]); } } bool operator>(const Vec3& rhs) const bool operator>(const Vec3& rhs) const { { if (data[0] == rhs[0]) { if (data[0] == rhs[0]) { ... @@ -230,42 +308,61 @@ public: ... @@ -230,42 +308,61 @@ public: } } return (data[0] > rhs[0]); return (data[0] > rhs[0]); } } bool operator==(const Vec3& rhs) const bool operator==(const Vec3& rhs) const { { return (data[0] == rhs[0] && data[1] == rhs[1] && data[2] == rhs[2]); return (data[0] == rhs[0] && data[1] == rhs[1] && data[2] == rhs[2]); } } bool operator!=(const Vec3& rhs) const bool operator!=(const Vec3& rhs) const { { return (data[0] != rhs[0] || data[1] != rhs[1] || data[2] != rhs[2]); return (data[0] != rhs[0] || data[1] != rhs[1] || data[2] != rhs[2]); } } friend std::ostream& operator<<(std::ostream& os, const Vec3& vec) friend std::ostream& operator<<(std::ostream& os, const Vec3& vec) { { os << vec[0] << " " << vec[1] << " " << vec[2] << std::endl; os << vec[0] << " " << vec[1] << " " << vec[2] << std::endl; return os; return os; } } friend std::istream& operator>>(std::istream& is, Vec3& vec) friend std::istream& operator>>(std::istream& is, Vec3& vec) { { is >> vec[0] >> vec[1] >> vec[2]; is >> vec[0] >> vec[1] >> vec[2]; return is; return is; } } Vec3(const T a) { data[0] = data[1] = data[2] = a; } Vec3(const T a) { data[0] = data[1] = data[2] = a; } Vec3(const T x, const T y, const T z) Vec3(const T x, const T y, const T z) { { data[0] = x; data[0] = x; data[1] = y; data[1] = y; data[2] = z; data[2] = z; } } Vec3(const Vec3& vec) Vec3(const Vec3& vec) { { data[0] = vec.data[0]; data[0] = vec.data[0]; data[1] = vec.data[1]; data[1] = vec.data[1]; data[2] = vec.data[2]; data[2] = vec.data[2]; } } template Vec3(const typename pcc::Vec3& vec) { data[0] = vec.data[0]; data[1] = vec.data[1]; data[2] = vec.data[2]; } Vec3() = default; Vec3() = default; ~Vec3(void) = default; ~Vec3(void) = default; private: private: T data[3]; T data[3]; template friend class pcc::Vec3; }; }; template template ... @@ -299,9 +396,9 @@ struct Box3 { ... @@ -299,9 +396,9 @@ struct Box3 { T getDist2(const Vec3& point) const T getDist2(const Vec3& point) const { { const T dx = std::max(std::max(min[0] - point[0], 0.0), point[0] - max[0]); const T dx = std::max(std::max(min[0] - point[0], T()), point[0] - max[0]); const T dy = std::max(std::max(min[1] - point[1], 0.0), point[1] - max[1]); const T dy = std::max(std::max(min[1] - point[1], T()), point[1] - max[1]); const T dz = std::max(std::max(min[2] - point[2], 0.0), point[2] - max[2]); const T dz = std::max(std::max(min[2] - point[2], T()), point[2] - max[2]); return dx * dx + dy * dy + dz * dz; return dx * dx + dy * dy + dz * dz; } } ... @@ -322,11 +419,12 @@ struct Box3 { ... @@ -322,11 +419,12 @@ struct Box3 { //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // element-wise multiplication of two vectors // element-wise multiplication of two vectors template template Vec3 Vec3::type> times(Vec3 lhs, const Vec3& rhs) times(Vec3 lhs, const Vec3& rhs) { { return Vec3{lhs[0] * rhs[0], lhs[1] * rhs[1], lhs[2] * rhs[2]}; return Vec3::type>( lhs[0] * rhs[0], lhs[1] * rhs[1], lhs[2] * rhs[2]); } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- ... ...
 ... @@ -438,8 +438,7 @@ decodeTrisoupCommon( ... @@ -438,8 +438,7 @@ decodeTrisoupCommon( Vec3 SS = 0; Vec3 SS = 0; for (int j = 0; j < leafVertices.size(); j++) { for (int j = 0; j < leafVertices.size(); j++) { Vec3 S = leafVertices[j].pos - blockCentroid; Vec3 S = leafVertices[j].pos - blockCentroid; SS += {(S[0] * S[0]) >> kTrisoupFpBits, (S[1] * S[1]) >> kTrisoupFpBits, SS += times(S, S) >> kTrisoupFpBits; (S[2] * S[2]) >> kTrisoupFpBits}; } } // Dominant axis is the coordinate minimizing the variance. // Dominant axis is the coordinate minimizing the variance. ... ...
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!