Advertisement
Bisqwit

math.hh in prender2

Apr 6th, 2020
819
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 18.62 KB | None | 0 0
  1. #ifndef bqtPrender2_MathHH
  2. #define bqtPrender2_MathHH
  3.  
  4. #include <type_traits> // std::decay_t
  5. #include <functional>
  6. #include <cmath>
  7. //#include <cstring> // memcmp
  8. //#include <numeric> // std::inner_product
  9. #include <algorithm> // std::transform
  10.  
  11. /* Contents of this include header:
  12.     vec<T,N>
  13.       xy<T>  = alias to vec<T,2>
  14.       xyz<T> = alias to vec<T,3>
  15.     mat<T,N>
  16.     quat<T>
  17.     Plane
  18.     overlap(a0,a1, b0,b1)
  19.     IntersectBox(amin,amax, bmin,bmax)
  20.  */
  21.  
  22. template<typename T, unsigned N> struct vec;
  23.  
  24. template<typename T, typename U> struct arith_result { typedef decltype(T() + U()) type; };
  25. template<typename T>             struct arith_result<T,T> { typedef T type; };
  26. template<typename T, unsigned M,typename F> struct arith_result<T, vec<F,M>> : public arith_result<T,F> {};
  27. template<typename T, unsigned M,typename F> struct arith_result<vec<F,M>,T> : public arith_result<T,F> {};
  28.  
  29. template<typename T, typename U> struct multiply_result : public arith_result<T,U> {};
  30. template<> struct multiply_result<int,int> { typedef long long type; };
  31.  
  32. template<typename T, typename U> using multiply_result_t = typename multiply_result<std::decay_t<T>,std::decay_t<U>>::type;
  33. template<typename T, typename U> using arith_result_t = typename arith_result<std::decay_t<T>,std::decay_t<U>>::type;
  34.  
  35.  
  36. template<typename T, unsigned N, typename U>
  37. auto CrossProduct(const vec<T,N>& a, const vec<U,N>& b);
  38.  
  39. template<typename U,typename>              struct disallow_vec { typedef U type; };
  40. template<typename U,unsigned M,typename F> struct disallow_vec<U,vec<F,M>> { };
  41. template<typename U,typename T>            using disallow_vec_t = typename disallow_vec<std::decay_t<U>,std::decay_t<T>>::type;
  42.  
  43. #define VEC_GENERIC_METHODS(name) \
  44.     typedef T value_type; \
  45.     static constexpr unsigned size() { return N; } \
  46.     \
  47.     template<typename... Rest> \
  48.     name(Rest&&... rest) : d{} \
  49.     { \
  50.         Assign<0u>(std::forward<Rest>(rest)...); \
  51.     } \
  52.     void Reset() \
  53.     { \
  54.         *this = vec<T,N>(); \
  55.     } \
  56.     void Normalize() \
  57.     { \
  58.         auto len = Length(); \
  59.         if(len <= T(1e-30)) { Reset(); return; } \
  60.         *this *= ( T(T(1) / len) ); \
  61.     } \
  62.     template<typename U> \
  63.     auto DotProduct(const vec<U,N>& b) const { return (*this * b).HorizontalSum(); } \
  64.     auto DotProduct(vec<T,N>        b) const { return (*this * b).HorizontalSum(); } \
  65.     \
  66.     auto Normalized() const { vec<T,N> r{*this}; r.Normalize(); return r; } \
  67.     auto DotSelf() const { return this->DotProduct(*this); } \
  68.     auto Length() const { return std::sqrt(DotSelf()); } \
  69.     \
  70.     template<typename U> bool operator==(const vec<U,N>& b) const \
  71.     { \
  72.         for(unsigned n=0; n<N; ++n) if( (*this)[n] != b[n]) return false; \
  73.         return true; \
  74.     } \
  75.     template<typename U> bool operator!=(const vec<U,N>& b) const \
  76.     { \
  77.         for(unsigned n=0; n<N; ++n) if( (*this)[n] != b[n]) return true; \
  78.         return false; \
  79.     } \
  80.     template<typename U> bool operator<(const vec<U,N>& b) const \
  81.     { \
  82.         for(unsigned n=0; n<N; ++n) if((*this)[n] != b[n]) return (*this)[n] < b[n]; \
  83.         return false; \
  84.     } \
  85.     \
  86.     template<unsigned First, typename... Rest> \
  87.     inline void PartialAssign(Rest&&... rest) \
  88.     { \
  89.         Assign<First>(std::forward<Rest>(rest)..., nullptr); \
  90.     } \
  91.     template<unsigned M, unsigned First=0> vec<T,M> Limit() const \
  92.     { \
  93.         static_assert(First+M <= N, "Limit: Out of range"); \
  94.         vec<T,M> result; \
  95.         for(unsigned n=0; n<M; ++n) result.set(n, (*this)[First+n]); \
  96.         return result; \
  97.     } \
  98. private: \
  99.     template<unsigned index, typename U, unsigned N2, typename... Rest> \
  100.     inline void Assign(const vec<U,N2>& b, Rest&&... rest) \
  101.     { \
  102.         static_assert(index+N2 <= N, "Assign: Too many parameters"); \
  103.         for(unsigned n=0; n<N2; ++n) this->set(index+n, b[n]); \
  104.         /*std::copy(b.d, b.d+N2, (*this)+index);*/ \
  105.         Assign<index+N2>(std::forward<Rest>(rest)...); \
  106.     } \
  107.     template<unsigned index, typename V, typename... Rest> \
  108.     inline disallow_vec_t<void, std::decay_t<V>> Assign(V&& v, Rest&&... rest) \
  109.     { \
  110.         static_assert(index<N, "Assign: Too many parameters"); \
  111.         this->set(index, std::forward<V>(v)); \
  112.         Assign<index+1>(std::forward<Rest>(rest)...); \
  113.     } \
  114.     template<unsigned index> \
  115.     inline void Assign() \
  116.     { \
  117.         static_assert(index == 0 || index >= N, "Assign: Too few parameters"); \
  118.     } \
  119.     template<unsigned index> \
  120.     inline void Assign(std::nullptr_t) \
  121.     { \
  122.     } \
  123. public: \
  124.     /* Promote both operands to a vector of the result type if possible */ \
  125.     template<typename U> std::enable_if_t<!std::is_same<T,U>::value, vec<arith_result_t<T,U>,N>> operator+(const vec<U,N>& b) const \
  126.     { \
  127.         typedef vec<arith_result_t<T,U>,N> R; \
  128.         return R((const vec<T,N>&)*this) + R(b); \
  129.     } \
  130.     template<typename U> std::enable_if_t<!std::is_same<T,U>::value, vec<arith_result_t<T,U>,N>> operator-(const vec<U,N>& b) const \
  131.     { \
  132.         typedef vec<arith_result_t<T,U>,N> R; \
  133.         return R((const vec<T,N>&)*this) - R(b); \
  134.     } \
  135.     template<typename U> std::enable_if_t<!std::is_same<T,U>::value, vec<multiply_result_t<T,U>,N>> operator*(const vec<U,N>& b) const \
  136.     { \
  137.         typedef vec<multiply_result_t<T,U>,N> R; \
  138.         return R((const vec<T,N>&)*this) * R(b); \
  139.     } \
  140.     template<typename U> std::enable_if_t<!std::is_same<T,U>::value, vec<arith_result_t<T,U>,N>> operator/(const vec<U,N>& b) const \
  141.     { \
  142.         typedef vec<arith_result_t<T,U>,N> R; \
  143.         return R((const vec<T,N>&)*this) / R(b); \
  144.     } \
  145.     /* Arithmetic operators with basic operands */ \
  146.     template<typename U> disallow_vec_t<vec<arith_result_t<T,U>,N>,U> operator+(U&& b) const \
  147.     { \
  148.         vec<arith_result_t<T,U>,N> result; \
  149.         for(unsigned n=0; n<N; ++n) result.set(n, (*this)[n] + std::forward<U>(b)); \
  150.         return result; \
  151.     } \
  152.     template<typename U> disallow_vec_t<vec<arith_result_t<T,U>,N>,U> operator-(U&& b) const \
  153.     { \
  154.         vec<arith_result_t<T,U>,N> result; \
  155.         for(unsigned n=0; n<N; ++n) result.set(n, (*this)[n] - std::forward<U>(b)); \
  156.         return result; \
  157.     } \
  158.     template<typename U> disallow_vec_t<vec<multiply_result_t<T,U>,N>,U> operator*(U&& b) const \
  159.     { \
  160.         vec<multiply_result_t<T,U>,N> result; \
  161.         for(unsigned n=0; n<N; ++n) result.set(n, (*this)[n] * std::forward<U>(b)); \
  162.         return result; \
  163.     } \
  164.     template<typename U> disallow_vec_t<vec<arith_result_t<T,U>,N>,U> operator/(U&& b) const \
  165.     { \
  166.         vec<arith_result_t<T,U>,N> result; \
  167.         for(unsigned n=0; n<N; ++n) result.set(n, (*this)[n] / std::forward<U>(b)); \
  168.         return result; \
  169.     } \
  170.     /* Promote the second operand to the target type if possible */ \
  171.     template<typename U> std::enable_if_t<!std::is_same<T,U>::value, vec<T,N>&> operator+=(const vec<U,N>& b) const \
  172.     { \
  173.         return *this += vec<T,N>(b); \
  174.     } \
  175.     template<typename U> std::enable_if_t<!std::is_same<T,U>::value, vec<T,N>&> operator-=(const vec<U,N>& b) const \
  176.     { \
  177.         return *this -= vec<T,N>(b); \
  178.     } \
  179.     template<typename U> std::enable_if_t<!std::is_same<T,U>::value, vec<T,N>&> operator*=(const vec<U,N>& b) const \
  180.     { \
  181.         return *this *= vec<T,N>(b); \
  182.     } \
  183.     template<typename U> std::enable_if_t<!std::is_same<T,U>::value, vec<T,N>&> operator/=(const vec<U,N>& b) const \
  184.     { \
  185.         return *this /= vec<T,N>(b); \
  186.     } \
  187.     /* Generic RMW operators */ \
  188.     template<typename U> auto& operator+=(U&& b) { return *this = *this + std::forward<U>(b); } \
  189.     template<typename U> auto& operator-=(U&& b) { return *this = *this - std::forward<U>(b); } \
  190.     template<typename U> auto& operator*=(U&& b) { return *this = *this * std::forward<U>(b); } \
  191.     template<typename U> auto& operator/=(U&& b) { return *this = *this / std::forward<U>(b); }
  192.  
  193. template<typename T, unsigned N>
  194. struct vec
  195. {
  196. private:
  197.     T d[N];
  198. public:
  199.     VEC_GENERIC_METHODS(vec)
  200. public:
  201.     vec() : d{} {}
  202.  
  203.     inline const T& operator[](unsigned n) const { return d[n]; }
  204.     template<typename U>
  205.     inline void set(unsigned n, U&& v) { d[n] = std::forward<U>(v); }
  206.  
  207.     #pragma omp declare simd
  208.     T HorizontalSum() const
  209.     {
  210.         T result{};
  211.         #pragma omp simd
  212.         for(unsigned n=0; n<N; ++n) result += d[n];
  213.         return result;
  214.     }
  215.  
  216.     #pragma omp declare simd
  217.     void clamp(T min, T max)
  218.     {
  219.         #pragma omp simd
  220.         for(unsigned n=0; n<N; ++n)
  221.             set(n, std::min(std::max((*this)[n], min), max));
  222.     }
  223.  
  224.     template<typename U>
  225.     inline auto CrossProduct(const vec<U,N>& b) const;
  226.  
  227.     /* Arithmetic operators with vector operands */
  228.     vec<T,N> operator+ (const vec<T,N>& b) const
  229.     {
  230.         vec<T,N> result = *this;
  231.         for(unsigned n=0; n<N; ++n) result.set(n, result[n] + b[n]);
  232.         return result;
  233.     }
  234.     vec<T,N> operator- (const vec<T,N>& b) const
  235.     {
  236.         vec<T,N> result = *this;
  237.         for(unsigned n=0; n<N; ++n) result.set(n, result[n] - b[n]);
  238.         return result;
  239.     }
  240.     vec<T,N> operator* (const vec<T,N>& b) const
  241.     {
  242.         vec<T,N> result = *this;
  243.         for(unsigned n=0; n<N; ++n) result.set(n, result[n] * b[n]);
  244.         return result;
  245.     }
  246.     vec<T,N> operator/ (const vec<T,N>& b) const
  247.     {
  248.         vec<T,N> result = *this;
  249.         for(unsigned n=0; n<N; ++n) result.set(n, result[n] / b[n]);
  250.         return result;
  251.     }
  252.     vec<T,N> operator-() const
  253.     {
  254.         vec<T, N> result = *this;
  255.         #pragma omp simd
  256.         for(unsigned n=0; n<N; ++n) result.set(n, -result[n]);
  257.         return result;
  258.     }
  259. };
  260.  
  261. template<typename T, typename U>
  262. auto CrossProduct(const vec<T,2>& a, const vec<U,2>& b)
  263. {
  264.     auto mult = vec<U,2>(b[1],b[0]) * a;
  265.     return mult[0] - mult[1];
  266. }
  267. template<typename T, typename U>
  268. auto CrossProduct(const vec<T,3>& a, const vec<U,3>& b)
  269. {
  270.     auto mult = vec<T,8>{0, a[1],a[2],a[0],  0, a[2],a[0],a[1]}
  271.               * vec<U,8>{0, b[2],b[0],b[1],  0, b[1],b[2],b[0]};
  272.     return (mult.template Limit<4,0>() - mult.template Limit<4,4>()).template Limit<3,1>();
  273. }
  274.  
  275.  
  276. #if defined(__has_include)
  277.  #if __has_include("math_simd.hh")
  278.   #include "math_simd.hh"
  279.  #endif
  280. #endif
  281.  
  282.  
  283. template<typename T> struct vec<T,0>
  284. {
  285. public:
  286.     vec() {}
  287.     vec(const vec<T,0>& ) {}
  288.  
  289.     T operator[](unsigned) const { return {}; }
  290.     template<typename U> inline void set(unsigned, U&& ) {}
  291.  
  292.     T HorizontalSum() const { return {}; }
  293.     T DotProduct(const vec<T,0>& ) const { return {}; }
  294.     template<typename U> vec<T,0> operator+ (U&& ) const { return *this; }
  295.     template<typename U> vec<T,0> operator- (U&& ) const { return *this; }
  296.     template<typename U> vec<T,0> operator* (U&& ) const { return *this; }
  297.     template<typename U> vec<T,0> operator/ (U&& ) const { return *this; }
  298.     template<typename U> vec<T,0>& operator+= (U&& ) { return *this; }
  299.     template<typename U> vec<T,0>& operator-= (U&& ) { return *this; }
  300.     template<typename U> vec<T,0>& operator*= (U&& ) { return *this; }
  301.     template<typename U> vec<T,0>& operator/= (U&& ) { return *this; }
  302.     vec<T,0> operator- () const { return *this; }
  303.     void clamp(T,T) {}
  304. };
  305.  
  306.  
  307.  
  308. template<typename T> using xy  = vec<T,2>;
  309. template<typename T> using xyz = vec<T,3>;
  310.  
  311.  
  312. template<typename T,unsigned N> template<typename U>
  313. inline auto vec<T,N>::CrossProduct(const vec<U,N>& b) const
  314. {
  315.     return ::CrossProduct(*this, b);
  316. }
  317.  
  318.  
  319. template<typename T, unsigned N>
  320. struct mat
  321. {
  322.     vec<T,N> d[N];
  323.  
  324.     template<typename U>
  325.     auto Transform(const vec<U,N>& v) const
  326.     {
  327.         return transform(v, std::make_index_sequence<N>());
  328.     }
  329.  
  330.     template<typename U>
  331.     auto operator* (const mat<U,N>& m) const
  332.     {
  333.         return multiply(m, std::make_index_sequence<N>());
  334.     }
  335.     template<typename U>
  336.     mat<T,N>& operator*= (const mat<U,N>& b) { return *this = (*this) * b; }
  337.  
  338. private:
  339.     template<typename U, std::size_t... Indexes>
  340.     auto transform(const vec<U,N>& v, std::index_sequence<Indexes...>) const
  341.     {
  342.         return vec<multiply_result_t<T,U>,N> { v.DotProduct(d[Indexes]) ... };
  343.     }
  344.  
  345.     template<typename U, std::size_t... Indexes>
  346.     auto multiply(const mat<U,N>& m, std::index_sequence<Indexes...>) const
  347.     {
  348.         mat<multiply_result_t<T,U>,N> r;
  349.         //#pragma omp simd collapse(2)
  350.         for(unsigned i=0; i<N; ++i)
  351.             for(unsigned j=0; j<N; ++j)
  352.                 r.d[i].set(j, (d[i] * vec<T,N> { m.d[Indexes][j]... }).HorizontalSum());
  353.         return r;
  354.     }
  355. };
  356.  
  357. template<typename T>
  358. struct quat : private vec<T,4> /* quaternion. a, x,y,z */
  359. {
  360.     quat() : vec<T,4>{1, 0,0,0} {}
  361.  
  362.     template<typename U>
  363.     quat(U a,U b,U c,U d) : vec<T,4>{a,b,c,d} {}
  364.  
  365.     template<typename U, typename H>
  366.     quat(xyz<U>&& refvec, H theta) { FromAngle(theta, refvec); }
  367.  
  368.     quat(vec<T,4> refvec) : vec<T,4>(refvec) {}
  369.  
  370.     quat(const mat<T,3>& rot) { FromMatrix(rot); }
  371.  
  372.     using vec<T,4>::operator[];
  373.  
  374.     void Reset() { *this = {1, 0,0,0}; }
  375.  
  376.     template<typename H, typename U>
  377.     void FromAngle(H theta, const xyz<U>& vector)
  378.     {
  379.         auto c = std::cos(theta * H(H(1)/H(2)));
  380.         auto s = std::sin(theta * H(H(1)/H(2)));
  381.         vec<T,4>::operator=( vec<T,4>(1,vector) * vec<T,4>(c,s,s,s) );
  382.         //a  =          c;
  383.         //v3 = vector * s;
  384.     }
  385.     mat<T,3> MakeMatrix() const
  386.     {
  387.         auto a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3];
  388.         return {{{a*a + b*b - c*c - d*d, 2*(b*c - a*d),          2*(b*d + a*c)},
  389.                  {2*(b*c + a*d),         a*a - b*b +  c*c - d*d, 2*(c*d - a*b)},
  390.                  {2*(b*d - a*c),         2*(c*d + a*b),          a*a - b*b - c*c + d*d}}};
  391.     };
  392.     // Optimization when we know this is a unit quaternion
  393.     mat<T,3> MakeMatrix_unit() const
  394.     {
  395.         auto a = (*this)[0], b = (*this)[1], c = (*this)[2], d = (*this)[3];
  396.         return {{{T(1) - 2*(c*c + d*d), 2*(b*c - a*d),        2*(b*d + a*c)},
  397.                  {2*(b*c + a*d),        T(1) - 2*(b*b + d*d), 2*(c*d - a*b)},
  398.                  {2*(b*d - a*c),        2*(c*d + a*b),        T(1) - 2*(b*b + c*c)}}};
  399.     };
  400.     void FromMatrix(const mat<T,3>& rot)
  401.     {
  402.         /* From
  403.          * http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/
  404.          */
  405.         const T m00 = rot.d[0][0], m01 = rot.d[0][1], m02 = rot.d[0][2];
  406.         const T m10 = rot.d[1][0], m11 = rot.d[1][1], m12 = rot.d[1][2];
  407.         const T m20 = rot.d[2][0], m21 = rot.d[2][1], m22 = rot.d[2][2];
  408.         T tr = m00 + m11 + m22, S;
  409.         vec<T,4>& vek = *this;
  410.         if (tr > 0)                      vek = { S = 1.0f + tr,              m21-m12, m02-m20, m10-m01 };
  411.         else if (m00 > m11 && m00 > m22) vek = { m21-m12, S = 1.0f + m00 - m11 - m22, m01+m10, m02+m20 };
  412.         else if (m11 > m22)              vek = { m02-m20, m01+m10, S = 1.0f + m11 - m00 - m22, m12+m21 };
  413.         else                             vek = { m10-m01, m02+m20, m12+m21, S = 1.0f + m22 - m00 - m11 };
  414.         vek *= (0.5f / std::sqrt(S));
  415.     }
  416.  
  417.     template<typename U>
  418.     quat<multiply_result_t<T,U>> operator* (const quat<U>& o) const
  419.     {
  420.         return { (vec<U,4>{ o[0],-o[1],-o[2],-o[3] } * (const vec<T,4>&)(*this)).HorizontalSum(),
  421.                  (vec<U,4>{ o[1], o[0], o[3],-o[2] } * (const vec<T,4>&)(*this)).HorizontalSum(),
  422.                  (vec<U,4>{ o[2],-o[3], o[0], o[1] } * (const vec<T,4>&)(*this)).HorizontalSum(),
  423.                  (vec<U,4>{ o[3], o[2],-o[1], o[0] } * (const vec<T,4>&)(*this)).HorizontalSum() };
  424.     }
  425.     template<typename U>
  426.     quat<T>& operator*= (const quat<U>& o) { return *this = *this * o; }
  427.  
  428.     void Invert()
  429.     {
  430.         for(unsigned n=1; n<4; ++n) this->set(n, -(*this)[n]);
  431.         // Note: [0] must not be negated
  432.     }
  433.     void Normalize()
  434.     {
  435.         auto len = this->Length();
  436.         if(std::abs(len - T(1)) < T(T(1) / T(1 << 6))) return; // Don't normalize if there's no need.
  437.         if(len <= T(1e-30)) { Reset(); return; }
  438.         *this /= len;
  439.     }
  440.  
  441.     quat<T> Inverted() const { return {(*this)[0], -(*this)[1], -(*this)[2], -(*this)[3]}; }
  442.     quat<T> Normalized() const { quat<T> r { *this }; r.Normalize(); return r; }
  443. };
  444.  
  445. struct Plane: private vec<double,4>
  446. {
  447.     Plane() : vec() {}
  448.     Plane(const vec<double,4>& b) : vec(b) {}
  449.  
  450.     template<typename T>
  451.     Plane(const xyz<T>& a, const xyz<T>& b, const xyz<T>& c)
  452.     {
  453.         xyz<T> normal{(b-a).CrossProduct(c-a).Normalized()};
  454.         *this = vec(normal, normal.DotProduct(a));
  455.     }
  456.  
  457.     inline xyz<double> Normal() const { return Limit<3>(); }
  458.     inline double Distance() const    { return (*this)[3]; }
  459.  
  460.     void Invert() { *this = -*this; }
  461.     Plane Inverted() const { return -*this; }
  462.  
  463.     double DistanceTo(const xyz<double>& point) const
  464.     {
  465.         return Normal().DotProduct(point) - Distance();
  466.     }
  467.  
  468.     bool IsCoplanar(const Plane& b) const
  469.     {
  470.         return (Normal() - b.Normal()).DotSelf() < 1e-8
  471.              && std::abs(Distance() - b.Distance()) < 1e-8;
  472.     }
  473.     bool IsOpposite(const Plane& b) const
  474.     {
  475.         return Inverted().IsCoplanar(b);
  476.     }
  477.     bool IsCoplanarOrOpposite(const Plane& b) const
  478.     {
  479.         return IsCoplanar(b) || IsOpposite(b);
  480.     }
  481. };
  482. /*namespace std
  483. {
  484.     template<> struct hash<Plane>
  485.     { std::size_t operator() (const Plane& b) const {
  486.     return std::hash<std::string>() ( std::string( (const char*)&b, (const char*)&b + sizeof(b) ) );
  487.       }
  488.     };
  489.     template<typename T,unsigned N> struct hash<vec<T,N>>
  490.     { std::size_t operator() (const vec<T,N>& b) const {
  491.     return std::hash<std::string>() ( std::string( (const char*)&b, (const char*)&b + sizeof(b) ) );
  492.       }
  493.     };
  494.  
  495.     template<typename T,unsigned N, typename U>
  496.     vec<T,N> pow(const vec<T,N>& a, const U& power)
  497.     {
  498.         vec<T,N> result;
  499.         #pragma omp simd
  500.         for(unsigned n=0; n<N; ++n) result.set(n, std::pow(a[n], power));
  501.         return result;
  502.     }
  503. }*/
  504.  
  505. template<typename T, typename U>
  506. inline bool overlap(const T& a0, const T& a1, const U& b0, const U& b1)
  507.     { return std::min(a0,a1) <= std::max(b0,b1) && std::min(b0,b1) <= std::max(a0,a1); }
  508.  
  509. template<typename T,typename U,unsigned N>
  510. inline bool IntersectBox(const vec<T,N>& amin, const vec<T,N>& amax,
  511.                          const vec<U,N>& bmin, const vec<U,N>& bmax)
  512. {
  513.     for(unsigned n=0; n<N; ++n)
  514.         if(!overlap(amin[n],amax[n], bmin[n],bmax[n]))
  515.             return false;
  516.     return true;
  517. }
  518.  
  519. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement