diff --git a/interfaces/Crafter.Math-BasicTypes.cppm b/interfaces/Crafter.Math-Basic.cppm similarity index 80% rename from interfaces/Crafter.Math-BasicTypes.cppm rename to interfaces/Crafter.Math-Basic.cppm index 8641a1e..68d3bc2 100755 --- a/interfaces/Crafter.Math-BasicTypes.cppm +++ b/interfaces/Crafter.Math-Basic.cppm @@ -18,9 +18,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -export module Crafter.Math:BasicTypes; +export module Crafter.Math:Basic; import std; namespace Crafter { - + template + constexpr T ToRadian(T degrees) { + return degrees * (std::numbers::pi / 180); + } } \ No newline at end of file diff --git a/interfaces/Crafter.Math-MatrixRowMajor.cppm b/interfaces/Crafter.Math-MatrixRowMajor.cppm index ab226dd..8cf9b5e 100755 --- a/interfaces/Crafter.Math-MatrixRowMajor.cppm +++ b/interfaces/Crafter.Math-MatrixRowMajor.cppm @@ -19,9 +19,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA export module Crafter.Math:MatrixRowMajor; -import :BasicTypes; +import :Basic; import :Vector; -import :Misc; import std; namespace Crafter { @@ -142,46 +141,6 @@ namespace Crafter { return result; } - static MatrixRowMajor Perspective(float fovAngleY, float aspectRatio, float nearZ, float farZ) requires(CollumSize == 4 && RowSize == 4 && Repeats == 1 && std::same_as) { - MatrixRowMajor M; - float SinFov; - float CosFov; - XMScalarSinCos(&SinFov, &CosFov, 0.5f * fovAngleY); - - float Height = CosFov / SinFov; - float Width = Height / aspectRatio; - float fRange = farZ / (nearZ - farZ); - - M.m[0][0] = Width; - M.m[0][1] = 0.0f; - M.m[0][2] = 0.0f; - M.m[0][3] = 0.0f; - - M.m[1][0] = 0.0f; - M.m[1][1] = Height; - M.m[1][2] = 0.0f; - M.m[1][3] = 0.0f; - - M.m[2][0] = 0.0f; - M.m[2][1] = 0.0f; - M.m[2][2] = fRange; - M.m[2][3] = -1.0f; - - M.m[3][0] = 0.0f; - M.m[3][1] = 0.0f; - M.m[3][2] = fRange * nearZ; - M.m[3][3] = 0.0f; - return M; - } - - static MatrixRowMajor Identity() requires(CollumSize == 4 && RowSize == 4 && Repeats == 1 && std::same_as) { - return MatrixRowMajor( - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - ); - } static MatrixRowMajor Identity() requires(CollumSize == 4 && RowSize == 3 && Repeats == 1 && std::same_as) { return MatrixRowMajor( 1, 0, 0, 0, @@ -189,8 +148,7 @@ namespace Crafter { 0, 0, 1, 0 ); } - - + static MatrixRowMajor Scaling(float x, float y, float z) requires(CollumSize == 4 && RowSize == 4 && Repeats == 1 && std::same_as) { return MatrixRowMajor( x, 0, 0, 0, diff --git a/interfaces/Crafter.Math-Misc.cppm b/interfaces/Crafter.Math-Misc.cppm deleted file mode 100644 index 9f88256..0000000 --- a/interfaces/Crafter.Math-Misc.cppm +++ /dev/null @@ -1,84 +0,0 @@ -/* -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:Misc; -import std; - -export namespace Crafter { - //------------------------------------------------------------------------------------- - // DirectXMathMisc.inl -- SIMD C++ Math library - // - // Copyright (c) Microsoft Corporation. - // Licensed under the MIT License. - // - // http://go.microsoft.com/fwlink/?LinkID=615560 - //------------------------------------------------------------------------------------- - constexpr float XM_PI = 3.141592654f; - constexpr float XM_2PI = 6.283185307f; - constexpr float XM_1DIVPI = 0.318309886f; - constexpr float XM_1DIV2PI = 0.159154943f; - constexpr float XM_PIDIV2 = 1.570796327f; - constexpr float XM_PIDIV4 = 0.785398163f; - - - inline void XMScalarSinCos(float* pSin, float* pCos, float Value) noexcept - { - // Map Value to y in [-pi,pi], x = 2*pi*quotient + remainder. - float quotient = XM_1DIV2PI * Value; - if (Value >= 0.0f) - { - quotient = static_cast(static_cast(quotient + 0.5f)); - } - else - { - quotient = static_cast(static_cast(quotient - 0.5f)); - } - float y = Value - XM_2PI * quotient; - - // Map y to [-pi/2,pi/2] with sin(y) = sin(Value). - float sign; - if (y > XM_PIDIV2) - { - y = XM_PI - y; - sign = -1.0f; - } - else if (y < -XM_PIDIV2) - { - y = -XM_PI - y; - sign = -1.0f; - } - else - { - sign = +1.0f; - } - - float y2 = y * y; - - // 11-degree minimax approximation - *pSin = (((((-2.3889859e-08f * y2 + 2.7525562e-06f) * y2 - 0.00019840874f) * y2 + 0.0083333310f) * y2 - 0.16666667f) * y2 + 1.0f) * y; - - // 10-degree minimax approximation - float p = ((((-2.6051615e-07f * y2 + 2.4760495e-05f) * y2 - 0.0013888378f) * y2 + 0.041666638f) * y2 - 0.5f) * y2 + 1.0f; - *pCos = sign * p; - } - - constexpr float ToRadian(float degrees) { - return degrees * (std::numbers::pi / 180); - } -} \ No newline at end of file diff --git a/interfaces/Crafter.Math-Ray.cppm b/interfaces/Crafter.Math-Ray.cppm new file mode 100755 index 0000000..cadbe3e --- /dev/null +++ b/interfaces/Crafter.Math-Ray.cppm @@ -0,0 +1,62 @@ +/* +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:Ray; +import :Vector; +import std; + +namespace Crafter { + export template + T IntersectionTestRayTriangle(Vector vert0, Vector vert1, Vector vert2, Vector rayOrigin, Vector rayDir) { + constexpr float EPSILON = 0.0000001; + Vector edge1 = vert1 - vert0; + Vector edge2 = vert2 - vert0; + + Vector h = Vector::Cross(rayDir, edge2); + float determinant = Vector::Dot(edge1, h); + + + if(determinant < 0) { + return -1; + } + + if (determinant > -EPSILON && determinant < EPSILON) { + return -1; + } + + float inverse_determinant = 1.0 / determinant; + + Vector origins_diff_vector = rayOrigin - vert0; + float u = Vector::Dot(origins_diff_vector, h) * inverse_determinant; + + if (u < 0.0 || u > 1.0) + { + return false; + } + + Vector q = Vector::Cross(origins_diff_vector, edge1); + float v = inverse_determinant * Vector::Dot(rayDir, q); + + if (v < 0.0 || u + v > 1.0) { + return -1; + } + + return inverse_determinant * Vector::Dot(edge2, q); + } +} \ No newline at end of file diff --git a/interfaces/Crafter.Math-Vector.cppm b/interfaces/Crafter.Math-Vector.cppm index a3a1c9d..75232d9 100755 --- a/interfaces/Crafter.Math-Vector.cppm +++ b/interfaces/Crafter.Math-Vector.cppm @@ -20,9 +20,6 @@ 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 { @@ -45,10 +42,10 @@ namespace Crafter { T x, y; }; }; - VectorBase(float x, float y): x(x), y(y) { + constexpr VectorBase(float x, float y): x(x), y(y) { } - VectorBase() = default; + constexpr VectorBase() = default; }; template @@ -59,10 +56,10 @@ namespace Crafter { T x, y, z; }; }; - VectorBase(float x, float y, float z): x(x), y(y), z(z) { + constexpr VectorBase(float x, float y, float z): x(x), y(y), z(z) { } - VectorBase() = default; + constexpr VectorBase() = default; }; template @@ -73,10 +70,10 @@ namespace Crafter { T x, y, z, w; }; }; - VectorBase(float x, float y, float z, float w): x(x), y(y), z(z), w(w) { + constexpr VectorBase(float x, float y, float z, float w): x(x), y(y), z(z), w(w) { } - VectorBase() = default; + constexpr VectorBase() = default; }; template @@ -100,10 +97,10 @@ namespace Crafter { T x, y; }; }; - VectorBase(float x, float y): x(x), y(y) { + constexpr VectorBase(float x, float y): x(x), y(y) { } - VectorBase() = default; + constexpr VectorBase() = default; }; template @@ -114,10 +111,10 @@ namespace Crafter { T x, y, z; }; }; - VectorBase(float x, float y, float z): x(x), y(y), z(z) { + constexpr VectorBase(float x, float y, float z): x(x), y(y), z(z) { } - VectorBase() = default; + constexpr VectorBase() = default; }; template @@ -128,49 +125,28 @@ namespace Crafter { T x, y, z, w; }; }; - VectorBase(float x, float y, float z, float w): x(x), y(y), z(z), w(w) { + constexpr VectorBase(float x, float y, float z, float w): x(x), y(y), z(z), w(w) { } - VectorBase() = default; + constexpr 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) { + constexpr 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) { + constexpr 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) { + constexpr 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 - ); - } + constexpr Vector() = default; template - Vector operator+(Vector b){ + 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]; @@ -178,14 +154,14 @@ namespace Crafter { return resultVector; } template - Vector operator-(Vector b){ + 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; } - Vector operator-(){ + constexpr Vector operator-(){ Vector resultVector; for(std::uint32_t i = 0; i < Len; i++) { resultVector.v[i] = -this->v[i]; @@ -193,7 +169,7 @@ namespace Crafter { return resultVector; } template - Vector operator*(Vector b){ + 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]; @@ -201,141 +177,101 @@ namespace Crafter { return resultVector; } template - Vector operator/(Vector b){ + 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; } - - 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); + 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]; + } } - Vector Normalize() requires(Len == 3) { + constexpr void Normalize() { float fLength = Length(); - // Prevent divide by zero - if (fLength > 0) - { + 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; + for(std::uint32_t i = 0; i < Len; i++) { + this->v[i] *= fLength; } - - return Vector(this->v[0] * fLength, this->v[1] * fLength, this->v[2] * fLength, this->v[3] * fLength); } - float Length() - { + constexpr float Length() const { float Result = LengthSq(); return std::sqrtf(Result); } - Vector ReciprocalLength() requires(Len == 3) { - Vector Result = LengthSq(); - Result = ReciprocalSqrt(Result); - return Result; + constexpr float LengthSq() const { + return Dot(*this, *this); } - 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]) + 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]) ); - } + } - 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 + 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 <> -struct std::formatter> : std::formatter { - auto format(const Crafter::Vector& obj, format_context& ctx) const { +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); } - auto format(const Crafter::Vector& obj, format_context& ctx) const { +}; + +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); diff --git a/interfaces/Crafter.Math.cppm b/interfaces/Crafter.Math.cppm index 340b1e9..bdf48ce 100644 --- a/interfaces/Crafter.Math.cppm +++ b/interfaces/Crafter.Math.cppm @@ -19,7 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ export module Crafter.Math; -export import :BasicTypes; +export import :Basic; export import :Vector; export import :MatrixRowMajor; -export import :Misc; \ No newline at end of file +export import :Ray; \ No newline at end of file diff --git a/interfaces/main.cpp b/interfaces/main.cpp new file mode 100644 index 0000000..af1b2c5 --- /dev/null +++ b/interfaces/main.cpp @@ -0,0 +1,13 @@ +import Crafter.Math; +import std; + +using namespace Crafter; + +int main() { + Vector test(1,2,3); + Vector test2(1,2,3); + Vector test3(1,2,3); + Vector test4(1,2,3); + Vector test5(1,2,3); + std::cout << IntersectionTestRayTriangle(test, test2, test3, test4, test5) << std::endl; +} \ No newline at end of file diff --git a/project.json b/project.json index de8a6f9..3ba2af5 100644 --- a/project.json +++ b/project.json @@ -3,7 +3,7 @@ "configurations": [ { "name": "base", - "interfaces": ["interfaces/Crafter.Math-Vector", "interfaces/Crafter.Math-BasicTypes", "interfaces/Crafter.Math-MatrixRowMajor", "interfaces/Crafter.Math-Misc", "interfaces/Crafter.Math"], + "interfaces": ["interfaces/Crafter.Math-Vector", "interfaces/Crafter.Math-Basic", "interfaces/Crafter.Math-MatrixRowMajor", "interfaces/Crafter.Math", "interfaces/Crafter.Math-Ray"], "implementations": [] }, { @@ -16,6 +16,12 @@ "name": "lib-debug", "extends": ["lib"], "debug": true + }, + { + "name": "test", + "implementations": ["interfaces/main"], + "extends": ["base"], + "debug": true } ] } \ No newline at end of file