// // Vector4.h // #pragma once #include #include "omath/linear_algebra/vector3.hpp" namespace omath { template requires std::is_arithmetic_v class Vector4 : public Vector3 { public: using ContainedType = Type; Type w; constexpr Vector4(const Type& x, const Type& y, const Type& z, const Type& w): Vector3(x, y, z), w(w) { } constexpr Vector4() noexcept: Vector3(), w(static_cast(0)) {}; [[nodiscard]] constexpr bool operator==(const Vector4& other) const noexcept { return Vector3::operator==(other) && w == other.w; } [[nodiscard]] constexpr bool operator!=(const Vector4& other) const noexcept { return !(*this == other); } constexpr Vector4& operator+=(const Vector4& other) noexcept { Vector3::operator+=(other); w += other.w; return *this; } constexpr Vector4& operator-=(const Vector4& other) noexcept { Vector3::operator-=(other); w -= other.w; return *this; } constexpr Vector4& operator*=(const Type& value) noexcept { Vector3::operator*=(value); w *= value; return *this; } constexpr Vector4& operator*=(const Vector4& other) noexcept { Vector3::operator*=(other); w *= other.w; return *this; } constexpr Vector4& operator/=(const Type& value) noexcept { Vector3::operator/=(value); w /= value; return *this; } constexpr Vector4& operator/=(const Vector4& other) noexcept { Vector3::operator/=(other); w /= other.w; return *this; } [[nodiscard]] constexpr Type length_sqr() const noexcept { return Vector3::length_sqr() + w * w; } [[nodiscard]] constexpr Type dot(const Vector4& other) const noexcept { return Vector3::dot(other) + w * other.w; } [[nodiscard]] Type length() const noexcept { return std::sqrt(length_sqr()); } constexpr Vector4& abs() noexcept { Vector3::abs(); w = w < 0.f ? -w : w; return *this; } constexpr Vector4& clamp(const Type& min, const Type& max) noexcept { this->x = std::clamp(this->x, min, max); this->y = std::clamp(this->y, min, max); this->z = std::clamp(this->z, min, max); return *this; } [[nodiscard]] constexpr Vector4 operator-() const noexcept { return {-this->x, -this->y, -this->z, -w}; } [[nodiscard]] constexpr Vector4 operator+(const Vector4& other) const noexcept { return {this->x + other.x, this->y + other.y, this->z + other.z, w + other.w}; } [[nodiscard]] constexpr Vector4 operator-(const Vector4& other) const noexcept { return {this->x - other.x, this->y - other.y, this->z - other.z, w - other.w}; } [[nodiscard]] constexpr Vector4 operator*(const Type& value) const noexcept { return {this->x * value, this->y * value, this->z * value, w * value}; } [[nodiscard]] constexpr Vector4 operator*(const Vector4& other) const noexcept { return {this->x * other.x, this->y * other.y, this->z * other.z, w * other.w}; } [[nodiscard]] constexpr Vector4 operator/(const Type& value) const noexcept { return {this->x / value, this->y / value, this->z / value, w / value}; } [[nodiscard]] constexpr Vector4 operator/(const Vector4& other) const noexcept { return {this->x / other.x, this->y / other.y, this->z / other.z, w / other.w}; } [[nodiscard]] constexpr Type sum() const noexcept { return Vector3::sum() + w; } [[nodiscard]] bool operator<(const Vector4& other) const noexcept { return length() < other.length(); } [[nodiscard]] bool operator>(const Vector4& other) const noexcept { return length() > other.length(); } [[nodiscard]] bool operator<=(const Vector4& other) const noexcept { return length() <= other.length(); } [[nodiscard]] bool operator>=(const Vector4& other) const noexcept { return length() >= other.length(); } #ifdef OMATH_IMGUI_INTEGRATION [[nodiscard]] constexpr ImVec4 to_im_vec4() const noexcept { return { static_cast(this->x), static_cast(this->y), static_cast(this->z), static_cast(w), }; } [[nodiscard]] static Vector4 from_im_vec4(const ImVec4& other) noexcept { return {static_cast(other.x), static_cast(other.y), static_cast(other.z)}; } #endif }; } // namespace omath template<> struct std::hash> { [[nodiscard]] std::size_t operator()(const omath::Vector4& vec) const noexcept { std::size_t hash = 0; constexpr std::hash hasher; hash ^= hasher(vec.x) + 0x9e3779b9 + (hash << 6) + (hash >> 2); hash ^= hasher(vec.y) + 0x9e3779b9 + (hash << 6) + (hash >> 2); hash ^= hasher(vec.z) + 0x9e3779b9 + (hash << 6) + (hash >> 2); hash ^= hasher(vec.w) + 0x9e3779b9 + (hash << 6) + (hash >> 2); return hash; } }; template struct std::formatter> // NOLINT(*-dcl58-cpp) { [[nodiscard]] static constexpr auto parse(std::format_parse_context& ctx) { return ctx.begin(); } template [[nodiscard]] static auto format(const omath::Vector4& vec, FormatContext& ctx) { if constexpr (std::is_same_v) return std::format_to(ctx.out(), "[{}, {}, {}, {}]", vec.x, vec.y, vec.z, vec.w); if constexpr (std::is_same_v) return std::format_to(ctx.out(), L"[{}, {}, {}, {}]", vec.x, vec.y, vec.z, vec.w); if constexpr (std::is_same_v) return std::format_to(ctx.out(), u8"[{}, {}, {}, {}]", vec.x, vec.y, vec.z, vec.w); } };