| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494 |
- #ifndef ANKI_MATH_VEC3_H
- #define ANKI_MATH_VEC3_H
- #include "anki/math/CommonIncludes.h"
- namespace anki {
- /// @addtogroup Math
- /// @{
- /// 3D vector template. One of the most used classes
- template<typename T>
- class TVec3
- {
- /// @name Friends
- /// @{
- template<typename Y>
- friend TVec3<Y> operator+(const Y f, const TVec3<Y>& v);
- template<typename Y>
- friend TVec3<Y> operator-(const Y f, const TVec3<Y>& v);
- template<typename Y>
- friend TVec3<Y> operator*(const Y f, const TVec3<Y>& v);
- template<typename Y>
- friend TVec3<Y> operator/(const Y f, const TVec3<Y>& v);
- /// @}
- public:
- /// @name Constructors
- /// @{
- explicit TVec3()
- {}
- explicit TVec3(const T x_, const T y_, const T z_)
- {
- x() = x_;
- y() = y_;
- z() = z_;
- }
- explicit TVec3(const T f)
- {
- arr[0] = arr[1] = arr[2] = f;
- }
- explicit TVec3(const T arr_[])
- {
- arr[0] = arr_[0];
- arr[1] = arr_[1];
- arr[2] = arr_[2];
- }
- explicit TVec3(const TVec2<T>& v2, const T z_)
- {
- x() = v2.x();
- y() = v2.y();
- z() = z_;
- }
- TVec3(const TVec3& b)
- {
- arr[0] = b.arr[0];
- arr[1] = b.arr[1];
- arr[2] = b.arr[2];
- }
- explicit TVec3(const TVec4<T>& v4)
- {
- arr[0] = v4[0];
- arr[1] = v4[1];
- arr[2] = v4[2];
- }
- explicit TVec3(const TQuat<T>& q)
- {
- x() = q.x();
- y() = q.y();
- z() = q.z();
- }
- /// @}
- /// @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& 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());
- }
- /// @}
- /// @name Operators with same type
- /// @{
- TVec3& operator=(const TVec3& b)
- {
- arr[0] = b.arr[0];
- arr[1] = b.arr[1];
- arr[2] = b.arr[2];
- return (*this);
- }
- TVec3 operator+(const TVec3& b) const
- {
- return TVec3(x() + b.x(), y() + b.y(), z() + b.z());
- }
- TVec3& operator+=(const TVec3& b)
- {
- x() += b.x();
- y() += b.y();
- z() += b.z();
- return *this;
- }
- TVec3 operator-(const TVec3& b) const
- {
- return TVec3(x() - b.x(), y() - b.y(), z() - b.z());
- }
- TVec3& operator-=(const TVec3& b)
- {
- x() -= b.x();
- y() -= b.y();
- z() -= b.z();
- return (*this);
- }
- TVec3 operator*(const TVec3& b) const
- {
- return TVec3(x() * b.x(), y() * b.y(), z() * b.z());
- }
- TVec3& operator*=(const TVec3& b)
- {
- x() *= b.x();
- y() *= b.y();
- z() *= b.z();
- return (*this);
- }
- TVec3 operator/(const TVec3& b) const
- {
- return TVec3(x() / b.x(), y() / b.y(), z() / b.z());
- }
- TVec3& operator/=(const TVec3& b)
- {
- x() /= b.x();
- y() /= b.y();
- z() /= b.z();
- return (*this);
- }
- TVec3 operator-() const
- {
- return TVec3(-x(), -y(), -z());
- }
- Bool operator==(const TVec3& b) const
- {
- return isZero<T>(x() - b.x())
- && isZero<T>(y() - b.y())
- && isZero<T>(z() - b.z());
- }
- Bool operator!=(const TVec3& b) const
- {
- return !operator==(b);
- }
- Bool operator<(const TVec3& b) const
- {
- return x() < b.x() && y() < b.y() && z() < b.z();
- }
- Bool operator<=(const TVec3& b) const
- {
- return x() <= b.x() && y() <= b.y() && z() <= b.z();
- }
- Bool operator>(const TVec3& b) const
- {
- return x() > b.x() && y() > b.y() && z() > b.z();
- }
- Bool operator>=(const TVec3& b) const
- {
- return x() >= b.x() && y() >= b.y() && z() >= b.z();
- }
- /// @}
- /// @name Operators with T
- /// @{
- TVec3 operator+(const T f) const
- {
- return (*this) + TVec3(f);
- }
- TVec3& operator+=(const T f)
- {
- (*this) += TVec3(f);
- return (*this);
- }
- TVec3 operator-(const T f) const
- {
- return (*this) - TVec3(f);
- }
- TVec3& operator-=(const T f)
- {
- (*this) -= TVec3(f);
- return (*this);
- }
- TVec3 operator*(const T f) const
- {
- return (*this) * TVec3(f);
- }
- TVec3& operator*=(const T f)
- {
- (*this) *= TVec3(f);
- return (*this);
- }
- TVec3 operator/(const T f) const
- {
- return (*this) / TVec3(f);
- }
- TVec3& operator/=(const T f)
- {
- (*this) /= TVec3(f);
- return (*this);
- }
- /// @}
- /// @name Operators with other types
- /// @{
- TVec3 operator*(const TMat3<T>& m3) const
- {
- ANKI_ASSERT(0 && "TODO");
- return TVec3(0.0);
- }
- /// @}
- /// @name Other
- /// @{
- /// 3 muls, 2 adds
- T dot(const TVec3& b) const
- {
- return x() * b.x() + y() * b.y() + z() * b.z();
- }
- /// 6 muls, 3 adds
- TVec3 cross(const TVec3& b) const
- {
- return TVec3(y() * b.z() - z() * b.y(),
- z() * b.x() - x() * b.z(),
- x() * b.y() - y() * b.x());
- }
- T getLengthSquared() const
- {
- return x() * x() + y() * y() + z() * z();
- }
- T getLength() const
- {
- return sqrt(getLengthSquared());
- }
- T getDistanceSquared(const TVec3& b) const
- {
- return ((*this) - b).getLengthSquared();
- }
- void normalize()
- {
- (*this) /= getLength();
- }
- TVec3 getNormalized() const
- {
- return (*this) / getLength();
- }
- TVec3 getProjection(const TVec3& toThis) const
- {
- return toThis * ((*this).dot(toThis) / (toThis.dot(toThis)));
- }
- /// Returns q * this * q.Conjucated() aka returns a rotated this.
- /// 18 muls, 12 adds
- TVec3 getRotated(const TQuat<T>& q) const
- {
- ANKI_ASSERT(isZero<T>(1.0 - q.getLength())); // Not normalized quat
- TVec3 qXyz(q);
- return
- (*this) + qXyz.cross(qXyz.cross((*this)) + (*this) * q.w()) * 2.0;
- }
- void rotate(const TQuat<T>& q)
- {
- (*this) = getRotated(q);
- }
- /// Return lerp(this, v1, t)
- TVec3 lerp(const TVec3& v1, T t) const
- {
- return ((*this) * (1.0 - t)) + (v1 * t);
- }
- /// @}
- /// @name Transformations
- /// The faster way is by far the TMat4 * TVec3 or the
- /// getTransformed(const TVec3&, const TMat3&)
- /// @{
- TVec3 getTransformed(const TVec3& translate, const TMat3<T>& rotate,
- T scale) const
- {
- return (rotate * ((*this) * scale)) + translate;
- }
- void transform(const TVec3& translate, const TMat3<T>& rotate, T scale)
- {
- (*this) = getTransformed(translate, rotate, scale);
- }
- TVec3 getTransformed(const TVec3& translate, const TMat3<T>& rotate) const
- {
- return (rotate * (*this)) + translate;
- }
- void transform(const TVec3& translate, const TMat3<T>& rotate)
- {
- (*this) = getTransformed(translate, rotate);
- }
- TVec3 getTransformed(const TVec3& translate, const TQuat<T>& rotate,
- T scale) const
- {
- return ((*this) * scale).getRotated(rotate) + translate;
- }
- void transform(const TVec3& translate, const TQuat<T>& rotate, T scale)
- {
- (*this) = getTransformed(translate, rotate, scale);
- }
- TVec3 getTransformed(const TVec3& translate, const TQuat<T>& rotate) const
- {
- return getRotated(rotate) + translate;
- }
- void transform(const TVec3& translate, const TQuat<T>& rotate)
- {
- (*this) = getTransformed(translate, rotate);
- }
- /// Transform the vector
- /// @param transform A transformation matrix
- ///
- /// @note 9 muls, 9 adds
- TVec3 getTransformed(const TMat4<T>& transform) const
- {
- return TVec3(
- transform(0, 0) * x() + transform(0, 1) * y()
- + transform(0, 2) * z() + transform(0, 3),
- transform(1, 0) * x() + transform(1, 1) * y()
- + transform(1, 2) * z() + transform(1, 3),
- transform(2, 0) * x() + transform(2, 1) * y()
- + transform(2, 2) * z() + transform(2, 3));
- }
- void transform(const TMat4<T>& transform)
- {
- (*this) = getTransformed(transform);
- }
- /// 12 muls, 9 adds
- TVec3 getTransformed(const TTransform<T>& transform) const
- {
- return (transform.getRotation() * ((*this) * transform.getScale()))
- + transform.getOrigin();
- }
- void transform(const TTransform<T>& transform)
- {
- (*this) = getTransformed(transform);
- }
- std::string toString() const
- {
- return std::to_string(x()) + " " + std::to_string(y()) + " "
- + std::to_string(z());
- }
- /// @}
- private:
- /// @name Data
- /// @{
- union
- {
- struct
- {
- T x, y, z;
- } vec;
- Array<T, 3> arr;
- };
- /// @}
- };
- template<typename T>
- TVec3<T> operator+(const T f, const TVec3<T>& v)
- {
- return v + f;
- }
- template<typename T>
- TVec3<T> operator-(const T f, const TVec3<T>& v)
- {
- return TVec3<T>(f) - v;
- }
- template<typename T>
- TVec3<T> operator*(const T f, const TVec3<T>& v)
- {
- return v * f;
- }
- template<typename T>
- TVec3<T> operator/(const T f, const TVec3<T>& v)
- {
- return TVec3<T>(f) / v;
- }
- /// F32 3D vector
- typedef TVec3<F32> Vec3;
- static_assert(sizeof(Vec3) == sizeof(F32) * 3, "Incorrect size");
- /// Half float 3D vector
- typedef TVec3<F16> HVec3;
- /// 32bit signed integer 3D vector
- typedef TVec3<I32> IVec3;
- /// 32bit unsigned integer 3D vector
- typedef TVec3<U32> UVec3;
- /// @}
- } // end namespace anki
- #endif
|