/* Crafter®.Math Copyright (C) 2026 Catcrafts® catcrafts.net This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3.0 as published by the Free Software Foundation; This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ export module Crafter.Math:Vector; import std; namespace Crafter { template struct __attribute__((packed)) VectorBase { T v[Aligment]; }; template struct __attribute__((packed)) VectorBase { union { T v[Aligment]; T x, r; }; }; template struct __attribute__((packed)) VectorBase { union { T v[Aligment]; struct __attribute__((packed)) { T x, y; }; struct __attribute__((packed)) { T r, g; }; }; constexpr VectorBase(float x, float y): x(x), y(y) { } constexpr VectorBase() = default; }; template struct __attribute__((packed)) VectorBase { union { T v[Aligment]; struct __attribute__((packed)) { T x, y, z; }; struct __attribute__((packed)) { T r, g, b; }; }; constexpr VectorBase(float x, float y, float z): x(x), y(y), z(z) { } constexpr VectorBase() = default; }; template struct __attribute__((packed)) VectorBase { union { T v[Aligment]; struct __attribute__((packed)) { T x, y, z, w; }; struct __attribute__((packed)) { T r, g, b, a; }; }; constexpr VectorBase(float x, float y, float z, float w): x(x), y(y), z(z), w(w) { } constexpr VectorBase() = default; }; template struct VectorBase { T v[Len]; }; template struct VectorBase { union { T v[1]; T x, r; }; }; template struct VectorBase { union { T v[2]; struct { T x, y; }; struct { T r, g; }; }; constexpr VectorBase(float x, float y): x(x), y(y) { } constexpr VectorBase() = default; }; template struct VectorBase { union { T v[3]; struct { T x, y, z; }; struct { T r, g, b; }; }; constexpr VectorBase(float x, float y, float z): x(x), y(y), z(z) { } constexpr VectorBase() = default; }; template struct VectorBase { union { T v[4]; struct { T x, y, z, w; }; struct { T r, g, b, a; }; }; constexpr VectorBase(float x, float y, float z, float w): x(x), y(y), z(z), w(w) { } constexpr VectorBase() = default; }; export template class Vector : public VectorBase { public: constexpr Vector(float x, float y, float z, float w ) requires(std::same_as && Len == 4) : VectorBase(x, y, z, w) { } constexpr Vector(float x, float y, float z) requires(std::same_as && Len == 3) : VectorBase(x, y, z) { } constexpr Vector(float x, float y) requires(std::same_as && Len == 2) : VectorBase(x, y) { } constexpr Vector() = default; template constexpr Vector operator+(Vector b) const { Vector resultVector; for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) { resultVector.v[i] = this->v[i]+b.v[i]; } return resultVector; } template constexpr Vector operator-(Vector b) const { Vector resultVector; for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) { resultVector.v[i] = this->v[i]-b.v[i]; } return resultVector; } constexpr Vector operator-(){ Vector resultVector; for(std::uint32_t i = 0; i < Len; i++) { resultVector.v[i] = -this->v[i]; } return resultVector; } template constexpr Vector operator*(Vector b) const { Vector resultVector; for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) { resultVector.v[i] = this->v[i]*b.v[i]; } return resultVector; } template constexpr Vector operator/(Vector b) const { Vector resultVector; for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) { resultVector.v[i] = this->v[i]/b.v[i]; } return resultVector; } template constexpr void operator+=(Vector b){ for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) { this->v[i]+=b.v[i]; } } template constexpr void operator-=(Vector b){ for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) { this->v[i]-=b.v[i]; } } template constexpr void operator*=(Vector b){ for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) { this->v[i]*=b.v[i]; } } template constexpr void operator/=(Vector b){ for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) { this->v[i]/=b.v[i]; } } template constexpr Vector operator+(BT b) const { Vector resultVector; for(std::uint32_t i = 0; i < Len; i++) { resultVector.v[i] = this->v[i] + b; } return resultVector; } template constexpr Vector operator-(BT b) const { Vector resultVector; for(std::uint32_t i = 0; i < Len; i++) { resultVector.v[i] = this->v[i] - b; } return resultVector; } template constexpr Vector operator*(BT b) const { Vector resultVector; for(std::uint32_t i = 0; i < Len; i++) { resultVector.v[i] = this->v[i] * b; } return resultVector; } template constexpr Vector operator/(BT b) const { Vector resultVector; for(std::uint32_t i = 0; i < Len; i++) { resultVector.v[i] = this->v[i] / b; } return resultVector; } template constexpr void operator+=(BT b){ for(std::uint32_t i = 0; i < Len; i++) { this->v[i] += b; } } template constexpr void operator-=(BT b){ for(std::uint32_t i = 0; i < Len; i++) { this->v[i] -= b; } } template constexpr void operator*=(BT b){ for(std::uint32_t i = 0; i < Len; i++) { this->v[i] *= b; } } template constexpr void operator/=(BT b){ for(std::uint32_t i = 0; i < Len; i++) { this->v[i] /= b; } } template operator Vector() const { Vector returnVector; for(std::uint32_t i = 0; i < Len; i++) { returnVector.v[i] = this->v[i]; } return returnVector; } template constexpr bool operator==(BT b) const { for(std::uint32_t i = 0; i < Len; i++) { if(this->v[i] != this->v[i]) { return false; } } return true; } template constexpr bool operator!=(BT b) const { for(std::uint32_t i = 0; i < Len; i++) { if(this->v[i] != this->v[i]) { return true; } } return false; } constexpr void Normalize() { float fLength = Length(); if (fLength > 0) { fLength = 1.0f / fLength; } for(std::uint32_t i = 0; i < Len; i++) { this->v[i] *= fLength; } } constexpr void Invert() { for(std::uint32_t i = 0; i < Len; i++) { this->v[i] = -this->v[i]; } } constexpr float Length() const { float Result = LengthSq(); return std::sqrtf(Result); } constexpr float LengthSq() const { return Dot(*this, *this); } template constexpr static Vector Cross(Vector a, Vector b) requires(Len == 3 && Alen >= 3 && Blen >= 3) { return Vector( (a.v[1] * b.v[2]) - (a.v[2] * b.v[1]), (a.v[2] * b.v[0]) - (a.v[0] * b.v[2]), (a.v[0] * b.v[1]) - (a.v[1] * b.v[0]) ); } template constexpr static Vector Normalize(Vector a) requires(Len == Alen) { Vector returned; float fLength = a.Length(); if (fLength > 0) { fLength = 1.0f / fLength; } for(std::uint32_t i = 0; i < Len; i++) { returned.v[i] = a.v[i] * fLength; } return returned; } template constexpr static float Dot(Vector a, Vector b) requires(Alen >= Len && Blen >= Len) { float accumulate = a.v[0] * b.v[0]; for(std::uint32_t i = 1; i < Len; i++) { accumulate += a.v[i] * b.v[i]; } return accumulate; } template constexpr static Vector Rotate(Vector v, Vector q) requires(Len == 3) { Vector qv(q.x, q.y, q.z); Vector t = Vector::Cross(qv, v) * T(2); return v + t * q.w + Vector::Cross(qv, t); } template constexpr static Vector QuanternionFromBasis(Vector right, Vector up, Vector forward) requires(Len == 4) { T m00 = right.x; T m01 = up.x; T m02 = forward.x; T m10 = right.y; T m11 = up.y; T m12 = forward.y; T m20 = right.z; T m21 = up.z; T m22 = forward.z; T trace = m00 + m11 + m22; Vector q; if (trace > std::numeric_limits::epsilon()) { T s = std::sqrt(trace + T(1)) * T(2); q.w = T(0.25) * s; q.x = (m21 - m12) / s; q.y = (m02 - m20) / s; q.z = (m10 - m01) / s; } else if ((m00 > m11) && (m00 > m22)) { T s = std::sqrt(T(1) + m00 - m11 - m22) * T(2); q.w = (m21 - m12) / s; q.x = T(0.25) * s; q.y = (m01 + m10) / s; q.z = (m02 + m20) / s; } else if (m11 > m22) { T s = std::sqrt(T(1) + m11 - m00 - m22) * T(2); q.w = (m02 - m20) / s; q.x = (m01 + m10) / s; q.y = T(0.25) * s; q.z = (m12 + m21) / s; } else { T s = std::sqrt(T(1) + m22 - m00 - m11) * T(2); q.w = (m10 - m01) / s; q.x = (m02 + m20) / s; q.y = (m12 + m21) / s; q.z = T(0.25) * s; } q.Normalize(); return q; } }; } template struct std::formatter> : std::formatter { auto format(const Crafter::Vector& obj, format_context& ctx) const { return std::formatter::format(std::format("{{{}, {}}}", obj.x, obj.y ), ctx); } }; template struct std::formatter> : std::formatter { auto format(const Crafter::Vector& obj, format_context& ctx) const { return std::formatter::format(std::format("{{{}, {}, {}}}", obj.x, obj.y, obj.z ), ctx); } }; template struct std::formatter> : std::formatter { auto format(const Crafter::Vector& obj, format_context& ctx) const { return std::formatter::format(std::format("{{{}, {}, {}, {}}}", obj.x, obj.y, obj.z, obj.w ), ctx); } }; template constexpr Crafter::Vector operator*(BT b, const Crafter::Vector& v) { return v * b; }