added comparison
This commit is contained in:
parent
2daa51680a
commit
05fbd3685b
5 changed files with 255 additions and 82 deletions
|
|
@ -1,78 +1,124 @@
|
||||||
/*
|
/*
|
||||||
Crafter®.Math
|
Crafter®.Math
|
||||||
Copyright (C) 2026 Catcrafts®
|
Copyright (C) 2026 Catcrafts®
|
||||||
catcrafts.net
|
catcrafts.net
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
License version 3.0 as published by the Free Software Foundation;
|
License version 3.0 as published by the Free Software Foundation;
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
Lesser General Public License for more details.
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this library; if not, write to the Free Software
|
License along with this library; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export module Crafter.Math:Ray;
|
export module Crafter.Math:Intersection;
|
||||||
import :Vector;
|
import :Vector;
|
||||||
import std;
|
import std;
|
||||||
|
|
||||||
namespace Crafter {
|
namespace Crafter {
|
||||||
export template<typename T>
|
export template<typename T>
|
||||||
constexpr T IntersectionTestRayTriangle(Vector<T, 3, 0> vert0, Vector<T, 3, 0> vert1, Vector<T, 3, 0> vert2, Vector<T, 3, 0> rayOrigin, Vector<T, 3, 0> rayDir) {
|
constexpr T IntersectionTestRayTriangle(Vector<T, 3, 0> vert0, Vector<T, 3, 0> vert1, Vector<T, 3, 0> vert2, Vector<T, 3, 0> rayOrigin, Vector<T, 3, 0> rayDir) {
|
||||||
constexpr T EPSILON = 0.0000001;
|
Vector<T, 3, 0> edge1 = vert1 - vert0;
|
||||||
Vector<T, 3, 0> edge1 = vert1 - vert0;
|
Vector<T, 3, 0> edge2 = vert2 - vert0;
|
||||||
Vector<T, 3, 0> edge2 = vert2 - vert0;
|
|
||||||
|
Vector<T, 3, 0> h = Vector<T, 3, 0>::Cross(rayDir, edge2);
|
||||||
Vector<T, 3, 0> h = Vector<T, 3, 0>::Cross(rayDir, edge2);
|
T determinant = Vector<T, 3, 0>::Dot(edge1, h);
|
||||||
T determinant = Vector<T, 3, 0>::Dot(edge1, h);
|
|
||||||
|
if (determinant <= std::numeric_limits<T>::epsilon()) {
|
||||||
if (determinant <= EPSILON) {
|
return std::numeric_limits<T>::max();
|
||||||
return std::numeric_limits<T>::max();
|
}
|
||||||
}
|
|
||||||
|
T inverse_determinant = T(1) / determinant;
|
||||||
T inverse_determinant = T(1) / determinant;
|
|
||||||
|
Vector<T, 3, 0> origins_diff_vector = rayOrigin - vert0;
|
||||||
Vector<T, 3, 0> origins_diff_vector = rayOrigin - vert0;
|
T u = Vector<T, 3, 0>::Dot(origins_diff_vector, h) * inverse_determinant;
|
||||||
T u = Vector<T, 3, 0>::Dot(origins_diff_vector, h) * inverse_determinant;
|
|
||||||
|
if (u < 0.0 || u > 1.0)
|
||||||
if (u < 0.0 || u > 1.0)
|
{
|
||||||
{
|
return std::numeric_limits<T>::max();
|
||||||
return std::numeric_limits<T>::max();
|
}
|
||||||
}
|
|
||||||
|
Vector<T, 3, 0> q = Vector<T, 3, 0>::Cross(origins_diff_vector, edge1);
|
||||||
Vector<T, 3, 0> q = Vector<T, 3, 0>::Cross(origins_diff_vector, edge1);
|
T v = inverse_determinant * Vector<T, 3, 0>::Dot(rayDir, q);
|
||||||
T v = inverse_determinant * Vector<T, 3, 0>::Dot(rayDir, q);
|
|
||||||
|
if (v < 0.0 || u + v > 1.0) {
|
||||||
if (v < 0.0 || u + v > 1.0) {
|
return std::numeric_limits<T>::max();
|
||||||
return std::numeric_limits<T>::max();
|
}
|
||||||
}
|
|
||||||
|
return inverse_determinant * Vector<T, 3, 0>::Dot(edge2, q);
|
||||||
return inverse_determinant * Vector<T, 3, 0>::Dot(edge2, q);
|
}
|
||||||
}
|
|
||||||
|
export template<typename T>
|
||||||
export template<typename T>
|
constexpr T IntersectionTestRaySphere(Vector<T, 3, 0> position, T radius, Vector<T, 3, 0> rayOrigin, Vector<T, 3, 0> rayDir) {
|
||||||
constexpr T IntersectionTestRaySphere(Vector<T, 3, 0> position, T radius, Vector<T, 3, 0> rayOrigin, Vector<T, 3, 0> rayDir) {
|
T a = Vector<T, 3, 0>::Dot(rayDir, rayDir);
|
||||||
T a = Vector<T, 3, 0>::Dot(rayDir, rayDir);
|
T b = Vector<T, 3, 0>::Dot(rayDir, (T(2) * (rayOrigin - position)));
|
||||||
T b = Vector<T, 3, 0>::Dot(rayDir, (T(2) * (rayOrigin - position)));
|
T c = Vector<T, 3, 0>::Dot(position, position) + Vector<T, 3, 0>::Dot(rayOrigin, rayOrigin) - T(2) * Vector<T, 3, 0>::Dot(rayOrigin, position) - radius * radius;
|
||||||
T c = Vector<T, 3, 0>::Dot(position, position) + Vector<T, 3, 0>::Dot(rayOrigin, rayOrigin) - T(2) * Vector<T, 3, 0>::Dot(rayOrigin, position) - radius * radius;
|
T d = b * b + (T(-4)) * a * c;
|
||||||
T d = b * b + (T(-4)) * a * c;
|
|
||||||
|
if (d < 0) {
|
||||||
if (d < 0) {
|
return std::numeric_limits<T>::max();
|
||||||
return std::numeric_limits<T>::max();
|
}
|
||||||
}
|
|
||||||
|
d = std::sqrt(d);
|
||||||
d = std::sqrt(d);
|
|
||||||
|
float t = (T(-0.5)) * (b + d) / a;
|
||||||
float t = (T(-0.5)) * (b + d) / a;
|
if (t > T(0)) {
|
||||||
if (t > T(0)) {
|
return t;
|
||||||
return t;
|
} else {
|
||||||
} else {
|
return std::numeric_limits<T>::max();
|
||||||
return std::numeric_limits<T>::max();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
export template<typename T>
|
||||||
|
constexpr T IntersectionTestRayOrientedBox(Vector<T, 3, 0> boxPosition, Vector<T, 3, 0> boxSize, Vector<T, 4, 0> boxRotation, Vector<T, 3, 0> rayOrigin, Vector<T, 3, 0> rayDir) {
|
||||||
|
Vector<T, 4, 0> invRot(
|
||||||
|
-boxRotation.x,
|
||||||
|
-boxRotation.y,
|
||||||
|
-boxRotation.z,
|
||||||
|
boxRotation.w
|
||||||
|
);
|
||||||
|
|
||||||
|
Vector<T, 3, 0> localOrigin = Vector<T, 3, 0>::Rotate(rayOrigin - boxPosition, invRot);
|
||||||
|
Vector<T, 3, 0> localDir = Vector<T, 3, 0>::Rotate(rayDir, invRot);
|
||||||
|
|
||||||
|
Vector<T,3,0> halfExtents = boxSize * T(0.5);
|
||||||
|
|
||||||
|
T tMin = T(0);
|
||||||
|
T tMax = std::numeric_limits<T>::max();
|
||||||
|
|
||||||
|
for (std::uint32_t i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
if (std::abs(localDir.v[i]) < std::numeric_limits<T>::epsilon())
|
||||||
|
{
|
||||||
|
if (localOrigin.v[i] < -halfExtents.v[i] || localOrigin.v[i] > halfExtents.v[i]) {
|
||||||
|
return std::numeric_limits<T>::max();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
T invD = T(1) / localDir.v[i];
|
||||||
|
T t1 = (-halfExtents.v[i] - localOrigin.v[i]) * invD;
|
||||||
|
T t2 = ( halfExtents.v[i] - localOrigin.v[i]) * invD;
|
||||||
|
|
||||||
|
if (t1 > t2) {
|
||||||
|
std::swap(t1, t2);
|
||||||
|
}
|
||||||
|
|
||||||
|
tMin = std::max(tMin, t1);
|
||||||
|
tMax = std::min(tMax, t2);
|
||||||
|
|
||||||
|
if (tMin > tMax) {
|
||||||
|
return std::numeric_limits<T>::max();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (tMin >= T(0)) ? tMin : tMax;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -30,7 +30,7 @@ namespace Crafter {
|
||||||
struct __attribute__((packed)) VectorBase<T, 1, Aligment> {
|
struct __attribute__((packed)) VectorBase<T, 1, Aligment> {
|
||||||
union {
|
union {
|
||||||
T v[Aligment];
|
T v[Aligment];
|
||||||
T x;
|
T x, r;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -41,6 +41,9 @@ namespace Crafter {
|
||||||
struct __attribute__((packed)) {
|
struct __attribute__((packed)) {
|
||||||
T x, y;
|
T x, y;
|
||||||
};
|
};
|
||||||
|
struct __attribute__((packed)) {
|
||||||
|
T r, g;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
constexpr VectorBase<T, 2, Aligment>(float x, float y): x(x), y(y) {
|
constexpr VectorBase<T, 2, Aligment>(float x, float y): x(x), y(y) {
|
||||||
|
|
||||||
|
|
@ -55,6 +58,9 @@ namespace Crafter {
|
||||||
struct __attribute__((packed)) {
|
struct __attribute__((packed)) {
|
||||||
T x, y, z;
|
T x, y, z;
|
||||||
};
|
};
|
||||||
|
struct __attribute__((packed)) {
|
||||||
|
T r, g, b;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
constexpr VectorBase<T, 3, Aligment>(float x, float y, float z): x(x), y(y), z(z) {
|
constexpr VectorBase<T, 3, Aligment>(float x, float y, float z): x(x), y(y), z(z) {
|
||||||
|
|
||||||
|
|
@ -69,6 +75,9 @@ namespace Crafter {
|
||||||
struct __attribute__((packed)) {
|
struct __attribute__((packed)) {
|
||||||
T x, y, z, w;
|
T x, y, z, w;
|
||||||
};
|
};
|
||||||
|
struct __attribute__((packed)) {
|
||||||
|
T r, g, b, a;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
constexpr VectorBase<T, 4, Aligment>(float x, float y, float z, float w): x(x), y(y), z(z), w(w) {
|
constexpr VectorBase<T, 4, Aligment>(float x, float y, float z, float w): x(x), y(y), z(z), w(w) {
|
||||||
|
|
||||||
|
|
@ -85,7 +94,7 @@ namespace Crafter {
|
||||||
struct VectorBase<T, 1, 0> {
|
struct VectorBase<T, 1, 0> {
|
||||||
union {
|
union {
|
||||||
T v[1];
|
T v[1];
|
||||||
T x;
|
T x, r;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -96,6 +105,9 @@ namespace Crafter {
|
||||||
struct {
|
struct {
|
||||||
T x, y;
|
T x, y;
|
||||||
};
|
};
|
||||||
|
struct {
|
||||||
|
T r, g;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
constexpr VectorBase<T, 2, 0>(float x, float y): x(x), y(y) {
|
constexpr VectorBase<T, 2, 0>(float x, float y): x(x), y(y) {
|
||||||
|
|
||||||
|
|
@ -110,6 +122,9 @@ namespace Crafter {
|
||||||
struct {
|
struct {
|
||||||
T x, y, z;
|
T x, y, z;
|
||||||
};
|
};
|
||||||
|
struct {
|
||||||
|
T r, g, b;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
constexpr VectorBase<T, 3, 0>(float x, float y, float z): x(x), y(y), z(z) {
|
constexpr VectorBase<T, 3, 0>(float x, float y, float z): x(x), y(y), z(z) {
|
||||||
|
|
||||||
|
|
@ -124,6 +139,9 @@ namespace Crafter {
|
||||||
struct {
|
struct {
|
||||||
T x, y, z, w;
|
T x, y, z, w;
|
||||||
};
|
};
|
||||||
|
struct {
|
||||||
|
T r, g, b, a;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
constexpr VectorBase<T, 4, 0>(float x, float y, float z, float w): x(x), y(y), z(z), w(w) {
|
constexpr VectorBase<T, 4, 0>(float x, float y, float z, float w): x(x), y(y), z(z), w(w) {
|
||||||
|
|
||||||
|
|
@ -274,6 +292,25 @@ namespace Crafter {
|
||||||
return returnVector;
|
return returnVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename BT>
|
||||||
|
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 <typename BT>
|
||||||
|
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() {
|
constexpr void Normalize() {
|
||||||
float fLength = Length();
|
float fLength = Length();
|
||||||
|
|
||||||
|
|
@ -310,6 +347,21 @@ namespace Crafter {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename AT, std::uint32_t Alen, std::uint32_t AAlignment, typename BT, std::uint32_t Blen, std::uint32_t BAlignment>
|
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) {
|
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];
|
float accumulate = a.v[0] * b.v[0];
|
||||||
|
|
@ -318,6 +370,64 @@ namespace Crafter {
|
||||||
}
|
}
|
||||||
return accumulate;
|
return accumulate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,4 +22,4 @@ export module Crafter.Math;
|
||||||
export import :Basic;
|
export import :Basic;
|
||||||
export import :Vector;
|
export import :Vector;
|
||||||
export import :MatrixRowMajor;
|
export import :MatrixRowMajor;
|
||||||
export import :Ray;
|
export import :Intersection;
|
||||||
|
|
@ -4,5 +4,22 @@ import std;
|
||||||
using namespace Crafter;
|
using namespace Crafter;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
std::cout << IntersectionTestRaySphere<float>({0,0,0}, 10, {0,0,-100}, {0,1,0}) << std::endl;
|
// // Test Ray-OrientedBox intersection
|
||||||
|
// Vector<float, 3, 0> boxPos(0.0f, 0.0f, 0.0f);
|
||||||
|
// Vector<float, 3, 0> boxSize(2.0f, 2.0f, 2.0f);
|
||||||
|
// Vector<float, 3, 0> boxRot(0.0f, 0.0f, 0.0f); // No rotation
|
||||||
|
// Vector<float, 3, 0> rayOrigin(0.0f, 0.0f, -5.0f);
|
||||||
|
// Vector<float, 3, 0> rayDir(0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
// float hitDistance = IntersectionTestRayOrientedBox(boxPos, boxSize, boxRot, rayOrigin, rayDir);
|
||||||
|
|
||||||
|
// if (hitDistance < std::numeric_limits<float>::max()) {
|
||||||
|
// // Hit occurred
|
||||||
|
// std::cout << "Ray-OrientedBox intersection at distance: " << hitDistance << std::endl;
|
||||||
|
// } else {
|
||||||
|
// // No hit
|
||||||
|
// std::cout << "No intersection with Ray-OrientedBox" << std::endl;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "base",
|
"name": "base",
|
||||||
"interfaces": ["interfaces/Crafter.Math-Vector", "interfaces/Crafter.Math-Basic", "interfaces/Crafter.Math-MatrixRowMajor", "interfaces/Crafter.Math", "interfaces/Crafter.Math-Ray"],
|
"interfaces": ["interfaces/Crafter.Math-Vector", "interfaces/Crafter.Math-Basic", "interfaces/Crafter.Math-MatrixRowMajor", "interfaces/Crafter.Math", "interfaces/Crafter.Math-Intersection"],
|
||||||
"implementations": []
|
"implementations": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue