Crafter.Math/interfaces/Crafter.Math-Vector.cppm

494 lines
16 KiB
Text
Raw Normal View History

2025-05-07 19:18:58 +02:00
/*
2026-01-29 20:19:20 +01:00
Crafter®.Math
Copyright (C) 2026 Catcrafts®
catcrafts.net
2025-05-07 19:18:58 +02:00
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
2026-01-29 20:19:20 +01:00
License version 3.0 as published by the Free Software Foundation;
2025-05-07 19:18:58 +02:00
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
*/
2025-05-05 02:01:44 +02:00
export module Crafter.Math:Vector;
2026-01-29 20:19:20 +01:00
import std;
2025-05-05 02:01:44 +02:00
namespace Crafter {
2026-02-05 01:18:05 +01:00
template <typename T, std::uint32_t Len, std::uint32_t Aligment>
struct __attribute__((packed)) VectorBase {
T v[Aligment];
2025-05-05 05:14:39 +02:00
};
2026-02-05 01:18:05 +01:00
template <typename T, std::uint32_t Aligment>
struct __attribute__((packed)) VectorBase<T, 1, Aligment> {
2025-05-05 05:14:39 +02:00
union {
2026-02-05 01:18:05 +01:00
T v[Aligment];
2026-02-19 02:36:36 +01:00
T x, r;
2025-05-05 05:14:39 +02:00
};
};
2026-02-05 01:18:05 +01:00
template <typename T, std::uint32_t Aligment>
struct __attribute__((packed)) VectorBase<T, 2, Aligment> {
2025-05-05 05:14:39 +02:00
union {
2026-02-05 01:18:05 +01:00
T v[Aligment];
struct __attribute__((packed)) {
2025-05-05 05:14:39 +02:00
T x, y;
};
2026-02-19 02:36:36 +01:00
struct __attribute__((packed)) {
T r, g;
};
2025-05-05 05:14:39 +02:00
};
2026-02-11 02:52:03 +01:00
constexpr VectorBase<T, 2, Aligment>(float x, float y): x(x), y(y) {
2025-05-07 19:18:58 +02:00
}
2026-02-11 02:52:03 +01:00
constexpr VectorBase<T, 2, Aligment>() = default;
2025-05-05 05:14:39 +02:00
};
2025-05-05 02:01:44 +02:00
2026-02-05 01:18:05 +01:00
template <typename T, std::uint32_t Aligment>
struct __attribute__((packed)) VectorBase<T, 3, Aligment> {
2025-05-05 05:14:39 +02:00
union {
2026-02-05 01:18:05 +01:00
T v[Aligment];
struct __attribute__((packed)) {
2025-05-05 05:14:39 +02:00
T x, y, z;
};
2026-02-19 02:36:36 +01:00
struct __attribute__((packed)) {
T r, g, b;
};
2025-05-05 05:14:39 +02:00
};
2026-02-11 02:52:03 +01:00
constexpr VectorBase<T, 3, Aligment>(float x, float y, float z): x(x), y(y), z(z) {
2025-05-05 05:14:39 +02:00
2025-05-05 02:01:44 +02:00
}
2026-02-11 02:52:03 +01:00
constexpr VectorBase<T, 3, Aligment>() = default;
2025-05-05 02:01:44 +02:00
};
2026-02-05 01:18:05 +01:00
template <typename T, std::uint32_t Aligment>
struct __attribute__((packed)) VectorBase<T, 4, Aligment> {
2025-05-05 05:14:39 +02:00
union {
2026-02-05 01:18:05 +01:00
T v[Aligment];
struct __attribute__((packed)) {
2025-05-05 05:14:39 +02:00
T x, y, z, w;
};
2026-02-19 02:36:36 +01:00
struct __attribute__((packed)) {
T r, g, b, a;
};
2025-05-05 05:14:39 +02:00
};
2026-02-11 02:52:03 +01:00
constexpr VectorBase<T, 4, Aligment>(float x, float y, float z, float w): x(x), y(y), z(z), w(w) {
2025-05-07 19:18:58 +02:00
}
2026-02-11 02:52:03 +01:00
constexpr VectorBase<T, 4, Aligment>() = default;
2025-05-05 05:14:39 +02:00
};
2026-02-05 01:57:32 +01:00
template <typename T, std::uint32_t Len>
struct VectorBase<T, Len, 0> {
T v[Len];
};
template <typename T>
struct VectorBase<T, 1, 0> {
union {
T v[1];
2026-02-19 02:36:36 +01:00
T x, r;
2026-02-05 01:57:32 +01:00
};
};
template <typename T>
struct VectorBase<T, 2, 0> {
union {
T v[2];
struct {
T x, y;
};
2026-02-19 02:36:36 +01:00
struct {
T r, g;
};
2026-02-05 01:57:32 +01:00
};
2026-02-11 02:52:03 +01:00
constexpr VectorBase<T, 2, 0>(float x, float y): x(x), y(y) {
2026-02-05 01:57:32 +01:00
}
2026-02-11 02:52:03 +01:00
constexpr VectorBase<T, 2, 0>() = default;
2026-02-05 01:57:32 +01:00
};
template <typename T>
struct VectorBase<T, 3, 0> {
union {
T v[3];
struct {
T x, y, z;
};
2026-02-19 02:36:36 +01:00
struct {
T r, g, b;
};
2026-02-05 01:57:32 +01:00
};
2026-02-11 02:52:03 +01:00
constexpr VectorBase<T, 3, 0>(float x, float y, float z): x(x), y(y), z(z) {
2026-02-05 01:57:32 +01:00
}
2026-02-11 02:52:03 +01:00
constexpr VectorBase<T, 3, 0>() = default;
2026-02-05 01:57:32 +01:00
};
template <typename T>
struct VectorBase<T, 4, 0> {
union {
T v[4];
struct {
T x, y, z, w;
};
2026-02-19 02:36:36 +01:00
struct {
T r, g, b, a;
};
2026-02-05 01:57:32 +01:00
};
2026-02-11 02:52:03 +01:00
constexpr VectorBase<T, 4, 0>(float x, float y, float z, float w): x(x), y(y), z(z), w(w) {
2026-02-05 01:57:32 +01:00
}
2026-02-11 02:52:03 +01:00
constexpr VectorBase<T, 4, 0>() = default;
2026-02-05 01:57:32 +01:00
};
2026-02-05 01:18:05 +01:00
export template <typename T, std::uint32_t Len, std::uint32_t Aligment>
class Vector : public VectorBase<T, Len, Aligment> {
2025-05-05 02:01:44 +02:00
public:
2026-02-11 02:52:03 +01:00
constexpr Vector(float x, float y, float z, float w ) requires(std::same_as<T, float> && Len == 4) : VectorBase<T, Len, Aligment>(x, y, z, w) {
2025-05-07 19:18:58 +02:00
}
2026-02-11 02:52:03 +01:00
constexpr Vector(float x, float y, float z) requires(std::same_as<T, float> && Len == 3) : VectorBase<T, Len, Aligment>(x, y, z) {
2025-05-07 19:18:58 +02:00
}
2026-02-11 02:52:03 +01:00
constexpr Vector(float x, float y) requires(std::same_as<T, float> && Len == 2) : VectorBase<T, Len, Aligment>(x, y) {
2025-05-07 19:18:58 +02:00
}
2026-02-19 06:36:34 +01:00
2026-02-11 02:52:03 +01:00
constexpr Vector() = default;
2025-05-07 19:18:58 +02:00
2026-02-19 07:09:53 +01:00
template <std::uint32_t BAlignment>
constexpr operator Vector<T, Len, BAlignment>() const {
Vector<T, Len, BAlignment> returnVector;
for(std::uint32_t i = 0; i < Len; i++) {
returnVector.v[i] = this->v[i];
}
return returnVector;
}
2026-02-05 01:51:31 +01:00
template <std::uint32_t Blen, std::uint32_t BAlignment>
2026-02-11 02:52:03 +01:00
constexpr Vector<T, Len, Aligment> operator+(Vector<T, Blen, BAlignment> b) const {
2026-02-05 01:18:05 +01:00
Vector<T, Len, Aligment> resultVector;
2026-01-29 20:19:20 +01:00
for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) {
2025-05-07 19:18:58 +02:00
resultVector.v[i] = this->v[i]+b.v[i];
}
return resultVector;
}
2026-02-05 01:51:31 +01:00
template <std::uint32_t Blen, std::uint32_t BAlignment>
2026-02-11 02:52:03 +01:00
constexpr Vector<T, Len, Aligment> operator-(Vector<T, Blen, BAlignment> b) const {
2026-02-05 01:18:05 +01:00
Vector<T, Len, Aligment> resultVector;
2026-01-29 20:19:20 +01:00
for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) {
2025-05-07 19:18:58 +02:00
resultVector.v[i] = this->v[i]-b.v[i];
}
return resultVector;
}
2026-02-11 02:52:03 +01:00
constexpr Vector<T, Len, Aligment> operator-(){
2026-02-05 01:18:05 +01:00
Vector<T, Len, Aligment> resultVector;
2026-01-29 20:19:20 +01:00
for(std::uint32_t i = 0; i < Len; i++) {
2025-05-07 19:18:58 +02:00
resultVector.v[i] = -this->v[i];
}
return resultVector;
}
2026-02-05 01:51:31 +01:00
template <std::uint32_t Blen, std::uint32_t BAlignment>
2026-02-11 02:52:03 +01:00
constexpr Vector<T, Len, Aligment> operator*(Vector<T, Blen, BAlignment> b) const {
2026-02-05 01:18:05 +01:00
Vector<T, Len, Aligment> resultVector;
2026-01-29 20:19:20 +01:00
for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) {
2025-05-07 19:18:58 +02:00
resultVector.v[i] = this->v[i]*b.v[i];
}
return resultVector;
}
2026-02-05 01:51:31 +01:00
template <std::uint32_t Blen, std::uint32_t BAlignment>
2026-02-11 02:52:03 +01:00
constexpr Vector<T, Len, Aligment> operator/(Vector<T, Blen, BAlignment> b) const {
2026-02-05 01:18:05 +01:00
Vector<T, Len, Aligment> resultVector;
2026-01-29 20:19:20 +01:00
for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) {
2025-05-07 19:18:58 +02:00
resultVector.v[i] = this->v[i]/b.v[i];
}
return resultVector;
}
2026-02-11 02:52:03 +01:00
template <std::uint32_t Blen, std::uint32_t BAlignment>
constexpr void operator+=(Vector<T, Blen, BAlignment> b){
for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) {
this->v[i]+=b.v[i];
}
2025-05-07 19:18:58 +02:00
}
2026-02-11 02:52:03 +01:00
template <std::uint32_t Blen, std::uint32_t BAlignment>
constexpr void operator-=(Vector<T, Blen, BAlignment> b){
for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) {
this->v[i]-=b.v[i];
}
}
template <std::uint32_t Blen, std::uint32_t BAlignment>
constexpr void operator*=(Vector<T, Blen, BAlignment> b){
for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) {
this->v[i]*=b.v[i];
}
}
template <std::uint32_t Blen, std::uint32_t BAlignment>
constexpr void operator/=(Vector<T, Blen, BAlignment> b){
for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) {
this->v[i]/=b.v[i];
2025-05-07 19:18:58 +02:00
}
}
2025-05-05 05:14:39 +02:00
2026-02-11 03:01:42 +01:00
template <typename BT>
2026-03-04 15:57:34 +01:00
constexpr Vector<T, Len, Aligment> operator+(BT b) const requires std::is_arithmetic_v<BT> {
2026-02-11 03:01:42 +01:00
Vector<T, Len, Aligment> resultVector;
for(std::uint32_t i = 0; i < Len; i++) {
resultVector.v[i] = this->v[i] + b;
}
return resultVector;
}
template <typename BT>
2026-03-04 15:57:34 +01:00
constexpr Vector<T, Len, Aligment> operator-(BT b) const requires std::is_arithmetic_v<BT> {
2026-02-11 03:01:42 +01:00
Vector<T, Len, Aligment> resultVector;
for(std::uint32_t i = 0; i < Len; i++) {
resultVector.v[i] = this->v[i] - b;
}
return resultVector;
}
template <typename BT>
2026-03-04 15:57:34 +01:00
constexpr Vector<T, Len, Aligment> operator*(BT b) const requires std::is_arithmetic_v<BT> {
2026-02-11 03:01:42 +01:00
Vector<T, Len, Aligment> resultVector;
for(std::uint32_t i = 0; i < Len; i++) {
resultVector.v[i] = this->v[i] * b;
}
return resultVector;
}
template <typename BT>
2026-03-04 15:57:34 +01:00
constexpr Vector<T, Len, Aligment> operator/(BT b) const requires std::is_arithmetic_v<BT> {
2026-02-11 03:01:42 +01:00
Vector<T, Len, Aligment> resultVector;
for(std::uint32_t i = 0; i < Len; i++) {
resultVector.v[i] = this->v[i] / b;
}
return resultVector;
}
template <typename BT>
2026-03-04 15:57:34 +01:00
constexpr void operator+=(BT b) requires std::is_arithmetic_v<BT>{
2026-02-11 03:01:42 +01:00
for(std::uint32_t i = 0; i < Len; i++) {
this->v[i] += b;
}
}
template <typename BT>
2026-03-04 15:57:34 +01:00
constexpr void operator-=(BT b) requires std::is_arithmetic_v<BT>{
2026-02-11 03:01:42 +01:00
for(std::uint32_t i = 0; i < Len; i++) {
this->v[i] -= b;
}
}
template <typename BT>
2026-03-04 15:57:34 +01:00
constexpr void operator*=(BT b) requires std::is_arithmetic_v<BT>{
2026-02-11 03:01:42 +01:00
for(std::uint32_t i = 0; i < Len; i++) {
this->v[i] *= b;
}
}
template <typename BT>
2026-03-04 15:57:34 +01:00
constexpr void operator/=(BT b) requires std::is_arithmetic_v<BT>{
2026-02-11 03:01:42 +01:00
for(std::uint32_t i = 0; i < Len; i++) {
this->v[i] /= b;
}
}
2026-02-19 07:00:58 +01:00
template <typename BT, std::uint32_t Blen, std::uint32_t BAlignment>
constexpr bool operator==(Vector<BT, Blen, BAlignment> b) const {
for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) {
if(this->v[i] != b.v[i]) {
2026-02-19 02:36:36 +01:00
return false;
}
}
return true;
}
2026-02-19 07:00:58 +01:00
template <typename BT, std::uint32_t Blen, std::uint32_t BAlignment>
constexpr bool operator!=(Vector<BT, Blen, BAlignment> b) const {
for(std::uint32_t i = 0; i < std::min(Len, Blen); i++) {
if(this->v[i] != b.v[i]) {
2026-02-19 02:36:36 +01:00
return true;
}
}
return false;
}
2026-02-11 02:52:03 +01:00
constexpr void Normalize() {
2025-05-07 19:18:58 +02:00
float fLength = Length();
2026-02-11 02:52:03 +01:00
if (fLength > 0) {
2025-05-07 19:18:58 +02:00
fLength = 1.0f / fLength;
}
2026-02-11 02:52:03 +01:00
for(std::uint32_t i = 0; i < Len; i++) {
this->v[i] *= fLength;
}
2025-05-07 19:18:58 +02:00
}
2026-02-11 03:07:31 +01:00
constexpr void Invert() {
for(std::uint32_t i = 0; i < Len; i++) {
this->v[i] = -this->v[i];
}
}
2026-02-11 02:52:03 +01:00
constexpr float Length() const {
2025-05-07 19:18:58 +02:00
float Result = LengthSq();
2026-01-29 20:19:20 +01:00
return std::sqrtf(Result);
2025-05-07 19:18:58 +02:00
}
2026-02-11 02:52:03 +01:00
constexpr float LengthSq() const {
return Dot(*this, *this);
2025-05-07 19:18:58 +02:00
}
2026-02-11 02:52:03 +01:00
template <typename AT, std::uint32_t Alen, std::uint32_t AAlignment, typename BT, std::uint32_t Blen, std::uint32_t BAlignment>
constexpr static Vector<T, Len, Aligment> Cross(Vector<AT, Alen, AAlignment> a, Vector<BT, Blen, BAlignment> b) requires(Len == 3 && Alen >= 3 && Blen >= 3) {
return Vector<T, Len, Aligment>(
(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])
2025-05-07 19:18:58 +02:00
);
2026-02-11 02:52:03 +01:00
}
2025-05-07 19:18:58 +02:00
2026-02-19 02:36:36 +01:00
template <typename AT, std::uint32_t Alen, std::uint32_t AAlignment>
constexpr static Vector<T, Len, Aligment> Normalize(Vector<AT, Alen, AAlignment> a) requires(Len == Alen) {
Vector<T, 3, 0> 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;
}
2026-02-11 02:52:03 +01:00
template <typename AT, std::uint32_t Alen, std::uint32_t AAlignment, typename BT, std::uint32_t Blen, std::uint32_t BAlignment>
constexpr static float Dot(Vector<AT, Alen, AAlignment> a, Vector<BT, Blen, BAlignment> 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;
2026-01-29 20:19:20 +01:00
}
2026-02-19 02:36:36 +01:00
template <typename AT, std::uint32_t AAlignment, typename BT, std::uint32_t BAlignment>
constexpr static Vector<T, 3, Aligment> Rotate(Vector<AT, 3, AAlignment> v, Vector<BT, 4, BAlignment> q) requires(Len == 3) {
Vector<T, 3, 0> qv(q.x, q.y, q.z);
Vector<T, 3, 0> t = Vector<T, 3, Aligment>::Cross(qv, v) * T(2);
return v + t * q.w + Vector<T, 3, Aligment>::Cross(qv, t);
}
2026-02-20 04:41:08 +01:00
template <typename AT, std::uint32_t AAlignment, typename BT, std::uint32_t BAlignment, typename PT, std::uint32_t PAlignment>
constexpr static Vector<T, 3, Aligment> RotatePivot(Vector<AT, 3, AAlignment> v, Vector<BT, 4, BAlignment> q, Vector<PT, 3, PAlignment> pivot) requires(Len == 3) {
Vector<T, 3, 0> translated = v - pivot;
Vector<T, 3, 0> qv(q.x, q.y, q.z);
Vector<T, 3, 0> t = Cross(qv, translated) * T(2);
Vector<T, 3, 0> rotated = translated + t * q.w +Cross(qv, t);
return rotated + pivot;
}
2026-02-19 02:36:36 +01:00
template <typename AT, std::uint32_t AAlignment, typename BT, std::uint32_t BAlignment, typename CT, std::uint32_t CAlignment>
constexpr static Vector<T, 4, Aligment> QuanternionFromBasis(Vector<AT, 3, AAlignment> right, Vector<BT, 3, BAlignment> up, Vector<CT, 3, CAlignment> 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<T, 4, Aligment> q;
if (trace > std::numeric_limits<T>::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;
}
2026-02-20 04:41:08 +01:00
constexpr static Vector<T, 4, Aligment> QuanternionFromEuler(T roll, T pitch, T yaw) {
T cr = std::cos(roll * 0.5);
T sr = std::sin(roll * 0.5);
T cp = std::cos(pitch * 0.5);
T sp = std::sin(pitch * 0.5);
T cy = std::cos(yaw * 0.5);
T sy = std::sin(yaw * 0.5);
return Vector<T, 4, Aligment>(
sr * cp * cy - cr * sp * sy,
cr * sp * cy + sr * cp * sy,
cr * cp * sy - sr * sp * cy,
cr * cp * cy + sr * sp * sy
);
}
2025-05-05 02:01:44 +02:00
};
2025-05-05 05:14:39 +02:00
}
2025-05-05 02:01:44 +02:00
2026-02-11 02:52:03 +01:00
template <typename T, std::uint32_t Aligment>
struct std::formatter<Crafter::Vector<T, 2, Aligment>> : std::formatter<std::string> {
auto format(const Crafter::Vector<T, 2, Aligment>& obj, format_context& ctx) const {
return std::formatter<std::string>::format(std::format("{{{}, {}}}",
obj.x, obj.y
), ctx);
}
};
template <typename T, std::uint32_t Aligment>
struct std::formatter<Crafter::Vector<T, 3, Aligment>> : std::formatter<std::string> {
auto format(const Crafter::Vector<T, 3, Aligment>& obj, format_context& ctx) const {
2025-05-05 05:14:39 +02:00
return std::formatter<std::string>::format(std::format("{{{}, {}, {}}}",
obj.x, obj.y, obj.z
), ctx);
}
2026-02-11 02:52:03 +01:00
};
template <typename T, std::uint32_t Aligment>
struct std::formatter<Crafter::Vector<T, 4, Aligment>> : std::formatter<std::string> {
auto format(const Crafter::Vector<T, 4, Aligment>& obj, format_context& ctx) const {
2026-02-05 01:18:05 +01:00
return std::formatter<std::string>::format(std::format("{{{}, {}, {}, {}}}",
obj.x, obj.y, obj.z, obj.w
), ctx);
}
2026-02-11 04:28:54 +01:00
};
template <typename T, std::uint32_t Len, std::uint32_t Aligment, typename BT>
2026-03-04 15:57:34 +01:00
constexpr Crafter::Vector<T, Len, Aligment> operator*(BT b, const Crafter::Vector<T, Len, Aligment>& v) requires std::is_arithmetic_v<BT> {
2026-02-11 04:28:54 +01:00
return v * b;
}