#pragma once #include #include "math.h" #include #include #include #include #include #include #include #include #include #include #include #include #if UF_USE_BFLOAT16 #include #endif namespace pod { template struct Vector; template using Vector1t = Vector; typedef Vector1t Vector1; typedef Vector1t Vector1s; typedef Vector1t Vector1us; typedef Vector1t Vector1i; typedef Vector1t Vector1ui; typedef Vector1t Vector1l; typedef Vector1t Vector1f; typedef Vector1t Vector1d; template using Vector2t = Vector; typedef Vector2t Vector2; typedef Vector2t Vector2s; typedef Vector2t Vector2us; typedef Vector2t Vector2i; typedef Vector2t Vector2ui; typedef Vector2t Vector2l; typedef Vector2t Vector2f; typedef Vector2t Vector2d; template using Vector3t = Vector; typedef Vector3t Vector3; typedef Vector3t Vector3b; typedef Vector3t Vector3s; typedef Vector3t Vector3us; typedef Vector3t Vector3i; typedef Vector3t Vector3ui; typedef Vector3t Vector3l; typedef Vector3t Vector3f; typedef Vector3t Vector3d; template using Vector4t = Vector; typedef Vector4t Vector4; typedef Vector4t Vector4b; typedef Vector4t Vector4s; typedef Vector4t Vector4us; typedef Vector4t Vector4i; typedef Vector4t Vector4ui; typedef Vector4t Vector4l; typedef Vector4t Vector4f; typedef Vector4t Vector4d; #if UF_USE_FLOAT16 typedef Vector2t Vector2f16; typedef Vector3t Vector3f16; typedef Vector4t Vector4f16; #endif #if UF_USE_BFLOAT16 typedef Vector2t Vector2bf16; typedef Vector3t Vector3bf16; typedef Vector4t Vector4bf16; #endif } // POD vector accessing/manipulation namespace uf { namespace vector { template /*FORCE_INLINE*/ pod::Vector1t /*UF_API*/ create( T x ); // creates a 1D vector template /*FORCE_INLINE*/ pod::Vector2t /*UF_API*/ create( T x, T y ); // creates a 2D vector template /*FORCE_INLINE*/ pod::Vector3t /*UF_API*/ create( T x, T y, T z ); // creates a 3D vector template /*FORCE_INLINE*/ pod::Vector4t /*UF_API*/ create( T x, T y, T z, T w ); // creates a 4D vector template /*FORCE_INLINE*/ pod::Vector /*UF_API*/ copy( const pod::Vector& = {}); // creates a copy of a vector (for whatever reason) template /*FORCE_INLINE*/ pod::Vector /*UF_API*/ copy( const T* ); // creates a copy of a vector (for whatever reason) template /*FORCE_INLINE*/ pod::Vector /*UF_API*/ cast( const U& from ); // casts one vector of one type to another (of the same size) // Equality checking template /*FORCE_INLINE*/ bool /*UF_API*/ equals( const T& left, const T& right ); // equality check between two vectors (==) template /*FORCE_INLINE*/ bool /*UF_API*/ notEquals( const T& left, const T& right ); // equality check between two vectors (==) template /*FORCE_INLINE*/ bool /*UF_API*/ less( const T& left, const T& right ); // equality check between two vectors (<) template /*FORCE_INLINE*/ bool /*UF_API*/ lessEquals( const T& left, const T& right ); // equality check between two vectors (<=) template /*FORCE_INLINE*/ bool /*UF_API*/ greater( const T& left, const T& right ); // equality check between two vectors (>) template /*FORCE_INLINE*/ bool /*UF_API*/ greaterEquals( const T& left, const T& right ); // equality check between two vectors (>=) template /*FORCE_INLINE*/ bool /*UF_API*/ isValid( const T& v ); // checks if all components are valid (non NaN, inf, etc.) // Basic arithmetic template /*FORCE_INLINE*/ T /*UF_API*/ add( const T& left, const T& right ); // adds two vectors of same type and size together template /*FORCE_INLINE*/ T /*UF_API*/ add( const T& left, typename T::type_t scalar ); // adds a scalar to every component of the vector template /*FORCE_INLINE*/ T /*UF_API*/ add( typename T::type_t scalar, const T& vector ); // adds a scalar to every component of the vector (inverted) template /*FORCE_INLINE*/ T /*UF_API*/ subtract( const T& left, const T& right ); // subtracts two vectors of same type and size together template /*FORCE_INLINE*/ T /*UF_API*/ subtract( const T& left, typename T::type_t scalar ); // subtracts a scalar to every component of the vector template /*FORCE_INLINE*/ T /*UF_API*/ subtract( typename T::type_t scalar, const T& vector ); // subtracts a scalar to every component of the vector (inverted) template /*FORCE_INLINE*/ T /*UF_API*/ multiply( const T& left, const T& right ); // multiplies two vectors of same type and size together template /*FORCE_INLINE*/ T /*UF_API*/ multiply( const T& vector, typename T::type_t scalar ); // multiplies a scalar to every component of the vector template /*FORCE_INLINE*/ T /*UF_API*/ multiply( typename T::type_t scalar, const T& vector ); // multiplies a scalar to every component of the vector (inverted) template /*FORCE_INLINE*/ T /*UF_API*/ divide( const T& left, const T& right ); // divides two vectors of same type and size together template /*FORCE_INLINE*/ T /*UF_API*/ divide( const T& left, typename T::type_t scalar ); // divides a scalar to every component of the vector template /*FORCE_INLINE*/ T /*UF_API*/ divide( typename T::type_t scalar, const T& vector ); // divides a scalar to every component of the vector (inverted) template /*FORCE_INLINE*/ T& /*UF_API*/ add_( T& left, const T& right ); // adds two vectors of same type and size together template /*FORCE_INLINE*/ T& /*UF_API*/ add_( T& left, typename T::type_t scalar ); // adds a scalar to every component of the vector template /*FORCE_INLINE*/ T& /*UF_API*/ add_( typename T::type_t scalar, T& vector ); // adds a scalar to every component of the vector (inverted) template /*FORCE_INLINE*/ T& /*UF_API*/ subtract_( T& left, const T& right ); // subtracts two vectors of same type and size together template /*FORCE_INLINE*/ T& /*UF_API*/ subtract_( T& left, typename T::type_t scalar ); // subtracts a scalar to every component of the vector template /*FORCE_INLINE*/ T& /*UF_API*/ subtract_( typename T::type_t scalar, T& vector ); // subtracts a scalar to every component of the vector (inverted) template /*FORCE_INLINE*/ T& /*UF_API*/ multiply_( T& left, const T& right ); // multiplies two vectors of same type and size together template /*FORCE_INLINE*/ T& /*UF_API*/ multiply_( T& vector, typename T::type_t scalar ); // multiplies a scalar to every component of the vector template /*FORCE_INLINE*/ T& /*UF_API*/ multiply_( typename T::type_t scalar, T& vector ); // multiplies a scalar to every component of the vector (inverted) template /*FORCE_INLINE*/ T& /*UF_API*/ divide_( T& left, const T& right ); // divides two vectors of same type and size together template /*FORCE_INLINE*/ T& /*UF_API*/ divide_( T& left, typename T::type_t scalar ); // divides a scalar to every component of the vector template /*FORCE_INLINE*/ T& /*UF_API*/ divide_( typename T::type_t scalar, T& vector ); // divides a scalar to every component of the vector (inverted) template /*FORCE_INLINE*/ T& /*UF_API*/ negate_( T& vector ); // flip sign of all components template /*FORCE_INLINE*/ T& /*UF_API*/ normalize_( T& vector ); // normalizes a vector template /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ sum( const T& vector ); // compute the sum of all components template /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ product( const T& vector ); // compute the product of all components template /*FORCE_INLINE*/ T /*UF_API*/ negate( const T& vector ); // flip sign of all components template /*FORCE_INLINE*/ T /*UF_API*/ abs( const T& vector ); // gets the absolute value of a vector template /*FORCE_INLINE*/ T /*UF_API*/ min( const T& left, const T& right ); // returns the minimum of each component between two vectors template /*FORCE_INLINE*/ T /*UF_API*/ max( const T& left, const T& right ); // returns the maximum of each component between two vectors template /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ min( const T& v ); // returns the minimum component of a vector template /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ max( const T& v ); // returns the maximum component of a vector template /*FORCE_INLINE*/ T /*UF_API*/ min( const T& vector, typename T::type_t& min ); // applies min on a vector template /*FORCE_INLINE*/ T /*UF_API*/ max( const T& vector, typename T::type_t& max ); // applies max on a vector template /*FORCE_INLINE*/ T /*UF_API*/ clamp( const T& vector, const T& min, const T& max ); // clamps a vector between two bounds template /*FORCE_INLINE*/ T /*UF_API*/ clamp( const T& vector, typename T::type_t& min, typename T::type_t& max ); // clamps a vector between a bound template /*FORCE_INLINE*/ T /*UF_API*/ ceil( const T& vector ); // rounds each component of the the vector up template /*FORCE_INLINE*/ T /*UF_API*/ floor( const T& vector ); // rounds each component of the vector down template /*FORCE_INLINE*/ T /*UF_API*/ round( const T& vector ); // rounds each component of the vector // Complex arithmetic template /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ dot( const T& left, const T& right ); // compute the dot product between two vectors template /*FORCE_INLINE*/ float /*UF_API*/ angle( const T& a, const T& b ); // compute the angle between two vectors template /*FORCE_INLINE*/ float /*UF_API*/ signedAngle( const T& a, const T& b, const T& axis ); // compute the signed angle between two vectors template /*FORCE_INLINE*/ T /*UF_API*/ cross( const T& a, const T& b ); // compute the cross product between two vectors template /*FORCE_INLINE*/ T /*UF_API*/ lerp( const T& from, const T& to, double, bool = true ); // linearly interpolate between two vectors template /*FORCE_INLINE*/ T /*UF_API*/ lerp( const T& from, const T& to, const T&, bool = true ); // linearly interpolate between two vectors, component-wise template /*FORCE_INLINE*/ T /*UF_API*/ slerp( const T& from, const T& to, double, bool = false ); // spherically interpolate between two vectors template /*FORCE_INLINE*/ T /*UF_API*/ mix( const T& from, const T& to, double, bool = false ); template /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ distanceSquared( const T& a, const T& b ); // compute the distance between two vectors (doesn't sqrt) template /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ distance( const T& a, const T& b ); // compute the distance between two vectors template /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ magnitude( const T& vector ); // gets the magnitude of the vector template /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ norm( const T& vector ); // compute the norm (length) of the vector template /*FORCE_INLINE*/ T /*UF_API*/ normalize( const T& vector ); // normalizes a vector template /*FORCE_INLINE*/ T /*UF_API*/ clampMagnitude( const T& vector, float maxMag ); // clamps the magnitude of a vector template /*FORCE_INLINE*/ void /*UF_API*/ orthonormalize( T& x, T& y ); // orthonormalizes a vector against another vector template /*FORCE_INLINE*/ T /*UF_API*/ orthonormalize( const T& x, const T& y ); // orthonormalizes a vector against another vector template /*FORCE_INLINE*/ size_t /*UF_API*/ hash( const T& vector ); // hashes a vector template /*FORCE_INLINE*/ uf::stl::string /*UF_API*/ toString( const T& vector, const uf::stl::string& = "Vector({})" ); // parses a vector as a string template /*FORCE_INLINE*/ ext::json::Value encode( const pod::Vector& v, const ext::json::EncodingSettings& = {} ); // parses a vector into a JSON value template /*FORCE_INLINE*/ pod::Vector& decode( const ext::json::Value& v, pod::Vector& ); // parses a JSON value into a vector template /*FORCE_INLINE*/ pod::Vector decode( const ext::json::Value& v, const pod::Vector& = {} ); // parses a JSON value into a vector template /*FORCE_INLINE*/ typename T::type_t /*UF_API*/ mips( const T& size ); // calculate amount of mips to use given a size } } #define DEFINE_VECTOR(T, N) \ using type_t = T;\ using container_t = T*;\ static constexpr size_t size = N;\ FORCE_INLINE T& operator[](size_t i) { return components[i]; }\ FORCE_INLINE const T& operator[](size_t i) const { return components[i]; }\ FORCE_INLINE Vector operator-() const { return uf::vector::negate(*this); } \ FORCE_INLINE Vector operator+(const Vector& rhs) const { return uf::vector::add(*this, rhs); } \ FORCE_INLINE Vector operator-(const Vector& rhs) const { return uf::vector::subtract(*this, rhs); } \ FORCE_INLINE Vector operator*(const Vector& rhs) const { return uf::vector::multiply(*this, rhs); } \ FORCE_INLINE Vector operator/(const Vector& rhs) const { return uf::vector::divide(*this, rhs); } \ FORCE_INLINE Vector operator+(type_t scalar) const { return uf::vector::add(*this, scalar); } \ FORCE_INLINE Vector operator-(type_t scalar) const { return uf::vector::subtract(*this, scalar); } \ FORCE_INLINE Vector operator*(type_t scalar) const { return uf::vector::multiply(*this, scalar); } \ FORCE_INLINE Vector operator/(type_t scalar) const { return uf::vector::divide(*this, scalar); } \ FORCE_INLINE Vector& operator+=(const Vector& rhs) { return uf::vector::add_(*this, rhs); } \ FORCE_INLINE Vector& operator-=(const Vector& rhs) { return uf::vector::subtract_(*this, rhs); } \ FORCE_INLINE Vector& operator*=(const Vector& rhs) { return uf::vector::multiply_(*this, rhs); } \ FORCE_INLINE Vector& operator/=(const Vector& rhs) { return uf::vector::divide_(*this, rhs); } \ FORCE_INLINE Vector& operator+=(type_t scalar) { return uf::vector::add_(*this, scalar); } \ FORCE_INLINE Vector& operator-=(type_t scalar) { return uf::vector::subtract_(*this, scalar); } \ FORCE_INLINE Vector& operator*=(type_t scalar) { return uf::vector::multiply_(*this, scalar); } \ FORCE_INLINE Vector& operator/=(type_t scalar) { return uf::vector::divide_(*this, scalar); } \ FORCE_INLINE bool operator==(const Vector& rhs) const { return uf::vector::equals(*this, rhs); } \ FORCE_INLINE bool operator!=(const Vector& rhs) const { return uf::vector::notEquals(*this, rhs); } \ FORCE_INLINE bool operator<(const Vector& rhs) const { return uf::vector::less(*this, rhs); } \ FORCE_INLINE bool operator<=(const Vector& rhs) const { return uf::vector::lessEquals(*this, rhs); } \ FORCE_INLINE bool operator>(const Vector& rhs) const { return uf::vector::greater(*this, rhs); } \ FORCE_INLINE bool operator>=(const Vector& rhs) const { return uf::vector::greaterEquals(*this, rhs); } \ FORCE_INLINE explicit operator bool() const { return uf::vector::notEquals(*this, Vector{}); } \ template FORCE_INLINE operator Vector() const { return uf::vector::cast(*this); } #define DEFINE_VECTOR_EXT(T, N) \ template FORCE_INLINE pod::Vector operator+( T scalar, const pod::Vector& v ) { return uf::vector::add(scalar, v); }\ template FORCE_INLINE pod::Vector operator-( T scalar, const pod::Vector& v ) { return uf::vector::subtract(scalar, v); }\ template FORCE_INLINE pod::Vector operator*( T scalar, const pod::Vector& v ) { return uf::vector::multiply(scalar, v); }\ template FORCE_INLINE pod::Vector operator/( T scalar, const pod::Vector& v ) { return uf::vector::divide(scalar, v); }\ namespace pod { template struct Vector { union { T components[N]; }; DEFINE_VECTOR(T, N); }; template struct Vector { union { struct { T x, y; }; T components[2]; }; DEFINE_VECTOR(T, 2); }; template struct Vector { union { struct { T x, y, z; }; T components[3]; }; DEFINE_VECTOR(T, 3); }; template struct Vector { union { struct { T x, y, z, w; }; T components[4]; }; DEFINE_VECTOR(T, 4); }; } // external functions // scalar operator vector template FORCE_INLINE pod::Vector operator+( T scalar, const pod::Vector& v ) { return uf::vector::add(scalar, v); } template FORCE_INLINE pod::Vector operator-( T scalar, const pod::Vector& v ) { return uf::vector::subtract(scalar, v); } template FORCE_INLINE pod::Vector operator*( T scalar, const pod::Vector& v ) { return uf::vector::multiply(scalar, v); } template FORCE_INLINE pod::Vector operator/( T scalar, const pod::Vector& v ) { return uf::vector::divide(scalar, v); } DEFINE_VECTOR_EXT(T, 2); DEFINE_VECTOR_EXT(T, 3); DEFINE_VECTOR_EXT(T, 4); // stringify namespace uf { namespace string { template FORCE_INLINE uf::stl::string toString( const pod::Vector& v, const uf::stl::string& = "Vector({})" ); } } // jsonify namespace ext { namespace json { template FORCE_INLINE ext::json::Value encode( const pod::Vector& v ); template FORCE_INLINE pod::Vector& decode( const ext::json::Value&, pod::Vector& ); template FORCE_INLINE pod::Vector decode( const ext::json::Value&, const pod::Vector& = {} ); } } // hash namespace std { template struct hash> { FORCE_INLINE size_t operator()(const pod::Vector& v) const; }; } #include "vector/vector.inl"