From 7a4ca89b14b98bc672d75ef76d905659073210dd Mon Sep 17 00:00:00 2001 From: Wellinator Date: Sun, 14 Aug 2022 16:52:06 -0300 Subject: [PATCH 1/4] refactor: implroves ray box collision accuracy --- engine/src/physics/ray.cpp | 55 +++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/engine/src/physics/ray.cpp b/engine/src/physics/ray.cpp index 6fafbaa..94430ab 100644 --- a/engine/src/physics/ray.cpp +++ b/engine/src/physics/ray.cpp @@ -33,41 +33,42 @@ float Ray::distanceToPoint(const Vec4& point) const { bool Ray::intersectBox(const Vec4& minCorner, const Vec4& maxCorner, float* outputDistance) const { - auto inv = invDir(); - inv.normalize(); + float t1 = (min->x - origin->x) / dir->x; + float t2 = (max->x - origin->x) / dir->x; + float t3 = (min->y - origin->y) / dir->y; + float t4 = (max->y - origin->y) / dir->y; + float t5 = (min->z - origin->z) / dir->z; + float t6 = (max->z - origin->z) / dir->z; - float tmin = (minCorner.x - this->origin.x) * inv.x; - float tmax = (maxCorner.x - this->origin.x) * inv.x; - float tymin = (minCorner.y - this->origin.y) * inv.y; - float tymax = (maxCorner.y - this->origin.y) * inv.y; - - if ((tmin > tymax) || (tymin > tmax)) { - return false; - } - - if (tymin > tmin) tmin = tymin; - - if (tymax < tmax) tmax = tymax; - - float tzmin = (minCorner.z - this->origin.z) * inv.z; - float tzmax = (maxCorner.z - this->origin.z) * inv.z; - - if ((tmin > tzmax) || (tzmin > tmax)) { - return false; - } - - if (tzmin > tmin) tmin = tzmin; - - if (tzmax < tmax) tmax = tzmax; + float tmin = MAX(MAX(MIN(t1, t2), MIN(t3, t4)), MIN(t5, t6)); + float tmax = MIN(MIN(MAX(t1, t2), MAX(t3, t4)), MAX(t5, t6)); + // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us if (tmax < 0) { + if (outputDistance != nullptr) { + *outputDistance = -1.0f; + } return false; } + // if tmin > tmax, ray doesn't intersect AABB + if (tmin > tmax) { + if (outputDistance != nullptr) { + *outputDistance = -1.0f; + } + return false; + } + + if (tmin < 0) { + if (outputDistance != nullptr) { + *outputDistance = tmax; + } + return true; + } + if (outputDistance != nullptr) { - *outputDistance = tmin >= 0 ? tmin : tmax; + *outputDistance = tmin; } - return true; } From 0558dd7612e61fb39f27336d3843c1fc4df5cdcc Mon Sep 17 00:00:00 2001 From: Wellinator Date: Sun, 14 Aug 2022 17:20:33 -0300 Subject: [PATCH 2/4] fix: MIN MAX definitions; refactor: reduce t variables to Vec4 --- engine/src/physics/ray.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/engine/src/physics/ray.cpp b/engine/src/physics/ray.cpp index 94430ab..a524d06 100644 --- a/engine/src/physics/ray.cpp +++ b/engine/src/physics/ray.cpp @@ -15,6 +15,9 @@ #include #include +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) + namespace Tyra { Ray::Ray() {} @@ -33,15 +36,11 @@ float Ray::distanceToPoint(const Vec4& point) const { bool Ray::intersectBox(const Vec4& minCorner, const Vec4& maxCorner, float* outputDistance) const { - float t1 = (min->x - origin->x) / dir->x; - float t2 = (max->x - origin->x) / dir->x; - float t3 = (min->y - origin->y) / dir->y; - float t4 = (max->y - origin->y) / dir->y; - float t5 = (min->z - origin->z) / dir->z; - float t6 = (max->z - origin->z) / dir->z; - - float tmin = MAX(MAX(MIN(t1, t2), MIN(t3, t4)), MIN(t5, t6)); - float tmax = MIN(MIN(MAX(t1, t2), MAX(t3, t4)), MAX(t5, t6)); + Vec4 _min = (minCorner - this->origin) / this->invDir(); + Vec4 _max = (minCorner - this->origin) / this->invDir(); + + float tmin = MAX(MAX(MIN(_min.x, _max.x), MIN(_min.y, _max.y)), MIN(_min.z, _max.z)); + float tmax = MIN(MIN(MAX(_min.x, _max.x), MAX(_min.y, _max.y)), MAX(_min.z, _max.z)); // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us if (tmax < 0) { From 0d15d0c7c8dc94c8ff0d567beecbc583236caf0f Mon Sep 17 00:00:00 2001 From: Wellinator Date: Sun, 14 Aug 2022 17:23:47 -0300 Subject: [PATCH 3/4] feat: add vec4 division operator --- engine/inc/math/vec4.hpp | 1 + engine/src/math/vec4.cpp | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/engine/inc/math/vec4.hpp b/engine/inc/math/vec4.hpp index 29cbf42..f688f92 100644 --- a/engine/inc/math/vec4.hpp +++ b/engine/inc/math/vec4.hpp @@ -56,6 +56,7 @@ class Vec4 { Vec4 operator*(const Vec4& v) const; Vec4 operator*(const float& v) const; Vec4 operator/(const float& v) const; + Vec4 operator/(const Vec4& v) const; Vec4 operator-(void) const; void operator=(const Vec4& v); void operator+=(const Vec4& v); diff --git a/engine/src/math/vec4.cpp b/engine/src/math/vec4.cpp index 559edf0..a01fc6f 100644 --- a/engine/src/math/vec4.cpp +++ b/engine/src/math/vec4.cpp @@ -77,6 +77,10 @@ Vec4 Vec4::operator/(const float& v) const { return Vec4(x / v, y / v, z / v, w); } +Vec4 Vec4::operator/(const Vec4& v) const { + return Vec4(x / v.x, y / v.y, z / v.z, w); +} + void Vec4::operator+=(const Vec4& v) { asm volatile( "lqc2 $vf4, 0x0(%0) \n\t" From 83f07f4789808713e9f80dc6290a5dfafa35997f Mon Sep 17 00:00:00 2001 From: Wellinator Date: Sun, 14 Aug 2022 17:37:55 -0300 Subject: [PATCH 4/4] refactor: apply std min/max --- engine/src/physics/ray.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/engine/src/physics/ray.cpp b/engine/src/physics/ray.cpp index a524d06..ab4b4e3 100644 --- a/engine/src/physics/ray.cpp +++ b/engine/src/physics/ray.cpp @@ -15,9 +15,6 @@ #include #include -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) - namespace Tyra { Ray::Ray() {} @@ -38,9 +35,13 @@ bool Ray::intersectBox(const Vec4& minCorner, const Vec4& maxCorner, float* outputDistance) const { Vec4 _min = (minCorner - this->origin) / this->invDir(); Vec4 _max = (minCorner - this->origin) / this->invDir(); - - float tmin = MAX(MAX(MIN(_min.x, _max.x), MIN(_min.y, _max.y)), MIN(_min.z, _max.z)); - float tmax = MIN(MIN(MAX(_min.x, _max.x), MAX(_min.y, _max.y)), MAX(_min.z, _max.z)); + + float tmin = + std::max(std::max(std::min(_min.x, _max.x), std::min(_min.y, _max.y)), + std::min(_min.z, _max.z)); + float tmax = + std::min(std::min(std::max(_min.x, _max.x), std::max(_min.y, _max.y)), + std::max(_min.z, _max.z)); // if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us if (tmax < 0) {