/* 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; import :BasicTypes; import :Misc; namespace Crafter { template struct __attribute__((packed)) VectorBase { T v[Aligment]; }; template struct __attribute__((packed)) VectorBase { union { T v[Aligment]; T x; }; }; template struct __attribute__((packed)) VectorBase { union { T v[Aligment]; struct __attribute__((packed)) { T x, y; }; }; VectorBase(float x, float y): x(x), y(y) { } VectorBase() = default; }; template struct __attribute__((packed)) VectorBase { union { T v[Aligment]; struct __attribute__((packed)) { T x, y, z; }; }; VectorBase(float x, float y, float z): x(x), y(y), z(z) { } VectorBase() = default; }; template struct __attribute__((packed)) VectorBase { union { T v[Aligment]; struct __attribute__((packed)) { T x, y, z, w; }; }; VectorBase(float x, float y, float z, float w): x(x), y(y), z(z), w(w) { } VectorBase() = default; }; template struct VectorBase { T v[Len]; }; template struct VectorBase { union { T v[1]; T x; }; }; template struct VectorBase { union { T v[2]; struct { T x, y; }; }; VectorBase(float x, float y): x(x), y(y) { } VectorBase() = default; }; template struct VectorBase { union { T v[3]; struct { T x, y, z; }; }; VectorBase(float x, float y, float z): x(x), y(y), z(z) { } VectorBase() = default; }; template struct VectorBase { union { T v[4]; struct { T x, y, z, w; }; }; VectorBase(float x, float y, float z, float w): x(x), y(y), z(z), w(w) { } VectorBase() = default; }; export template class Vector : public VectorBase { public: Vector(float x, float y, float z, float w ) requires(std::same_as && Len == 4) : VectorBase(x, y, z, w) { } Vector(float x, float y, float z) requires(std::same_as && Len == 3) : VectorBase(x, y, z) { } Vector(float x, float y) requires(std::same_as && Len == 2) : VectorBase(x, y) { } Vector() = default; static Vector QuaternionRotationRollPitchYaw(float Pitch, float Yaw, float Roll) requires(Len == 4) { const float halfpitch = Pitch * 0.5f; float cp = std::cosf(halfpitch); float sp = std::sinf(halfpitch); const float halfyaw = Yaw * 0.5f; float cy = std::cosf(halfyaw); float sy = std::sinf(halfyaw); const float halfroll = Roll * 0.5f; float cr = std::cosf(halfroll); float sr = std::sinf(halfroll); return Vector( cr * sp * cy + sr * cp * sy, cr * cp * sy - sr * sp * cy, sr * cp * cy - cr * sp * sy, cr * cp * cy + sr * sp * sy ); } template Vector operator+(Vector b){ 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 Vector operator-(Vector b){ 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; } Vector operator-(){ Vector resultVector; for(std::uint32_t i = 0; i < Len; i++) { resultVector.v[i] = -this->v[i]; } return resultVector; } template Vector operator*(Vector b){ 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 Vector operator/(Vector b){ 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; } Vector Rotate(Vector rotation) requires(Len == 3) { Vector q = rotation.QuaternionConjugate(); Vector result = q.QuaternionMultiply(Vector(this->x, this->y, this->z, 0)); return Vector(result.x, result.y, result.z); } Vector Normalize() requires(Len == 3) { float fLength = Length(); // Prevent divide by zero if (fLength > 0) { fLength = 1.0f / fLength; } return Vector(this->v[0] * fLength, this->v[1] * fLength, this->v[2] * fLength); } Vector Normalize() requires(Len == 4) { float fLength = Length(); // Prevent divide by zero if (fLength > 0) { fLength = 1.0f / fLength; } return Vector(this->v[0] * fLength, this->v[1] * fLength, this->v[2] * fLength, this->v[3] * fLength); } float Length() { float Result = LengthSq(); return std::sqrtf(Result); } Vector ReciprocalLength() requires(Len == 3) { Vector Result = LengthSq(); Result = ReciprocalSqrt(Result); return Result; } Vector ReciprocalSqrt() requires(Len == 3) { return Vector( 1.f / std::sqrtf(this->v[0]), 1.f / std::sqrtf(this->v[1]), 1.f / std::sqrtf(this->v[2]) ); } float LengthSq() { return Dot(*this); } float Dot(Vector v2) requires(Len == 3) { return this->v[0] * v2.v[0] + this->v[1] * v2.v[1] + this->v[2] * v2.v[2]; } float Dot(Vector v2) requires(Len == 4) { return this->v[0] * v2.v[0] + this->v[1] * v2.v[1] + this->v[2] * v2.v[2] + this->v[3] * v2.v[3]; } Vector Cross(Vector v2) requires(Len == 3) { return Vector( (this->v[1] * v2.v[2]) - (this->v[2] * v2.v[1]), (this->v[2] * v2.v[0]) - (this->v[0] * v2.v[2]), (this->v[0] * v2.v[1]) - (this->v[1] * v2.v[0]) ); }; Vector QuaternionConjugate() requires(Len == 4) { return Vector( -this->x, -this->y, -this->z, this->w ); } Vector QuaternionMultiply(Vector q2) requires(Len == 4) { return Vector( (q2.v[3] * this->v[0]) + (q2.v[0] * this->v[3]) + (q2.v[1] * this->v[2]) - (q2.v[2] * this->v[1]), (q2.v[3] * this->v[1]) - (q2.v[0] * this->v[2]) + (q2.v[1] * this->v[3]) + (q2.v[2] * this->v[0]), (q2.v[3] * this->v[2]) + (q2.v[0] * this->v[1]) - (q2.v[1] * this->v[0]) + (q2.v[2] * this->v[3]), (q2.v[3] * this->v[3]) - (q2.v[0] * this->v[0]) - (q2.v[1] * this->v[1]) - (q2.v[2] * this->v[2]) ); } Vector QuaternionRotationAxis(float angle) requires(Len == 3) { Vector Normal = Normalize(); return Normal.QuaternionRotationNormal(angle); } Vector QuaternionRotationNormal(float angle) requires(Len == 3) { Vector N = Vector(this->x, this->y, this->z, 1); float SinV, CosV; XMScalarSinCos(&SinV, &CosV, 0.5f * angle); Vector Scale = Vector(SinV, SinV, SinV, CosV); return N * Scale; } static Vector NegativeMultiplySubtract(Vector a, Vector b, Vector c) requires(Len == 4) { return Vector( c.v[0] - (a.v[0] * b.v[0]), c.v[1] - (a.v[1] * b.v[1]), c.v[2] - (a.v[2] * b.v[2]), c.v[3] - (a.v[3] * b.v[3]) ); } }; } 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); } 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); } };