#pragma once #include #include #include #include namespace prism { #define DEFINE_OPERATORS(Size) \ constexpr Vector(const T scalar = T(0)) { \ for (std::size_t i = 0; i < (Size); i++) \ data[i] = scalar; \ } \ constexpr T& operator[](const size_t index) { return data[index]; } \ constexpr T operator[](const size_t index) const { return data[index]; } \ constexpr Vector& operator+=(const Vector rhs) { \ for (std::size_t i = 0; i < (Size); i++) \ data[i] += rhs[i]; \ return *this; \ } \ constexpr Vector& operator-=(const Vector rhs) { \ for (std::size_t i = 0; i < (Size); i++) \ data[i] -= rhs[i]; \ return *this; \ } \ constexpr Vector& operator*=(const Vector rhs) { \ for (std::size_t i = 0; i < (Size); i++) \ data[i] *= rhs[i]; \ return *this; \ } \ constexpr Vector& operator/=(const T scalar) { \ for (std::size_t i = 0; i < (Size); i++) \ data[i] /= scalar; \ return *this; \ } \ constexpr T* ptr() const { return data.data(); } \ constexpr T* ptr() { return data.data(); } \ constexpr Vector operator-() const { \ Vector vec; \ for (std::size_t i = 0; i < (Size); i++) \ vec[i] = -data[i]; \ return vec; \ } template struct Vector { std::array data; }; template struct Vector<2, T> { constexpr Vector(const T x_, const T y_) { x = x_; y = y_; } DEFINE_OPERATORS(2) union { std::array data; struct { T x, y; }; }; }; template struct Vector<3, T> { constexpr Vector(const T x_, const T y_, const T z_) { x = x_; y = y_; z = z_; } DEFINE_OPERATORS(3) union { std::array data; struct { T x, y, z; }; }; }; template struct alignas(16) Vector<4, T> { constexpr Vector(const T x_, const T y_, const T z_, const T w_) { x = x_; y = y_; z = z_; w = w_; } constexpr Vector(const Vector<3, T>& v, const float w = 0.0f) : x(v.x), y(v.y), z(v.z), w(w) {} DEFINE_OPERATORS(4) union { std::array data; struct { T x, y, z, w; }; struct { Vector<3, T> xyz; T padding_xyz; }; }; }; using float2 = Vector<2, float>; using float3 = Vector<3, float>; using float4 = Vector<4, float>; template constexpr inline T dot(const Vector lhs, const Vector rhs) { T product = T(0.0); for (std::size_t i = 0; i < N; i++) product += lhs[i] * rhs[i]; return product; } template constexpr inline T length(const Vector vec) { return sqrtf(dot(vec, vec)); } template constexpr inline Vector lerp(const Vector a, const Vector b, const T t) { Vector vec; for (std::size_t i = 0; i < N; i++) vec[i] = (T(1) - t) * a[i] + t * b[i]; return vec; } template constexpr inline Vector normalize(const Vector vec) { Vector result; const float len = length(vec); for (std::size_t i = 0; i < N; i++) result[i] = vec[i] / len; return result; } constexpr inline float3 cross(const float3 u, const float3 v) { return float3(u.y * v.z - u.z * v.y, u.z * v.x - u.x * v.z, u.x * v.y - u.y * v.x); } inline float distance(const float3 lhs, const float3 rhs) { const float diffX = lhs.x - rhs.x; const float diffY = lhs.y - rhs.y; const float diffZ = lhs.z - rhs.z; return std::sqrt((diffX * diffX) + (diffY * diffY) + (diffZ * diffZ)); } template constexpr inline T norm(const Vector vec) { T val = T(0); for (std::size_t i = 0; i < N; i++) val += abs(vec[i]); return sqrtf(dot(vec, vec)); } } // namespace prism template constexpr inline bool operator==(const prism::Vector lhs, const prism::Vector rhs) { bool is_equal = true; for (std::size_t i = 0; i < N; i++) { if (lhs[i] != rhs[i]) is_equal = false; } return is_equal; } template constexpr inline bool operator!=(const prism::Vector lhs, const prism::Vector rhs) { return !(lhs == rhs); } template constexpr inline prism::Vector operator-(const prism::Vector lhs, const prism::Vector rhs) { prism::Vector vec; for (std::size_t i = 0; i < N; i++) vec[i] = lhs[i] - rhs[i]; return vec; } template constexpr inline prism::Vector operator+(const prism::Vector lhs, const prism::Vector rhs) { prism::Vector vec; for (std::size_t i = 0; i < N; i++) vec[i] = lhs[i] + rhs[i]; return vec; } template constexpr inline prism::Vector operator*(const prism::Vector lhs, const prism::Vector rhs) { prism::Vector vec; for (std::size_t i = 0; i < N; i++) vec[i] = lhs[i] * rhs[i]; return vec; } template constexpr inline prism::Vector operator+(const prism::Vector lhs, const T scalar) { prism::Vector vec; for (std::size_t i = 0; i < N; i++) vec[i] = lhs[i] + scalar; return vec; } template constexpr inline prism::Vector operator*(const prism::Vector lhs, const T scalar) { prism::Vector vec; for (std::size_t i = 0; i < N; i++) vec[i] = lhs[i] * scalar; return vec; } template constexpr inline prism::Vector operator/(const prism::Vector lhs, const prism::Vector rhs) { prism::Vector vec; for (std::size_t i = 0; i < N; i++) vec[i] = lhs[i] / rhs[i]; return vec; } template constexpr inline prism::Vector operator/(const prism::Vector lhs, const T scalar) { prism::Vector vec; for (std::size_t i = 0; i < N; i++) vec[i] = lhs[i] / scalar; return vec; }