#pragma once #include "Types.hpp" #include #include #include "MathF.hpp" namespace TSE { class Vector2; class Vector4; class Vector3 { public: #pragma region member float x = 0, y = 0, z = 0; #pragma endregion member #pragma region consts static const Vector3 left; static const Vector3 right; static const Vector3 up; static const Vector3 down; static const Vector3 forward; static const Vector3 back; static const Vector3 one; static const Vector3 zero; #pragma endregion consts #pragma region ctor /// @brief default constructer constructs a Vector3 with (0,0,0) Vector3(); /// @brief constructor where you only need to set x and y. z stays 0. /// @param _x x component /// @param _y y component Vector3(float _x, float _y); /// @brief constructor with custom values /// @param _x x component /// @param _y y component /// @param _z z component Vector3(float _x, float _y, float _z); /// @brief copy constructor /// @param other the vector3 to be copied Vector3(const Vector3& other); /// @brief converter constructer. it converts a Vector2 to a vector3 where z gets value 0 /// @param other the Vector2 to be converted Vector3(const Vector2& other); /// @brief converter constructer. it converts a Vector4 to a vector3 where w gets disregarded /// @param other the Vector3 to be converted Vector3(const Vector4& other); #pragma endregion ctor #pragma region methods /// @brief the length of the vector /// @return the length float Length() const; /// @brief the length² of the vector /// @return the length² float LengthSqr() const; /// @brief checks if the individual components have valid values aka are not nan /// @return are the values valid bool IsValid() const; /// @brief normalizes the Vector3 to have a length of 1 void Normalize(); /// @brief normalizes the Vector3 to have a length of 1. If the current length of the vector is smaller then epsilon, it gives you the fallback value. /// @param fallback the value to set the vector to if the current length is smaller then epsilon void NormalizeSafe(const Vector3& fallback); /// @brief gives you the vector3 as a string representation. mostly for debugging /// @return the vector3 in a format like (x|y|z) string ToString() const; /// @brief creates a Vector2 with the same values as the Vector3, the y component gets disregarded /// @return the Vector3 as a Vector2 Vector2 ToVector2() const; /// @brief creates a Vector4 with the same values as the Vector3, the w component get the value 0 /// @return the Vector3 as a Vector4 Vector4 ToVector4() const; #pragma region static /// @brief gives you the distance between two vectors. /// @param a point 1 /// @param b point 2 /// @return the distance between point 1 and point 2 static float Distance(const Vector3& a, const Vector3& b); /// @brief gives you the distance² between two vectors. /// @param a point 1 /// @param b point 2 /// @return the distance² between point 1 and point 2 static float DistanceSqr(const Vector3& a, const Vector3& b); /// @brief normalizes a copy of the Vector3 to have a length of 1 /// @param v the vector to be normaliezed /// @return a normalies copy of the vector static Vector3 Normalize(const Vector3& v); /// @brief normalizes a copy of the Vector3 to have a length of 1. If the current length of the vector is smaller then epsilon, it gives you the fallback value. /// @param fallback the value to set the vector to if the current length is smaller then epsilon /// @param v the vector to be normaliezed /// @return a normalies copy of the vector static Vector3 NormalizeSafe(const Vector3& v, const Vector3& fallback); /// @brief linearly interpolates between two points using t /// @param a point 1 /// @param b point 2 /// @param t the amoint to interpolate by /// @return the interpolated point static Vector3 Lerp(const Vector3& a, const Vector3& b, float t); /// @brief bezier interpolation using three points using t /// @param a point 1 /// @param b controll point /// @param c point 2 /// @param t the amoint to interpolate by /// @return the interpolated point static Vector3 Berp(const Vector3& a, const Vector3& b, const Vector3& c, float t); /// @brief gives you the midpoint between two points /// @param a point 1 /// @param b point 2 /// @return the midpoint static Vector3 Midpoint(const Vector3& a, const Vector3& b); /// @brief gives you the dot product between to vectors /// @param a vector 1 /// @param b vector 2 /// @return the dot product static float Dot(const Vector3& a, const Vector3& b); /// @brief it gives you the Cross Product /// @param a vector 1 /// @param b vector 2 /// @return cross product static Vector3 Cross(const Vector3& a, const Vector3& b); #pragma endregion static #pragma region operators Vector3 operator+(const Vector3& other) const; Vector3 operator+=(const Vector3& other); Vector3 operator-(const Vector3& other) const; Vector3 operator-=(const Vector3& other); Vector3 operator*(const Vector3& other) const; Vector3 operator*=(const Vector3& other); Vector3 operator/(const Vector3& other) const; Vector3 operator/=(const Vector3& other); Vector3 operator*(const float other) const; Vector3 operator*=(const float other); Vector3 operator/(const float other) const; Vector3 operator/=(const float other); bool operator==(const Vector3& other) const; bool operator!=(const Vector3& other) const; #pragma endregion operators #pragma endregion methods }; } // namespace TSE namespace std { template<> struct hash { size_t operator()(const TSE::Vector3& v) const noexcept { size_t h1 = std::hash{}(v.x); size_t h2 = std::hash{}(v.y); size_t h3 = std::hash{}(v.z); size_t hash = h1; hash ^= h2 + TSE::TSE_HASH_GOLDEN_RATIO_32 + (hash << 6) + (hash >> 2); hash ^= h3 + TSE::TSE_HASH_GOLDEN_RATIO_32 + (hash << 6) + (hash >> 2); return hash; } }; }