#pragma once #include "FrameworkMath.h" namespace Framework { template //! An N-dimensional vector class VecN { private: T v[N]; public: //! Constructor inline VecN() {} //! Constructor //! \param v The values of the vector inline VecN(const T v[N]) { memcpy(this->v, v, sizeof(T) * N); } inline VecN(std::initializer_list l) { assert(l.size() == N); int i = 0; for (auto v : l) { this->v[i] = v; i++; } } //! Constructor //! \param vect A vector whose values should be copied inline VecN(const VecN& vect) : VecN(vect.v) {} //! Scales the vector so that it has length 1 inline VecN& normalize() { const T length = getLength(); for (int i = 0; i < N; i++) v[i] /= length; return *this; } //! Swaps the values of the vector with those of another vector //! \param vect The other vector inline VecN& swap(VecN& vect) { const VecN tmp = vect; vect = *this; *this = tmp; return *this; } //! Calculates an angle between this and another vector inline float angle(VecN vect) { return lowPrecisionACos( (float)(*this * vect) / ((float)getLength() * (float)vect.getLength())); } //! Copies the values of another vector //! \param r The other vector inline VecN operator=(const VecN& r) { memcpy(v, r.v, sizeof(T) * N); return *this; } //! Adds another vector to this one //! \param r The other vector inline VecN operator+=(const VecN& r) { for (int i = 0; i < N; i++) v[i] += r.v[i]; return *this; } //! Subtracts another vector from this one //! \param r The other vector inline VecN operator-=(const VecN& r) { for (int i = 0; i < N; i++) v[i] -= r.v[i]; return *this; } //! Scales this vector //! \param r The factor inline VecN operator*=(const T& r) { for (int i = 0; i < N; i++) v[i] *= r; return *this; } //! Scales this vector by 1/factor //! \param r The factor inline VecN operator/=(const T& r) { for (int i = 0; i < N; i++) v[i] /= r; return *this; } //! Calculates the square of the distance between two vectors //! \param p The other vector inline T distanceSq(const VecN& p) const { T sum = (T)0; for (int i = 0; i < N; i++) sum += (v[i] - p.v[i]) * (v[i] - p.v[i]); return sum; } //! Calculates the distance between two vectors //! \param p The other vector inline T distance(const VecN& p) const { return sqrt(distanceSq(p)); } //! Returns a new vector that is the negation of this one inline VecN operator-() const { T r[N]; for (int i = 0; i < N; i++) r[i] = -v[i]; return {r}; } template //! Converts the vector type to another inline operator VecN() const { T2 r[N]; for (int i = 0; i < N; i++) r[i] = (T2)v[i]; return {r}; } //! Calculates the square of the vector's length inline T getLengthSq() const { return *this * *this; } //! Calculates the length of the vector inline T getLength() const { return (T)sqrt(getLengthSq()); } //! Calculates the dot product between two vectors //! \param r The other vector inline T operator*(const VecN& r) const { T sum = (T)0; for (int i = 0; i < N; i++) sum += v[i] * r.v[i]; return sum; } //! Calculates the sum of two vectors //! \param r The other vector inline VecN operator+(const VecN& r) const { return VecN(*this) += r; } //! Subtracts two vectors from each other //! \param r The other vector inline VecN operator-(const VecN& r) const { return VecN(*this) -= r; } //! Scales the vector without modifying it //! \param r The factor inline VecN operator*(const T& r) const { return VecN(*this) *= r; } //! Scales the vector by 1/factor without modifying it //! \param r The factor inline VecN operator/(const T& r) const { return VecN(*this) /= r; } //! Checks two vectors for equality //! \param r The other vector inline bool operator==(const VecN& r) const { for (int i = 0; i < N; i++) { if (v[i] != r.v[i]) return 0; } return 1; } //! Checks two vectors for inequality //! \param r The other vector inline bool operator!=(const VecN& r) const { return !(*this == r); } inline T operator[](int i) const { return v[i]; } }; } // namespace Framework