| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525 |
- #ifndef ANKI_MATH_VEC4_H
- #define ANKI_MATH_VEC4_H
- #include "anki/math/CommonIncludes.h"
- namespace anki {
- /// @addtogroup Math
- /// @{
- /// Template struct that gives the type of the TVec4 SIMD
- template<typename T>
- struct TVec4Simd
- {
- typedef Array<T, 4> Type;
- };
- #if ANKI_SIMD == ANKI_SIMD_SSE
- // Specialize for F32
- template<>
- struct TVec4Simd<F32>
- {
- typedef __m128 Type;
- };
- #elif ANKI_SIMD == ANKI_SIMD_NEON
- // Specialize for F32
- template<>
- struct TVec4Simd<F32>
- {
- typedef float32x4_t Type;
- };
- #endif
- /// 4D vector. SIMD optimized
- template<typename T>
- ANKI_ATTRIBUTE_ALIGNED(class, 16) TVec4
- {
- /// @name Friends
- /// @{
- template<typename Y>
- friend TVec4<Y> operator+(const Y f, const TVec4<Y>& v4);
- template<typename Y>
- friend TVec4<Y> operator-(const Y f, const TVec4<Y>& v4);
- template<typename Y>
- friend TVec4<Y> operator*(const Y f, const TVec4<Y>& v4);
- template<typename Y>
- friend TVec4<Y> operator/(const Y f, const TVec4<Y>& v4);
- /// @}
- public:
- typedef typename TVec4Simd<T>::Type Simd;
- /// @name Constructors
- /// @{
- explicit TVec4()
- {}
- explicit TVec4(const T x_, const T y_, const T z_, const T w_)
- {
- x() = x_;
- y() = y_;
- z() = z_;
- w() = w_;
- }
- explicit TVec4(const T f)
- {
- arr[0] = arr[1] = arr[2] = arr[3] = f;
- }
- explicit TVec4(const T arr_[])
- {
- arr[0] = arr_[0];
- arr[1] = arr_[1];
- arr[2] = arr_[2];
- arr[3] = arr_[3];
- }
- explicit TVec4(const TVec2<T>& v2, const T z_, const T w_)
- {
- x() = v2.x();
- y() = v2.y();
- z() = z_;
- w() = w_;
- }
- explicit TVec4(const TVec2<T>& av2, const TVec2<T>& bv2)
- {
- x() = av2.x();
- y() = av2.y();
- z() = bv2.x();
- w() = bv2.y();
- }
- explicit TVec4(const TVec3<T>& v3, const T w_)
- {
- x() = v3.x();
- y() = v3.y();
- z() = v3.z();
- w() = w_;
- }
- TVec4(const TVec4& b)
- {
- x() = b.x();
- y() = b.y();
- z() = b.z();
- w() = b.w();
- }
- explicit TVec4(const TQuat<T>& q)
- {
- x() = q.x();
- y() = q.y();
- z() = q.z();
- w() = q.w();
- }
- explicit TVec4(const Simd& simd_)
- {
- simd = simd_;
- }
- /// @}
- /// @name Accessors
- /// @{
- T& x()
- {
- return vec.x;
- }
- T x() const
- {
- return vec.x;
- }
- T& y()
- {
- return vec.y;
- }
- T y() const
- {
- return vec.y;
- }
- T& z()
- {
- return vec.z;
- }
- T z() const
- {
- return vec.z;
- }
- T& w()
- {
- return vec.w;
- }
- T w() const
- {
- return vec.w;
- }
- T& operator[](const U i)
- {
- return arr[i];
- }
- T operator[](const U i) const
- {
- return arr[i];
- }
- TVec2<T> xy() const
- {
- return TVec2<T>(x(), y());
- }
- TVec3<T> xyz() const
- {
- return TVec3<T>(x(), y(), z());
- }
- Simd& getSimd()
- {
- return simd;
- }
- const Simd& getSimd() const
- {
- return simd;
- }
- /// @}
- /// @name Operators with same type
- /// @{
- TVec4& operator=(const TVec4& b)
- {
- x() = b.x();
- y() = b.y();
- z() = b.z();
- w() = b.w();
- return (*this);
- }
- TVec4 operator+(const TVec4& b) const
- {
- return TVec4(x() + b.x(), y() + b.y(), z() + b.z(), w() + b.w());
- }
- TVec4& operator+=(const TVec4& b)
- {
- x() += b.x();
- y() += b.y();
- z() += b.z();
- w() += b.w();
- return (*this);
- }
- TVec4 operator-(const TVec4& b) const
- {
- return TVec4(x() - b.x(), y() - b.y(), z() - b.z(), w() - b.w());
- }
- TVec4& operator-=(const TVec4& b)
- {
- x() -= b.x();
- y() -= b.y();
- z() -= b.z();
- w() -= b.w();
- return (*this);
- }
- TVec4 operator*(const TVec4& b) const
- {
- return TVec4(x() * b.x(), y() * b.y(), z() * b.z(), w() * b.w());
- }
- TVec4& operator*=(const TVec4& b)
- {
- x() *= b.x();
- y() *= b.y();
- z() *= b.z();
- w() *= b.w();
- return (*this);
- }
- TVec4 operator/(const TVec4& b) const
- {
- return TVec4(x() / b.x(), y() / b.y(), z() / b.z(), w() / b.w());
- }
- TVec4& operator/=(const TVec4& b)
- {
- x() /= b.x();
- y() /= b.y();
- z() /= b.z();
- w() /= b.w();
- return (*this);
- }
- TVec4 operator-() const
- {
- return TVec4(-x(), -y(), -z(), -w());
- }
- Bool operator==(const TVec4& b) const
- {
- TVec4 sub = (*this) - b;
- return isZero<T>(sub.x())
- && isZero<T>(sub.y())
- && isZero<T>(sub.z())
- && isZero<T>(sub.w());
- }
- Bool operator!=(const TVec4& b) const
- {
- return !operator==(b);
- }
- Bool operator<(const TVec4& b) const
- {
- return x() < b.x() && y() < b.y() && z() < b.z() && w() < b.w();
- }
- Bool operator<=(const TVec4& b) const
- {
- return x() <= b.x() && y() <= b.y() && z() <= b.z() && w() <= b.w();
- }
- Bool operator>(const TVec4& b) const
- {
- return x() > b.x() && y() > b.y() && z() > b.z() && w() > b.w();
- }
- Bool operator>=(const TVec4& b) const
- {
- return x() >= b.x() && y() >= b.y() && z() >= b.z() && w() >= b.w();
- }
- /// @}
- /// @name Operators with T
- /// @{
- TVec4 operator+(const T f) const
- {
- return (*this) + TVec4(f);
- }
- TVec4& operator+=(const T f)
- {
- (*this) += TVec4(f);
- return (*this);
- }
- TVec4 operator-(const T f) const
- {
- return (*this) - TVec4(f);
- }
- TVec4& operator-=(const T f)
- {
- (*this) -= TVec4(f);
- return (*this);
- }
- TVec4 operator*(const T f) const
- {
- return (*this) * TVec4(f);
- }
- TVec4& operator*=(const T f)
- {
- (*this) *= TVec4(f);
- return (*this);
- }
- TVec4 operator/(const T f) const
- {
- return (*this) / TVec4(f);
- }
- TVec4& operator/=(const T f)
- {
- (*this) /= TVec4(f);
- return (*this);
- }
- /// @}
- /// @name Operators with other
- /// @{
- /// @note 16 muls 12 adds
- TVec4 operator*(const TMat4<T>& m4) const
- {
- return TVec4(
- x() * m4(0, 0) + y() * m4(1, 0) + z() * m4(2, 0) + w() * m4(3, 0),
- x() * m4(0, 1) + y() * m4(1, 1) + z() * m4(2, 1) + w() * m4(3, 1),
- x() * m4(0, 2) + y() * m4(1, 2) + z() * m4(2, 2) + w() * m4(3, 2),
- x() * m4(0, 3) + y() * m4(1, 3) + z() * m4(2, 3) + w() * m4(3, 3));
- }
- /// @}
- /// @name Other
- /// @{
- T getLength() const
- {
- return sqrt<T>(dot(*this));
- }
- TVec4 getNormalized() const
- {
- return (*this) / getLength();
- }
- void normalize()
- {
- (*this) /= getLength();
- }
- T dot(const TVec4& b) const
- {
- return x() * b.x() + y() * b.y() + z() * b.z() + w() * b.w();
- }
- /// @}
- private:
- /// @name Data
- /// @{
- union
- {
- struct
- {
- T x, y, z, w;
- } vec;
- Array<T, 4> arr;
- Simd simd;
- };
- /// @}
- };
- #if ANKI_SIMD == ANKI_SIMD_SSE
- // Forward declare specializations
- template<>
- TVec4<F32>::TVec4(F32 f);
- template<>
- TVec4<F32>::TVec4(const F32 arr_[]);
- template<>
- TVec4<F32>::TVec4(const F32 x_, const F32 y_, const F32 z_, const F32 w_);
- template<>
- TVec4<F32>::TVec4(const TVec4<F32>& b);
- template<>
- TVec4<F32>& TVec4<F32>::operator=(const TVec4<F32>& b);
- template<>
- TVec4<F32> TVec4<F32>::operator+(const TVec4<F32>& b) const;
- template<>
- TVec4<F32>& TVec4<F32>::operator+=(const TVec4<F32>& b);
- template<>
- TVec4<F32> TVec4<F32>::operator-(const TVec4<F32>& b) const;
- template<>
- TVec4<F32>& TVec4<F32>::operator-=(const TVec4<F32>& b);
- template<>
- TVec4<F32> TVec4<F32>::operator*(const TVec4<F32>& b) const;
- template<>
- TVec4<F32>& TVec4<F32>::operator*=(const TVec4<F32>& b);
- template<>
- TVec4<F32> TVec4<F32>::operator/(const TVec4<F32>& b) const;
- template<>
- TVec4<F32>& TVec4<F32>::operator/=(const TVec4<F32>& b);
- template<>
- F32 TVec4<F32>::dot(const TVec4<F32>& b) const;
- template<>
- TVec4<F32> TVec4<F32>::getNormalized() const;
- template<>
- void TVec4<F32>::normalize();
- #elif ANKI_SIMD == ANKI_SIMD_NEON
- template<>
- TVec4<F32>::TVec4(F32 f);
- template<>
- TVec4<F32>::TVec4(const F32 arr_[]);
- template<>
- TVec4<F32>::TVec4(const TVec4<F32>& b);
- template<>
- TVec4<F32>& TVec4<F32>::operator=(const TVec4<F32>& b);
- template<>
- TVec4<F32> TVec4<F32>::operator+(const TVec4<F32>& b) const;
- template<>
- TVec4<F32>& TVec4<F32>::operator+=(const TVec4<F32>& b);
- template<>
- TVec4<F32> TVec4<F32>::operator-(const TVec4<F32>& b) const;
- template<>
- TVec4<F32>& TVec4<F32>::operator-=(const TVec4<F32>& b);
- template<>
- TVec4<F32> TVec4<F32>::operator*(const TVec4<F32>& b) const;
- template<>
- TVec4<F32>& TVec4<F32>::operator*=(const TVec4<F32>& b);
- template<>
- TVec4<F32> operator*(const F32 f) const;
- template<>
- TVec4<F32>& operator*=(const F32 f);
- template<>
- F32 TVec4<F32>::dot(const TVec4<F32>& b) const;
- template<>
- TVec4<F32> TVec4<F32>::getNormalized() const;
- template<>
- void TVec4<F32>::normalize();
- #endif
- /// F32 4D vector
- typedef TVec4<F32> Vec4;
- static_assert(sizeof(Vec4) == sizeof(F32) * 4, "Incorrect size");
- /// Half float 4D vector
- typedef TVec4<F16> HVec4;
- /// 32bit signed integer 4D vector
- typedef TVec4<I32> IVec4;
- /// 32bit unsigned integer 4D vector
- typedef TVec4<U32> UVec4;
- /// @}
- } // end namespace anki
- #include "anki/math/Vec4.inl.h"
- #endif
|