#pragma once #include namespace J3ML::LinearAlgebra { class Vector4 { public: // Default Constructor Vector4(); // Constructs a new Vector4 with x,y,z values from a Vector3 Vector4(const Vector3& xyz, float w = 0); // Constructs a new Vector4 with the value (X, Y, Z, W) Vector4(float X, float Y, float Z, float W); Vector4(const Vector4& copy) = default; Vector4(Vector4&& move) = default; Vector4& operator=(const Vector4& rhs); float* ptr() { return &x; } Vector3 XYZ() const { return {x, y, z}; } float GetX() const { return x; } float GetY() const { return y; } float GetZ() const { return z; } float GetW() const { return w; } #if MUTABLE void SetX(float newX) { x = newX;} void SetY(float newY) { y = newY;} void SetZ(float newZ) { z = newZ;} void SetW(float newW) { w = newW;} #endif static const Vector4 Zero; static const Vector4 NaN; float operator[](std::size_t index) const; float &operator[](std::size_t index); bool IsWithinMarginOfError(const Vector4& rhs, float margin=0.0001f) const; float LengthSqXYZ() const; bool IsNormalized3(float epsilonSq = 1e-5f) const { return std::abs(LengthSqXYZ()-1.f) <= epsilonSq; } bool IsNormalized4(float epsilonSq = 1e-5f) const { return std::abs(LengthSquared()-1.f) <= epsilonSq; } bool IsNormalized(float epsilonSq = 1e-5f) const { return IsNormalized4(epsilonSq); } bool IsZero(float epsilonSq = 1e-6f) const; bool IsFinite() const; bool IsPerpendicular(const Vector4& other, float epsilonSq=1e-5f) const { float dot = Dot(other); return dot*dot <= epsilonSq * LengthSquared() * other.LengthSquared(); } bool IsPerpendicular3(const Vector4& other, float epsilonSq = 1e-5f) const { } bool operator==(const Vector4& rhs) const; bool operator!=(const Vector4& rhs) const; bool Equals(const Vector4& rhs, float epsilon = 1e-3f) const; bool Equals(float _x, float _y, float _z, float _w, float epsilon = 1e-3f) const; Vector4 Min(const Vector4& min) const; Vector4 Max(const Vector4& max) const; Vector4 Clamp(const Vector4& min, const Vector4& max) const; float Distance(const Vector4& to) const; float Length() const; float LengthSquared() const; float Magnitude() const; float Dot(const Vector4& rhs) const; Vector4 Project(const Vector4& rhs) const; // While it is feasable to compute a cross-product in four dimensions // the cross product only has the orthogonality property in 3 and 7 dimensions // You should consider instead looking at Gram-Schmidt Orthogonalization // to find orthonormal vectors. Vector4 Cross3(const Vector3& rhs) const; Vector4 Cross3(const Vector4& rhs) const; Vector4 Cross(const Vector4& rhs) const { return Cross3(rhs); } Vector4 Normalize() const; Vector4 Lerp(const Vector4& goal, float alpha) const; float AngleBetween(const Vector4& rhs) const; // Adds two vectors Vector4 operator+(const Vector4& rhs) const; Vector4 Add(const Vector4& rhs) const; static Vector4 Add(const Vector4& lhs, const Vector4& rhs); // Subtracts two vectors Vector4 operator-(const Vector4& rhs) const; Vector4 Sub(const Vector4& rhs) const; static Vector4 Sub(const Vector4& lhs, const Vector4& rhs); // Multiplies this vector by a scalar value Vector4 operator*(float rhs) const; Vector4 Mul(float scalar) const; static Vector4 Mul(const Vector4& lhs, float rhs); // Divides this vector by a scalar Vector4 operator/(float rhs) const; Vector4 Div(float scalar) const; static Vector4 Div(const Vector4& rhs, float scalar); Vector4 operator+() const; // Unary + Operator Vector4 operator-() const; // Unary - Operator (Negation) public: #if MUTABLE float x; float y; float z; float w; #else float x = 0; float y = 0; float z = 0; float w = 0; #endif }; }