From 919d931b4ed736649236ee366b3968edc54401b1 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Fri, 26 Apr 2024 17:36:57 +0900 Subject: [PATCH 01/15] Impl Sphere/Sphere and Sphere/AABB collision TODO: Impl Sphere/Generic-Box collision --- src/sc_sacd.cpp | 166 ++++++++++++++++++++++++++++++++++++++++++++++++ src/sc_sacd.h | 24 +++++++ src/test.cpp | 91 ++++++++++++++++++++++++++ 3 files changed, 281 insertions(+) diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index f97bb3c..a5ab6b1 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -9,10 +9,24 @@ // Private Helpers BEGIN // ============================================================================= +constexpr float INV_SQRT2 = 0.70710678118654752440F; + SC_SACD_Vec3 operator+(const SC_SACD_Vec3 &a, const SC_SACD_Vec3 &b) { return SC_SACD_Vec3{a.x + b.x, a.y + b.y, a.z + b.z}; } +SC_SACD_Vec3 operator-(const SC_SACD_Vec3 &a, const SC_SACD_Vec3 &b) { + return SC_SACD_Vec3{a.x - b.x, a.y - b.y, a.z - b.z}; +} + +SC_SACD_Vec3 operator*(const SC_SACD_Vec3 &a, float scalar) { + return SC_SACD_Vec3{a.x * scalar, a.y * scalar, a.z * scalar}; +} + +SC_SACD_Vec3 operator/(const SC_SACD_Vec3 &a, float scalar) { + return SC_SACD_Vec3{a.x / scalar, a.y / scalar, a.z / scalar}; +} + std::vector SC_SACD_Get_Box_Normals( const SC_SACD_Generic_Box *box) { std::vector normals; @@ -184,6 +198,141 @@ int SC_SACD_AABB_Generic_Box_Collision(const SC_SACD_AABB_Box *a, return SC_SACD_Generic_Box_Collision(&a_conv, b); } +int SC_SACD_Sphere_Collision(const SC_SACD_Sphere *a, const SC_SACD_Sphere *b) { + SC_SACD_Vec3 vec{a->x - b->x, a->y - b->y, a->z - b->z}; + + return (a->radius + b->radius) > std::sqrt(SC_SACD_Dot_Product(vec, vec)) ? 1 + : 0; +} + +int SC_SACD_Sphere_AABB_Box_Collision(const SC_SACD_Sphere *sphere, + const SC_SACD_AABB_Box *box) { + std::vector dirs{// yz-plane + {0.0F, INV_SQRT2, INV_SQRT2}, + // xz-plane + {INV_SQRT2, 0.0F, INV_SQRT2}, + // xy-plane + {INV_SQRT2, INV_SQRT2, 0.0F}}; + SC_SACD_Vec3 pos{box->x, box->y, box->z}; + SC_SACD_Vec3 sphere_pos{sphere->x, sphere->y, sphere->z}; + + for (unsigned int i = 0; i < 3; ++i) { + SC_SACD_Vec3 side_pos = pos; + + // Side 1 of 2. + + // Get point on side. + switch (i) { + case 0: // yz-plane + side_pos.x += box->width / 2.0F; + break; + case 1: // xz-plane + side_pos.y += box->height / 2.0F; + break; + case 2: // xy-plane + side_pos.z += box->depth / 2.0F; + break; + } + + // Calculate closest point to "side". + SC_SACD_Vec3 closest_point = + SC_SACD_Closest_Point_Dir_Normalized(&side_pos, &dirs[i], &sphere_pos); + // Calculate diff between closest and sphere. + SC_SACD_Vec3 point_diff = closest_point - sphere_pos; + float magnitude = std::sqrt(SC_SACD_Dot_Product(point_diff, point_diff)); + + if (magnitude < sphere->radius) { + // Check if point is on side. + switch (i) { + case 0: // yz-plane + if (closest_point.y > side_pos.y - box->height / 2.0F && + closest_point.y < side_pos.y + box->height / 2.0F && + closest_point.z > side_pos.z - box->depth / 2.0F && + closest_point.z < side_pos.z + box->depth / 2.0F) { + return 1; + } + break; + case 1: // xz-plane + if (closest_point.x > side_pos.x - box->width / 2.0F && + closest_point.x < side_pos.x + box->width / 2.0F && + closest_point.z > side_pos.z - box->depth / 2.0F && + closest_point.z < side_pos.z + box->depth / 2.0F) { + return 1; + } + break; + case 2: // xy-plane + if (closest_point.x > side_pos.x - box->width / 2.0F && + closest_point.x < side_pos.x + box->width / 2.0F && + closest_point.y > side_pos.y - box->height / 2.0F && + closest_point.y < side_pos.y + box->height / 2.0F) { + return 1; + } + break; + } + } + + // Side 2 of 2. + + // Get point on side. + switch (i) { + case 0: // yz-plane + side_pos.x -= box->width / 2.0F; + break; + case 1: // xz-plane + side_pos.y -= box->height / 2.0F; + break; + case 2: // xy-plane + side_pos.z -= box->depth / 2.0F; + break; + } + + // Calculate closest point to "side". + closest_point = + SC_SACD_Closest_Point_Dir_Normalized(&side_pos, &dirs[i], &sphere_pos); + // Calculate diff between closest and sphere. + point_diff = closest_point - sphere_pos; + magnitude = std::sqrt(SC_SACD_Dot_Product(point_diff, point_diff)); + + if (magnitude < sphere->radius) { + // Check if point is on side. + switch (i) { + case 0: // yz-plane + if (closest_point.y > side_pos.y - box->height / 2.0F && + closest_point.y < side_pos.y + box->height / 2.0F && + closest_point.z > side_pos.z - box->depth / 2.0F && + closest_point.z < side_pos.z + box->depth / 2.0F) { + return 1; + } + break; + case 1: // xz-plane + if (closest_point.x > side_pos.x - box->width / 2.0F && + closest_point.x < side_pos.x + box->width / 2.0F && + closest_point.z > side_pos.z - box->depth / 2.0F && + closest_point.z < side_pos.z + box->depth / 2.0F) { + return 1; + } + break; + case 2: // xy-plane + if (closest_point.x > side_pos.x - box->width / 2.0F && + closest_point.x < side_pos.x + box->width / 2.0F && + closest_point.y > side_pos.y - box->height / 2.0F && + closest_point.y < side_pos.y + box->height / 2.0F) { + return 1; + } + break; + } + } + } + + return 0; +} + +int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere, + const SC_SACD_Generic_Box *box) { + // TODO + return 0; +} + float SC_SACD_Dot_Product(const SC_SACD_Vec3 a, const SC_SACD_Vec3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; } @@ -263,3 +412,20 @@ SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec, float x_axis, return SC_SACD_Mat3_Vec3_Mult(&mat, result); } + +SC_SACD_Vec3 SC_SACD_Closest_Point_Dir_Normalized(const SC_SACD_Vec3 *pos, + const SC_SACD_Vec3 *dir, + const SC_SACD_Vec3 *point) { + float alpha = + SC_SACD_Dot_Product(*dir, *point) - SC_SACD_Dot_Product(*dir, *pos); + return *pos + *dir * alpha; +} + +SC_SACD_Vec3 SC_SACD_Closest_Point(const SC_SACD_Vec3 *pos, + const SC_SACD_Vec3 *dir, + const SC_SACD_Vec3 *point) { + float alpha = + (SC_SACD_Dot_Product(*dir, *point) - SC_SACD_Dot_Product(*dir, *pos)) / + SC_SACD_Dot_Product(*dir, *dir); + return *pos + *dir * alpha; +} diff --git a/src/sc_sacd.h b/src/sc_sacd.h index 4893046..38e1f0a 100644 --- a/src/sc_sacd.h +++ b/src/sc_sacd.h @@ -60,6 +60,13 @@ typedef struct SC_SACD_EXPORT SC_SACD_Generic_Box { float z_radians; } SC_SACD_Generic_Box; +typedef struct SC_SACD_EXPORT SC_SACD_Sphere { + float x; + float y; + float z; + float radius; +} SC_SACD_Sphere; + /// Returns non-zero if there is collision. SC_SACD_EXPORT int SC_SACD_AABB_Box_Collision(const SC_SACD_AABB_Box *a, const SC_SACD_AABB_Box *b); @@ -72,6 +79,15 @@ SC_SACD_EXPORT int SC_SACD_Generic_Box_Collision(const SC_SACD_Generic_Box *a, SC_SACD_EXPORT int SC_SACD_AABB_Generic_Box_Collision( const SC_SACD_AABB_Box *a, const SC_SACD_Generic_Box *b); +SC_SACD_EXPORT int SC_SACD_Sphere_Collision(const SC_SACD_Sphere *a, + const SC_SACD_Sphere *b); + +SC_SACD_EXPORT int SC_SACD_Sphere_AABB_Box_Collision( + const SC_SACD_Sphere *sphere, const SC_SACD_AABB_Box *box); + +SC_SACD_EXPORT int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere, + const SC_SACD_Generic_Box *box); + SC_SACD_EXPORT float SC_SACD_Dot_Product(const SC_SACD_Vec3 a, const SC_SACD_Vec3 b); @@ -85,6 +101,14 @@ SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec, float x_axis, float y_axis, float z_axis); +SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Closest_Point_Dir_Normalized( + const SC_SACD_Vec3 *pos, const SC_SACD_Vec3 *dir, + const SC_SACD_Vec3 *point); + +SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Closest_Point(const SC_SACD_Vec3 *pos, + const SC_SACD_Vec3 *dir, + const SC_SACD_Vec3 *point); + #ifdef __cplusplus } #endif diff --git a/src/test.cpp b/src/test.cpp index ea09c49..1c191c6 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -131,6 +131,97 @@ int main() { CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); } + // Test Sphere/Sphere collision check. + { + SC_SACD_Sphere a{0.0F, 0.0F, 0.0F, 1.0F}; + SC_SACD_Sphere b{0.0F, 0.0F, 0.0F, 1.0F}; + CHECK_TRUE(SC_SACD_Sphere_Collision(&a, &b)); + + a.x = 10.0F; + a.y = 10.0F; + a.z = 10.0F; + b.x = 10.0F; + b.y = 10.5F; + b.z = 10.0F; + CHECK_TRUE(SC_SACD_Sphere_Collision(&a, &b)); + b.y = 12.0F; + b.z = 12.0F; + CHECK_FALSE(SC_SACD_Sphere_Collision(&a, &b)); + b.y = 11.0F; + b.z = 11.0F; + CHECK_TRUE(SC_SACD_Sphere_Collision(&a, &b)); + } + + // Test Sphere/AABB collision check. + { + SC_SACD_Sphere sphere{0.0F, 0.0F, 0.0F, 1.0F}; + SC_SACD_AABB_Box box{0.0F, 0.0F, 0.0F, 2.0F, 2.0F, 2.0F}; + + CHECK_TRUE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.x = 2.1F; + CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.x = -2.1F; + CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.x = 0.0F; + sphere.y = 2.1F; + CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.y = -2.1F; + CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.y = 0.0F; + sphere.z = 2.1F; + CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.z = -2.1F; + CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.z = 0.0F; + sphere.x = 1.0F; + sphere.y = 1.0F; + CHECK_TRUE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.x = -1.0F; + sphere.y = -1.0F; + CHECK_TRUE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.x = 2.0F; + sphere.y = 2.0F; + CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.x = -2.0F; + sphere.y = -2.0F; + CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.x = 1.0F; + sphere.y = 0.0F; + sphere.z = 1.0F; + CHECK_TRUE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.x = -1.0F; + sphere.z = -1.0F; + CHECK_TRUE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.x = 2.0F; + sphere.z = 2.0F; + CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.x = -2.0F; + sphere.z = -2.0F; + CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.x = 1.0F; + sphere.z = 1.5F; + CHECK_TRUE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + + sphere.x = 1.0F; + sphere.z = 1.8F; + CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); + } + std::cout << "Checks checked: " << checks_checked << '\n' << "Checks passed: " << checks_passed << '\n'; From 39593ad99689bb4864382cc05de29887b9c8c4d0 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Fri, 26 Apr 2024 19:48:43 +0900 Subject: [PATCH 02/15] Fix Sphere/AABB collision --- src/sc_sacd.cpp | 132 +++++++----------------------------------------- src/test.cpp | 2 +- 2 files changed, 19 insertions(+), 115 deletions(-) diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index a5ab6b1..93cb9f2 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -207,124 +207,28 @@ int SC_SACD_Sphere_Collision(const SC_SACD_Sphere *a, const SC_SACD_Sphere *b) { int SC_SACD_Sphere_AABB_Box_Collision(const SC_SACD_Sphere *sphere, const SC_SACD_AABB_Box *box) { - std::vector dirs{// yz-plane - {0.0F, INV_SQRT2, INV_SQRT2}, - // xz-plane - {INV_SQRT2, 0.0F, INV_SQRT2}, - // xy-plane - {INV_SQRT2, INV_SQRT2, 0.0F}}; - SC_SACD_Vec3 pos{box->x, box->y, box->z}; - SC_SACD_Vec3 sphere_pos{sphere->x, sphere->y, sphere->z}; + SC_SACD_Vec3 box_min{ + box->x - box->width / 2.0F, + box->y - box->height / 2.0F, + box->z - box->depth / 2.0F, + }; + SC_SACD_Vec3 box_max{ + box->x + box->width / 2.0F, + box->y + box->height / 2.0F, + box->z + box->depth / 2.0F, + }; - for (unsigned int i = 0; i < 3; ++i) { - SC_SACD_Vec3 side_pos = pos; + SC_SACD_Vec3 clamped{ + std::max(box_min.x, std::min(sphere->x, box_max.x)), + std::max(box_min.y, std::min(sphere->y, box_max.y)), + std::max(box_min.z, std::min(sphere->z, box_max.z)) + }; - // Side 1 of 2. + SC_SACD_Vec3 diff = clamped - SC_SACD_Vec3{sphere->x, sphere->y, sphere->z}; - // Get point on side. - switch (i) { - case 0: // yz-plane - side_pos.x += box->width / 2.0F; - break; - case 1: // xz-plane - side_pos.y += box->height / 2.0F; - break; - case 2: // xy-plane - side_pos.z += box->depth / 2.0F; - break; - } + float dist = std::sqrt(SC_SACD_Dot_Product(diff, diff)); - // Calculate closest point to "side". - SC_SACD_Vec3 closest_point = - SC_SACD_Closest_Point_Dir_Normalized(&side_pos, &dirs[i], &sphere_pos); - // Calculate diff between closest and sphere. - SC_SACD_Vec3 point_diff = closest_point - sphere_pos; - float magnitude = std::sqrt(SC_SACD_Dot_Product(point_diff, point_diff)); - - if (magnitude < sphere->radius) { - // Check if point is on side. - switch (i) { - case 0: // yz-plane - if (closest_point.y > side_pos.y - box->height / 2.0F && - closest_point.y < side_pos.y + box->height / 2.0F && - closest_point.z > side_pos.z - box->depth / 2.0F && - closest_point.z < side_pos.z + box->depth / 2.0F) { - return 1; - } - break; - case 1: // xz-plane - if (closest_point.x > side_pos.x - box->width / 2.0F && - closest_point.x < side_pos.x + box->width / 2.0F && - closest_point.z > side_pos.z - box->depth / 2.0F && - closest_point.z < side_pos.z + box->depth / 2.0F) { - return 1; - } - break; - case 2: // xy-plane - if (closest_point.x > side_pos.x - box->width / 2.0F && - closest_point.x < side_pos.x + box->width / 2.0F && - closest_point.y > side_pos.y - box->height / 2.0F && - closest_point.y < side_pos.y + box->height / 2.0F) { - return 1; - } - break; - } - } - - // Side 2 of 2. - - // Get point on side. - switch (i) { - case 0: // yz-plane - side_pos.x -= box->width / 2.0F; - break; - case 1: // xz-plane - side_pos.y -= box->height / 2.0F; - break; - case 2: // xy-plane - side_pos.z -= box->depth / 2.0F; - break; - } - - // Calculate closest point to "side". - closest_point = - SC_SACD_Closest_Point_Dir_Normalized(&side_pos, &dirs[i], &sphere_pos); - // Calculate diff between closest and sphere. - point_diff = closest_point - sphere_pos; - magnitude = std::sqrt(SC_SACD_Dot_Product(point_diff, point_diff)); - - if (magnitude < sphere->radius) { - // Check if point is on side. - switch (i) { - case 0: // yz-plane - if (closest_point.y > side_pos.y - box->height / 2.0F && - closest_point.y < side_pos.y + box->height / 2.0F && - closest_point.z > side_pos.z - box->depth / 2.0F && - closest_point.z < side_pos.z + box->depth / 2.0F) { - return 1; - } - break; - case 1: // xz-plane - if (closest_point.x > side_pos.x - box->width / 2.0F && - closest_point.x < side_pos.x + box->width / 2.0F && - closest_point.z > side_pos.z - box->depth / 2.0F && - closest_point.z < side_pos.z + box->depth / 2.0F) { - return 1; - } - break; - case 2: // xy-plane - if (closest_point.x > side_pos.x - box->width / 2.0F && - closest_point.x < side_pos.x + box->width / 2.0F && - closest_point.y > side_pos.y - box->height / 2.0F && - closest_point.y < side_pos.y + box->height / 2.0F) { - return 1; - } - break; - } - } - } - - return 0; + return dist < sphere->radius; } int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere, diff --git a/src/test.cpp b/src/test.cpp index 1c191c6..5aaa9b2 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -218,7 +218,7 @@ int main() { CHECK_TRUE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); sphere.x = 1.0F; - sphere.z = 1.8F; + sphere.z = 2.0F; CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); } From a194e71d94f822fd64bddac37f4c99efa6006009 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sat, 27 Apr 2024 17:12:16 +0900 Subject: [PATCH 03/15] Impl Sphere/Generic_Box collision checking --- src/sc_sacd.cpp | 76 ++++++++++++++++++++++++++++++++++++++++--------- src/test.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 14 deletions(-) diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index 93cb9f2..c0695f9 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -43,7 +43,8 @@ std::vector SC_SACD_Get_Box_Normals( normals.back() = SC_SACD_Vec3_Rotate(normals.back(), box->x_radians, box->y_radians, box->z_radians); - // Not normalizing the normals on purpose for optimization. (No unit vectors.) + // Not normalizing the normals on purpose for optimization. It should already + // be normalized as each normal is a rotated unit vector. return normals; } @@ -208,21 +209,19 @@ int SC_SACD_Sphere_Collision(const SC_SACD_Sphere *a, const SC_SACD_Sphere *b) { int SC_SACD_Sphere_AABB_Box_Collision(const SC_SACD_Sphere *sphere, const SC_SACD_AABB_Box *box) { SC_SACD_Vec3 box_min{ - box->x - box->width / 2.0F, - box->y - box->height / 2.0F, - box->z - box->depth / 2.0F, + box->x - box->width / 2.0F, + box->y - box->height / 2.0F, + box->z - box->depth / 2.0F, }; SC_SACD_Vec3 box_max{ - box->x + box->width / 2.0F, - box->y + box->height / 2.0F, - box->z + box->depth / 2.0F, + box->x + box->width / 2.0F, + box->y + box->height / 2.0F, + box->z + box->depth / 2.0F, }; - SC_SACD_Vec3 clamped{ - std::max(box_min.x, std::min(sphere->x, box_max.x)), - std::max(box_min.y, std::min(sphere->y, box_max.y)), - std::max(box_min.z, std::min(sphere->z, box_max.z)) - }; + SC_SACD_Vec3 clamped{std::max(box_min.x, std::min(sphere->x, box_max.x)), + std::max(box_min.y, std::min(sphere->y, box_max.y)), + std::max(box_min.z, std::min(sphere->z, box_max.z))}; SC_SACD_Vec3 diff = clamped - SC_SACD_Vec3{sphere->x, sphere->y, sphere->z}; @@ -233,8 +232,57 @@ int SC_SACD_Sphere_AABB_Box_Collision(const SC_SACD_Sphere *sphere, int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere, const SC_SACD_Generic_Box *box) { - // TODO - return 0; + // Adapted from Generic_Box/Generic_Box collision. + + // First check plane where normal = box_pos - sphere_pos. + + SC_SACD_Vec3 sphere_pos{sphere->x, sphere->y, sphere->z}; + SC_SACD_Vec3 sphere_box_normal = + SC_SACD_Vec3{box->x, box->y, box->z} - sphere_pos; + sphere_box_normal = + sphere_box_normal / + std::sqrt(SC_SACD_Dot_Product(sphere_box_normal, sphere_box_normal)); + + std::vector normals{sphere_box_normal}; + + std::vector box_minmaxes = + SC_SACD_Get_Box_MinMax(box, normals); + + float projected_0 = SC_SACD_Dot_Product( + sphere_box_normal, sphere_pos + sphere_box_normal * sphere->radius); + float projected_1 = SC_SACD_Dot_Product( + sphere_box_normal, sphere_pos - sphere_box_normal * sphere->radius); + if (projected_0 < projected_1) { + if (box_minmaxes[0].max < projected_0 || + box_minmaxes[0].min > projected_1) { + return 0; + } + } else if (box_minmaxes[0].max < projected_1 || + box_minmaxes[0].min > projected_0) { + return 0; + } + + // Next check the planes for the 3 normals of the box. + + normals = SC_SACD_Get_Box_Normals(box); + box_minmaxes = SC_SACD_Get_Box_MinMax(box, normals); + for (unsigned int i = 0; i < normals.size(); ++i) { + projected_0 = SC_SACD_Dot_Product(normals[i], + sphere_pos + normals[i] * sphere->radius); + projected_1 = SC_SACD_Dot_Product(normals[i], + sphere_pos - normals[i] * sphere->radius); + if (projected_0 < projected_1) { + if (box_minmaxes[i].max < projected_0 || + box_minmaxes[i].min > projected_1) { + return 0; + } + } else if (box_minmaxes[i].max < projected_1 || + box_minmaxes[i].min > projected_0) { + return 0; + } + } + + return 1; } float SC_SACD_Dot_Product(const SC_SACD_Vec3 a, const SC_SACD_Vec3 b) { diff --git a/src/test.cpp b/src/test.cpp index 5aaa9b2..f5f9471 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -222,6 +222,76 @@ int main() { CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box)); } + // Test Sphere/Generic_Box collision check. + { + SC_SACD_Sphere sphere{0.0F, 0.0F, 0.0F, 1.0F}; + SC_SACD_Generic_Box box{0.0F, 0.0F, 0.0F, + 2.0F, 2.0F, 2.0F, + 0.0F, 0.0F, std::numbers::pi_v / 4.0F}; + + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = 2.5F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.x = -2.5F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.x = 2.3F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.x = -2.3F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = 0.0F; + sphere.y = 2.5F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.y = -2.5F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.y = 2.3F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.y = -2.3F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.y = 0.0F; + sphere.z = 2.1F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.z = -2.1F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.z = 1.9F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.z = -1.9F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = 1.5F; + sphere.y = 1.5F; + sphere.z = 0.0F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.x = 1.4F; + sphere.y = 1.4F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = 2.2F; + sphere.y = 0.7929F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = 2.1F; + sphere.y = 0.6929F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = -1.5F; + sphere.y = -1.5F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.x = -1.4F; + sphere.y = -1.4F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = -2.2F; + sphere.y = -0.7929F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = -2.1F; + sphere.y = -0.6929F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + } + std::cout << "Checks checked: " << checks_checked << '\n' << "Checks passed: " << checks_passed << '\n'; From 2cffea260472b22e70bad8e9fe6bd344a167ecf1 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sat, 27 Apr 2024 17:16:15 +0900 Subject: [PATCH 04/15] Add more testing to UnitTest --- src/test.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/test.cpp b/src/test.cpp index f5f9471..667341c 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -290,6 +290,72 @@ int main() { sphere.x = -2.1F; sphere.y = -0.6929F; CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + box.x = 10.0F; + box.y = -10.0F; + box.z = 13.0F; + + sphere.y = -10.0F; + sphere.z = 13.0F; + sphere.x = 10.0F + 2.5F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.x = 10.0F + -2.5F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.x = 10.0F + 2.3F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.x = 10.0F + -2.3F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = 10.0F + 0.0F; + sphere.y = -10.0F + 2.5F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.y = -10.0F + -2.5F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.y = -10.0F + 2.3F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.y = -10.0F + -2.3F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.y = -10.0F + 0.0F; + sphere.z = 13.0F + 2.1F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.z = 13.0F + -2.1F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.z = 13.0F + 1.9F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.z = 13.0F + -1.9F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = 10.0F + 1.5F; + sphere.y = -10.0F + 1.5F; + sphere.z = 13.0F + 0.0F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.x = 10.0F + 1.4F; + sphere.y = -10.0F + 1.4F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = 10.0F + 2.2F; + sphere.y = -10.0F + 0.7929F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = 10.0F + 2.1F; + sphere.y = -10.0F + 0.6929F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = 10.0F + -1.5F; + sphere.y = -10.0F + -1.5F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + sphere.x = 10.0F + -1.4F; + sphere.y = -10.0F + -1.4F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = 10.0F + -2.2F; + sphere.y = -10.0F + -0.7929F; + CHECK_FALSE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); + + sphere.x = 10.0F + -2.1F; + sphere.y = -10.0F + -0.6929F; + CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); } std::cout << "Checks checked: " << checks_checked << '\n' From de126aa15028edfdff4e70af5f56d5d8c3d6b5b6 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sat, 27 Apr 2024 19:11:36 +0900 Subject: [PATCH 05/15] Matrix/Vector multiplication and changes Change Mat3 values to column-major (I think?) order. Add Matrix/Matrix multiplication and tweak Matrix/Vector multiplication. Fix Matrix rotation values since Mat3 representation changed. Added more UnitTest tests. --- src/sc_sacd.cpp | 116 ++++++++++++++++++++++++--------- src/sc_sacd.h | 15 ++++- src/test.cpp | 170 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 266 insertions(+), 35 deletions(-) diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index c0695f9..c677511 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -27,6 +27,30 @@ SC_SACD_Vec3 operator/(const SC_SACD_Vec3 &a, float scalar) { return SC_SACD_Vec3{a.x / scalar, a.y / scalar, a.z / scalar}; } +SC_SACD_Mat3 operator*(const SC_SACD_Mat3 &a, const SC_SACD_Mat3 &b) { + SC_SACD_Mat3 mat; + + mat.x0 = b.x0 * a.x0 + b.y0 * a.x1 + b.z0 * a.x2; + mat.y0 = b.x0 * a.y0 + b.y0 * a.y1 + b.z0 * a.y2; + mat.z0 = b.x0 * a.z0 + b.y0 * a.z1 + b.z0 * a.z2; + + mat.x1 = b.x1 * a.x0 + b.y1 * a.x1 + b.z1 * a.x2; + mat.y1 = b.x1 * a.y0 + b.y1 * a.y1 + b.z1 * a.y2; + mat.z1 = b.x1 * a.z0 + b.y1 * a.z1 + b.z1 * a.z2; + + mat.x2 = b.x2 * a.x0 + b.y2 * a.x1 + b.z2 * a.x2; + mat.y2 = b.x2 * a.y0 + b.y2 * a.y1 + b.z2 * a.y2; + mat.z2 = b.x2 * a.z0 + b.y2 * a.z1 + b.z2 * a.z2; + + return mat; +} + +SC_SACD_Vec3 operator*(const SC_SACD_Mat3 &mat, const SC_SACD_Vec3 &vec) { + return SC_SACD_Vec3{vec.x * mat.x0 + vec.y * mat.x1 + vec.z * mat.x2, + vec.x * mat.y0 + vec.y * mat.y1 + vec.z * mat.y2, + vec.x * mat.z0 + vec.y * mat.z1 + vec.z * mat.z2}; +} + std::vector SC_SACD_Get_Box_Normals( const SC_SACD_Generic_Box *box) { std::vector normals; @@ -294,13 +318,17 @@ SC_SACD_Vec3 SC_SACD_Cross_Product(const SC_SACD_Vec3 a, const SC_SACD_Vec3 b) { a.x * b.y - a.y * b.x}; } +SC_SACD_Mat3 SC_SACD_Mat3_Identity(void) { + return SC_SACD_Mat3{1.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 1.0F}; +} + +SC_SACD_Mat3 SC_SACD_Mat3_Mult(const SC_SACD_Mat3 *a, const SC_SACD_Mat3 *b) { + return (*a) * (*b); +} + SC_SACD_Vec3 SC_SACD_Mat3_Vec3_Mult(const SC_SACD_Mat3 *mat, const SC_SACD_Vec3 vec) { - return SC_SACD_Vec3{ - vec.x * mat->x0 + vec.y * mat->y0 + vec.z * mat->z0, - vec.x * mat->x1 + vec.y * mat->y1 + vec.z * mat->z1, - vec.x * mat->x2 + vec.y * mat->y2 + vec.z * mat->z2, - }; + return (*mat) * vec; } SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec, float x_axis, @@ -326,45 +354,69 @@ SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec, float x_axis, SC_SACD_Vec3 result; // About x_axis. - mat.x0 = 1.0F; - mat.y0 = 0.0F; - mat.z0 = 0.0F; - mat.x1 = 0.0F; - mat.y1 = std::cos(x_axis); - mat.z1 = -std::sin(x_axis); - mat.x2 = 0.0F; - mat.y2 = -mat.z1; - mat.z2 = mat.y1; + mat = SC_SACD_Rotation_Mat3_XAxis(x_axis); result = SC_SACD_Mat3_Vec3_Mult(&mat, vec); // About y_axis. - mat.x0 = std::cos(y_axis); - mat.y0 = 0.0F; - mat.z0 = std::sin(y_axis); - mat.x1 = 0.0F; - mat.y1 = 1.0F; - mat.z1 = 0.0F; - mat.x2 = -mat.z0; - mat.y2 = 0.0F; - mat.z2 = mat.x0; + mat = SC_SACD_Rotation_Mat3_YAxis(y_axis); result = SC_SACD_Mat3_Vec3_Mult(&mat, result); // About z_axis. - mat.x0 = std::cos(z_axis); - mat.y0 = -std::sin(z_axis); - mat.z0 = 0.0F; - mat.x1 = -mat.y0; - mat.y1 = mat.x0; - mat.z1 = 0.0F; - mat.x2 = 0.0F; - mat.y2 = 0.0F; - mat.z2 = 1.0F; + mat = SC_SACD_Rotation_Mat3_ZAxis(z_axis); return SC_SACD_Mat3_Vec3_Mult(&mat, result); } +SC_SACD_Mat3 SC_SACD_Rotation_Mat3_XAxis(float x_radians) { + SC_SACD_Mat3 mat; + + mat.x0 = 1.0F; + mat.x1 = 0.0F; + mat.x2 = 0.0F; + mat.y0 = 0.0F; + mat.y1 = std::cos(x_radians); + mat.y2 = -std::sin(x_radians); + mat.z0 = 0.0F; + mat.z1 = -mat.y2; + mat.z2 = mat.y1; + + return mat; +} + +SC_SACD_Mat3 SC_SACD_Rotation_Mat3_YAxis(float y_radians) { + SC_SACD_Mat3 mat; + + mat.x0 = std::cos(y_radians); + mat.x1 = 0.0F; + mat.x2 = std::sin(y_radians); + mat.y0 = 0.0F; + mat.y1 = 1.0F; + mat.y2 = 0.0F; + mat.z0 = -mat.x2; + mat.z1 = 0.0F; + mat.z2 = mat.x0; + + return mat; +} + +SC_SACD_Mat3 SC_SACD_Rotation_Mat3_ZAxis(float z_radians) { + SC_SACD_Mat3 mat; + + mat.x0 = std::cos(z_radians); + mat.x1 = -std::sin(z_radians); + mat.x2 = 0.0F; + mat.y0 = -mat.x1; + mat.y1 = mat.x0; + mat.y2 = 0.0F; + mat.z0 = 0.0F; + mat.z1 = 0.0F; + mat.z2 = 1.0F; + + return mat; +} + SC_SACD_Vec3 SC_SACD_Closest_Point_Dir_Normalized(const SC_SACD_Vec3 *pos, const SC_SACD_Vec3 *dir, const SC_SACD_Vec3 *point) { diff --git a/src/sc_sacd.h b/src/sc_sacd.h index 38e1f0a..dc45db4 100644 --- a/src/sc_sacd.h +++ b/src/sc_sacd.h @@ -25,9 +25,9 @@ typedef struct SC_SACD_EXPORT SC_SACD_Vec3 { } SC_SACD_Vec3; typedef struct SC_SACD_EXPORT SC_SACD_Mat3 { - float x0, y0, z0; - float x1, y1, z1; - float x2, y2, z2; + float x0, x1, x2; + float y0, y1, y2; + float z0, z1, z2; } SC_SACD_Mat3; typedef struct SC_SACD_EXPORT SC_SACD_AABB_Box { @@ -94,6 +94,11 @@ SC_SACD_EXPORT float SC_SACD_Dot_Product(const SC_SACD_Vec3 a, SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Cross_Product(const SC_SACD_Vec3 a, const SC_SACD_Vec3 b); +SC_SACD_EXPORT SC_SACD_Mat3 SC_SACD_Mat3_Identity(void); + +SC_SACD_EXPORT SC_SACD_Mat3 SC_SACD_Mat3_Mult(const SC_SACD_Mat3 *a, + const SC_SACD_Mat3 *b); + SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Mat3_Vec3_Mult(const SC_SACD_Mat3 *mat, const SC_SACD_Vec3 vec); @@ -101,6 +106,10 @@ SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec, float x_axis, float y_axis, float z_axis); +SC_SACD_EXPORT SC_SACD_Mat3 SC_SACD_Rotation_Mat3_XAxis(float x_radians); +SC_SACD_EXPORT SC_SACD_Mat3 SC_SACD_Rotation_Mat3_YAxis(float y_radians); +SC_SACD_EXPORT SC_SACD_Mat3 SC_SACD_Rotation_Mat3_ZAxis(float z_radians); + SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Closest_Point_Dir_Normalized( const SC_SACD_Vec3 *pos, const SC_SACD_Vec3 *dir, const SC_SACD_Vec3 *point); diff --git a/src/test.cpp b/src/test.cpp index 667341c..a1f3c9f 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -1,3 +1,4 @@ +#include #include #include @@ -25,6 +26,16 @@ static int checks_passed = 0; } \ } while (false); +#define CHECK_FLOAT(var, value) \ + do { \ + ++checks_checked; \ + if ((var) > (value)-0.0001F && (var) < (value) + 0.0001F) { \ + ++checks_passed; \ + } else { \ + std::cout << "CHECK_FLOAT at line " << __LINE__ << " failed!\n"; \ + } \ + } while (false); + #include "sc_sacd.h" int main() { @@ -358,6 +369,165 @@ int main() { CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); } + // Test matrix/vector multiplication. + { + SC_SACD_Mat3 mat_a{1.0F, 2.0F, 3.0F, 4.0F, 5.0F, 6.0F, 7.0F, 8.0F, 9.0F}; + + SC_SACD_Mat3 mat_b{1.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 1.0F}; + + { + auto result = SC_SACD_Mat3_Mult(&mat_a, &mat_b); + CHECK_TRUE(mat_a.x0 == result.x0); + CHECK_TRUE(mat_a.x1 == result.x1); + CHECK_TRUE(mat_a.x2 == result.x2); + CHECK_TRUE(mat_a.y0 == result.y0); + CHECK_TRUE(mat_a.y1 == result.y1); + CHECK_TRUE(mat_a.y2 == result.y2); + CHECK_TRUE(mat_a.z0 == result.z0); + CHECK_TRUE(mat_a.z1 == result.z1); + CHECK_TRUE(mat_a.z2 == result.z2); + } + + mat_b.x0 = 2.0F; + mat_b.y1 = 0.0F; + mat_b.z2 = 0.0F; + { + auto result = SC_SACD_Mat3_Mult(&mat_a, &mat_b); + CHECK_FLOAT(result.x0, 2.0F); + CHECK_FLOAT(result.y0, 8.0F); + CHECK_FLOAT(result.z0, 14.0F); + CHECK_FLOAT(result.x1, 0.0F); + CHECK_FLOAT(result.y1, 0.0F); + CHECK_FLOAT(result.z1, 0.0F); + CHECK_FLOAT(result.x2, 0.0F); + CHECK_FLOAT(result.y2, 0.0F); + CHECK_FLOAT(result.z2, 0.0F); + } + + mat_b = SC_SACD_Mat3_Identity(); + SC_SACD_Vec3 vec_a{1.0F, 0.0F, 0.0F}; + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_b, vec_a); + CHECK_TRUE(result.x == vec_a.x); + CHECK_TRUE(result.y == vec_a.y); + CHECK_TRUE(result.z == vec_a.z); + } + + // Rotations about each axis. + mat_a = SC_SACD_Rotation_Mat3_ZAxis(std::numbers::pi_v / 2.0F); + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + CHECK_TRUE(result.x < 0.0001F && result.x > -0.0001F); + CHECK_TRUE(result.y < 1.0001F && result.y > 0.9999F); + CHECK_TRUE(result.z < 0.0001F && result.z > -0.0001F); + } + + mat_a = SC_SACD_Rotation_Mat3_ZAxis(std::numbers::pi_v); + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + CHECK_TRUE(result.x < -0.9999F && result.x > -1.0001F); + CHECK_TRUE(result.y < 0.0001F && result.y > -0.0001F); + CHECK_TRUE(result.z < 0.0001F && result.z > -0.0001F); + } + + mat_a = + SC_SACD_Rotation_Mat3_ZAxis(std::numbers::pi_v * 3.0F / 2.0F); + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + CHECK_TRUE(result.x < 0.0001F && result.x > -0.0001F); + CHECK_TRUE(result.y < -0.9999F && result.y > -1.0001F); + CHECK_TRUE(result.z < 0.0001F && result.z > -0.0001F); + } + + mat_a = SC_SACD_Rotation_Mat3_XAxis(std::numbers::pi_v / 2.0F); + vec_a.x = 0.0F; + vec_a.y = 1.0F; + vec_a.z = 0.0F; + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + CHECK_TRUE(result.x < 0.0001F && result.x > -0.0001F); + CHECK_TRUE(result.y < 0.0001F && result.y > -0.0001F); + CHECK_TRUE(result.z < 1.0001F && result.z > 0.9999F); + } + + mat_a = SC_SACD_Rotation_Mat3_XAxis(std::numbers::pi_v); + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + CHECK_TRUE(result.x < 0.0001F && result.x > -0.0001F); + CHECK_TRUE(result.y < -0.9999F && result.y > -1.0001F); + CHECK_TRUE(result.z < 0.0001F && result.z > -0.0001F); + } + + mat_a = + SC_SACD_Rotation_Mat3_XAxis(std::numbers::pi_v * 3.0F / 2.0F); + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + CHECK_TRUE(result.x < 0.0001F && result.x > -0.0001F); + CHECK_TRUE(result.y < 0.0001F && result.y > -0.0001F); + CHECK_TRUE(result.z < -0.9999F && result.z > -1.0001F); + } + + mat_a = SC_SACD_Rotation_Mat3_YAxis(std::numbers::pi_v / 2.0F); + vec_a.x = 0.0F; + vec_a.y = 0.0F; + vec_a.z = 1.0F; + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + CHECK_TRUE(result.x < 1.0001F && result.x > 0.9999F); + CHECK_TRUE(result.y < 0.0001F && result.y > -0.0001F); + CHECK_TRUE(result.z < 0.0001F && result.z > -0.0001F); + } + + mat_a = SC_SACD_Rotation_Mat3_YAxis(std::numbers::pi_v); + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + CHECK_TRUE(result.x < 0.0001F && result.x > -0.0001F); + CHECK_TRUE(result.y < 0.0001F && result.y > -0.0001F); + CHECK_TRUE(result.z < -0.9999F && result.z > -1.0001F); + } + + mat_a = + SC_SACD_Rotation_Mat3_YAxis(std::numbers::pi_v * 3.0F / 2.0F); + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + CHECK_TRUE(result.x < -0.9999F && result.x > -1.0001F); + CHECK_TRUE(result.y < 0.0001F && result.y > -0.0001F); + CHECK_TRUE(result.z < 0.0001F && result.z > -0.0001F); + } + + // Combined axis rotation. + vec_a.x = 1.0F; + vec_a.y = 0.0F; + vec_a.z = 0.0F; + mat_a = SC_SACD_Rotation_Mat3_YAxis(std::numbers::pi_v / 4.0F); + mat_b = SC_SACD_Rotation_Mat3_ZAxis(std::numbers::pi_v / 4.0F); + // Apply mat_a, then mat_b. + mat_a = SC_SACD_Mat3_Mult(&mat_b, &mat_a); + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + CHECK_FLOAT(result.x, 0.5F); + CHECK_FLOAT(result.y, 0.5F); + CHECK_FLOAT(result.z, -std::sqrt(2.0F) / 2.0F); + } + // Apply another rotation on combined mat_a. + mat_b = SC_SACD_Rotation_Mat3_ZAxis(std::numbers::pi_v / 4.0F); + mat_a = SC_SACD_Mat3_Mult(&mat_b, &mat_a); + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + CHECK_FLOAT(result.x, 0.0F); + CHECK_FLOAT(result.y, std::sqrt(2.0F) / 2.0F); + CHECK_FLOAT(result.z, -std::sqrt(2.0F) / 2.0F); + } + // Apply another rotation on combined mat_a. + mat_b = SC_SACD_Rotation_Mat3_XAxis(std::numbers::pi_v / 2.0F); + mat_a = SC_SACD_Mat3_Mult(&mat_b, &mat_a); + { + auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + CHECK_FLOAT(result.x, 0.0F); + CHECK_FLOAT(result.y, std::sqrt(2.0F) / 2.0F); + CHECK_FLOAT(result.z, std::sqrt(2.0F) / 2.0F); + } + } std::cout << "Checks checked: " << checks_checked << '\n' << "Checks passed: " << checks_passed << '\n'; From 551610743c8385f45b7cf138c27e692b8ae6f028 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Sat, 27 Apr 2024 19:18:57 +0900 Subject: [PATCH 06/15] Bump version to 2.0.0 since API changed Mat3 struct changed. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ce00a45..840d6fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(SC_3D_CollisionDetectionHelpers_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/sc_ add_library(SC_3D_CollisionDetectionHelpers ${SC_3D_CollisionDetectionHelpers_SOURCES}) -set_target_properties(SC_3D_CollisionDetectionHelpers PROPERTIES VERSION 1.0.0 SOVERSION 1) +set_target_properties(SC_3D_CollisionDetectionHelpers PROPERTIES VERSION 2.0.0 SOVERSION 2) if(NOT DEFINED CMAKE_BUILD_TYPE OR "${CMAKE_BUILD_TYPE}" STREQUAL "") message("Defaulting to \"Debug\" build type.") From 68fe3bd79acfdd812cecc07a99e62010bce1ea0b Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 29 Apr 2024 13:24:35 +0900 Subject: [PATCH 07/15] Update Changelog.md --- Changelog.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Changelog.md b/Changelog.md index f26d6ed..db75876 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,11 @@ # Changelog +## Version 2.0.0 + +Add collision detection with Spheres. + +Add some more vector/matrix math stuff. + ## Version 1.0.0 First version of this library. From 954c48f6f9b1a10d2081064c186ddcdb9a804271 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 29 Apr 2024 13:39:59 +0900 Subject: [PATCH 08/15] Change Mat3 to Mat4 --- src/sc_sacd.cpp | 104 +++++++++++++++++++++++++++++++++--------------- src/sc_sacd.h | 25 ++++++------ src/test.cpp | 87 +++++++++++++++++++++++----------------- 3 files changed, 136 insertions(+), 80 deletions(-) diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index c677511..d7f905b 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -27,28 +27,37 @@ SC_SACD_Vec3 operator/(const SC_SACD_Vec3 &a, float scalar) { return SC_SACD_Vec3{a.x / scalar, a.y / scalar, a.z / scalar}; } -SC_SACD_Mat3 operator*(const SC_SACD_Mat3 &a, const SC_SACD_Mat3 &b) { - SC_SACD_Mat3 mat; +SC_SACD_Mat4 operator*(const SC_SACD_Mat4 &a, const SC_SACD_Mat4 &b) { + SC_SACD_Mat4 mat; - mat.x0 = b.x0 * a.x0 + b.y0 * a.x1 + b.z0 * a.x2; - mat.y0 = b.x0 * a.y0 + b.y0 * a.y1 + b.z0 * a.y2; - mat.z0 = b.x0 * a.z0 + b.y0 * a.z1 + b.z0 * a.z2; + mat.x0 = b.x0 * a.x0 + b.y0 * a.x1 + b.z0 * a.x2 + b.w0 * a.x3; + mat.y0 = b.x0 * a.y0 + b.y0 * a.y1 + b.z0 * a.y2 + b.w0 * a.y3; + mat.z0 = b.x0 * a.z0 + b.y0 * a.z1 + b.z0 * a.z2 + b.w0 * a.z3; + mat.w0 = b.x0 * a.w0 + b.y0 * a.w1 + b.z0 * a.w2 + b.w0 * a.w3; - mat.x1 = b.x1 * a.x0 + b.y1 * a.x1 + b.z1 * a.x2; - mat.y1 = b.x1 * a.y0 + b.y1 * a.y1 + b.z1 * a.y2; - mat.z1 = b.x1 * a.z0 + b.y1 * a.z1 + b.z1 * a.z2; + mat.x1 = b.x1 * a.x0 + b.y1 * a.x1 + b.z1 * a.x2 + b.w1 * a.x3; + mat.y1 = b.x1 * a.y0 + b.y1 * a.y1 + b.z1 * a.y2 + b.w1 * a.y3; + mat.z1 = b.x1 * a.z0 + b.y1 * a.z1 + b.z1 * a.z2 + b.w1 * a.z3; + mat.w1 = b.x1 * a.w0 + b.y1 * a.w1 + b.z1 * a.w2 + b.w1 * a.w3; - mat.x2 = b.x2 * a.x0 + b.y2 * a.x1 + b.z2 * a.x2; - mat.y2 = b.x2 * a.y0 + b.y2 * a.y1 + b.z2 * a.y2; - mat.z2 = b.x2 * a.z0 + b.y2 * a.z1 + b.z2 * a.z2; + mat.x2 = b.x2 * a.x0 + b.y2 * a.x1 + b.z2 * a.x2 + b.w2 * a.x3; + mat.y2 = b.x2 * a.y0 + b.y2 * a.y1 + b.z2 * a.y2 + b.w2 * a.y3; + mat.z2 = b.x2 * a.z0 + b.y2 * a.z1 + b.z2 * a.z2 + b.w2 * a.z3; + mat.w2 = b.x2 * a.w0 + b.y2 * a.w1 + b.z2 * a.w2 + b.w2 * a.w3; + + mat.x3 = b.x3 * a.x0 + b.y3 * a.x1 + b.z3 * a.x2 + b.w3 * a.x3; + mat.y3 = b.x3 * a.y0 + b.y3 * a.y1 + b.z3 * a.y2 + b.w3 * a.y3; + mat.z3 = b.x3 * a.z0 + b.y3 * a.z1 + b.z3 * a.z2 + b.w3 * a.z3; + mat.w3 = b.x3 * a.w0 + b.y3 * a.w1 + b.z3 * a.w2 + b.w3 * a.w3; return mat; } -SC_SACD_Vec3 operator*(const SC_SACD_Mat3 &mat, const SC_SACD_Vec3 &vec) { - return SC_SACD_Vec3{vec.x * mat.x0 + vec.y * mat.x1 + vec.z * mat.x2, - vec.x * mat.y0 + vec.y * mat.y1 + vec.z * mat.y2, - vec.x * mat.z0 + vec.y * mat.z1 + vec.z * mat.z2}; +SC_SACD_Vec3 operator*(const SC_SACD_Mat4 &mat, const SC_SACD_Vec3 &vec) { + return SC_SACD_Vec3{ + vec.x * mat.x0 + vec.y * mat.x1 + vec.z * mat.x2 + mat.x3, + vec.x * mat.y0 + vec.y * mat.y1 + vec.z * mat.y2 + mat.y3, + vec.x * mat.z0 + vec.y * mat.z1 + vec.z * mat.z2 + mat.z3}; } std::vector SC_SACD_Get_Box_Normals( @@ -318,15 +327,16 @@ SC_SACD_Vec3 SC_SACD_Cross_Product(const SC_SACD_Vec3 a, const SC_SACD_Vec3 b) { a.x * b.y - a.y * b.x}; } -SC_SACD_Mat3 SC_SACD_Mat3_Identity(void) { - return SC_SACD_Mat3{1.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 1.0F}; +SC_SACD_Mat4 SC_SACD_Mat4_Identity(void) { + return SC_SACD_Mat4{1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, + 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F}; } -SC_SACD_Mat3 SC_SACD_Mat3_Mult(const SC_SACD_Mat3 *a, const SC_SACD_Mat3 *b) { +SC_SACD_Mat4 SC_SACD_Mat4_Mult(const SC_SACD_Mat4 *a, const SC_SACD_Mat4 *b) { return (*a) * (*b); } -SC_SACD_Vec3 SC_SACD_Mat3_Vec3_Mult(const SC_SACD_Mat3 *mat, +SC_SACD_Vec3 SC_SACD_Mat4_Vec3_Mult(const SC_SACD_Mat4 *mat, const SC_SACD_Vec3 vec) { return (*mat) * vec; } @@ -350,69 +360,99 @@ SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec, float x_axis, * [ -sin, 0, cos ] */ - SC_SACD_Mat3 mat; + SC_SACD_Mat4 mat; SC_SACD_Vec3 result; // About x_axis. - mat = SC_SACD_Rotation_Mat3_XAxis(x_axis); + mat = SC_SACD_Rotation_Mat4_XAxis(x_axis); - result = SC_SACD_Mat3_Vec3_Mult(&mat, vec); + result = SC_SACD_Mat4_Vec3_Mult(&mat, vec); // About y_axis. - mat = SC_SACD_Rotation_Mat3_YAxis(y_axis); + mat = SC_SACD_Rotation_Mat4_YAxis(y_axis); - result = SC_SACD_Mat3_Vec3_Mult(&mat, result); + result = SC_SACD_Mat4_Vec3_Mult(&mat, result); // About z_axis. - mat = SC_SACD_Rotation_Mat3_ZAxis(z_axis); + mat = SC_SACD_Rotation_Mat4_ZAxis(z_axis); - return SC_SACD_Mat3_Vec3_Mult(&mat, result); + return SC_SACD_Mat4_Vec3_Mult(&mat, result); } -SC_SACD_Mat3 SC_SACD_Rotation_Mat3_XAxis(float x_radians) { - SC_SACD_Mat3 mat; +SC_SACD_Mat4 SC_SACD_Rotation_Mat4_XAxis(float x_radians) { + SC_SACD_Mat4 mat; mat.x0 = 1.0F; mat.x1 = 0.0F; mat.x2 = 0.0F; + mat.x3 = 0.0F; + mat.y0 = 0.0F; mat.y1 = std::cos(x_radians); mat.y2 = -std::sin(x_radians); + mat.y3 = 0.0F; + mat.z0 = 0.0F; mat.z1 = -mat.y2; mat.z2 = mat.y1; + mat.z3 = 0.0F; + + mat.w0 = 0.0F; + mat.w1 = 0.0F; + mat.w2 = 0.0F; + mat.w3 = 1.0F; return mat; } -SC_SACD_Mat3 SC_SACD_Rotation_Mat3_YAxis(float y_radians) { - SC_SACD_Mat3 mat; +SC_SACD_Mat4 SC_SACD_Rotation_Mat4_YAxis(float y_radians) { + SC_SACD_Mat4 mat; mat.x0 = std::cos(y_radians); mat.x1 = 0.0F; mat.x2 = std::sin(y_radians); + mat.x3 = 0.0F; + mat.y0 = 0.0F; mat.y1 = 1.0F; mat.y2 = 0.0F; + mat.y3 = 0.0F; + mat.z0 = -mat.x2; mat.z1 = 0.0F; mat.z2 = mat.x0; + mat.z3 = 0.0F; + + mat.w0 = 0.0F; + mat.w1 = 0.0F; + mat.w2 = 0.0F; + mat.w3 = 1.0F; return mat; } -SC_SACD_Mat3 SC_SACD_Rotation_Mat3_ZAxis(float z_radians) { - SC_SACD_Mat3 mat; +SC_SACD_Mat4 SC_SACD_Rotation_Mat4_ZAxis(float z_radians) { + SC_SACD_Mat4 mat; mat.x0 = std::cos(z_radians); mat.x1 = -std::sin(z_radians); mat.x2 = 0.0F; + mat.x3 = 0.0F; + mat.y0 = -mat.x1; mat.y1 = mat.x0; mat.y2 = 0.0F; + mat.y3 = 0.0F; + mat.z0 = 0.0F; mat.z1 = 0.0F; mat.z2 = 1.0F; + mat.z3 = 0.0F; + + mat.w0 = 0.0F; + mat.w1 = 0.0F; + mat.w2 = 0.0F; + mat.w3 = 1.0F; return mat; } diff --git a/src/sc_sacd.h b/src/sc_sacd.h index dc45db4..59a632e 100644 --- a/src/sc_sacd.h +++ b/src/sc_sacd.h @@ -24,11 +24,12 @@ typedef struct SC_SACD_EXPORT SC_SACD_Vec3 { float x, y, z; } SC_SACD_Vec3; -typedef struct SC_SACD_EXPORT SC_SACD_Mat3 { - float x0, x1, x2; - float y0, y1, y2; - float z0, z1, z2; -} SC_SACD_Mat3; +typedef struct SC_SACD_EXPORT SC_SACD_Mat4 { + float x0, x1, x2, x3; + float y0, y1, y2, y3; + float z0, z1, z2, z3; + float w0, w1, w2, w3; +} SC_SACD_Mat4; typedef struct SC_SACD_EXPORT SC_SACD_AABB_Box { /// Coordinates are to center of box. @@ -94,21 +95,21 @@ SC_SACD_EXPORT float SC_SACD_Dot_Product(const SC_SACD_Vec3 a, SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Cross_Product(const SC_SACD_Vec3 a, const SC_SACD_Vec3 b); -SC_SACD_EXPORT SC_SACD_Mat3 SC_SACD_Mat3_Identity(void); +SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Mat4_Identity(void); -SC_SACD_EXPORT SC_SACD_Mat3 SC_SACD_Mat3_Mult(const SC_SACD_Mat3 *a, - const SC_SACD_Mat3 *b); +SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Mat4_Mult(const SC_SACD_Mat4 *a, + const SC_SACD_Mat4 *b); -SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Mat3_Vec3_Mult(const SC_SACD_Mat3 *mat, +SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Mat4_Vec3_Mult(const SC_SACD_Mat4 *mat, const SC_SACD_Vec3 vec); SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec, float x_axis, float y_axis, float z_axis); -SC_SACD_EXPORT SC_SACD_Mat3 SC_SACD_Rotation_Mat3_XAxis(float x_radians); -SC_SACD_EXPORT SC_SACD_Mat3 SC_SACD_Rotation_Mat3_YAxis(float y_radians); -SC_SACD_EXPORT SC_SACD_Mat3 SC_SACD_Rotation_Mat3_ZAxis(float z_radians); +SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Rotation_Mat4_XAxis(float x_radians); +SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Rotation_Mat4_YAxis(float y_radians); +SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Rotation_Mat4_ZAxis(float z_radians); SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Closest_Point_Dir_Normalized( const SC_SACD_Vec3 *pos, const SC_SACD_Vec3 *dir, diff --git a/src/test.cpp b/src/test.cpp index a1f3c9f..b5e4a60 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -371,125 +371,140 @@ int main() { // Test matrix/vector multiplication. { - SC_SACD_Mat3 mat_a{1.0F, 2.0F, 3.0F, 4.0F, 5.0F, 6.0F, 7.0F, 8.0F, 9.0F}; + SC_SACD_Mat4 mat_a{1.0F, 2.0F, 3.0F, 4.0F, 5.0F, 6.0F, 7.0F, 8.0F, + 9.0F, 10.0F, 11.0F, 12.0F, 13.0F, 14.0F, 15.0F, 16.0F}; - SC_SACD_Mat3 mat_b{1.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.0F, 1.0F}; + SC_SACD_Mat4 mat_b = SC_SACD_Mat4_Identity(); { - auto result = SC_SACD_Mat3_Mult(&mat_a, &mat_b); + auto result = SC_SACD_Mat4_Mult(&mat_a, &mat_b); CHECK_TRUE(mat_a.x0 == result.x0); CHECK_TRUE(mat_a.x1 == result.x1); CHECK_TRUE(mat_a.x2 == result.x2); + CHECK_TRUE(mat_a.x3 == result.x3); CHECK_TRUE(mat_a.y0 == result.y0); CHECK_TRUE(mat_a.y1 == result.y1); CHECK_TRUE(mat_a.y2 == result.y2); + CHECK_TRUE(mat_a.y3 == result.y3); CHECK_TRUE(mat_a.z0 == result.z0); CHECK_TRUE(mat_a.z1 == result.z1); CHECK_TRUE(mat_a.z2 == result.z2); + CHECK_TRUE(mat_a.z3 == result.z3); + CHECK_TRUE(mat_a.w0 == result.w0); + CHECK_TRUE(mat_a.w1 == result.w1); + CHECK_TRUE(mat_a.w2 == result.w2); + CHECK_TRUE(mat_a.w3 == result.w3); } mat_b.x0 = 2.0F; mat_b.y1 = 0.0F; mat_b.z2 = 0.0F; { - auto result = SC_SACD_Mat3_Mult(&mat_a, &mat_b); + auto result = SC_SACD_Mat4_Mult(&mat_a, &mat_b); CHECK_FLOAT(result.x0, 2.0F); - CHECK_FLOAT(result.y0, 8.0F); - CHECK_FLOAT(result.z0, 14.0F); + CHECK_FLOAT(result.y0, 10.0F); + CHECK_FLOAT(result.z0, 18.0F); + CHECK_FLOAT(result.w0, 26.0F); CHECK_FLOAT(result.x1, 0.0F); CHECK_FLOAT(result.y1, 0.0F); CHECK_FLOAT(result.z1, 0.0F); + CHECK_FLOAT(result.w1, 0.0F); CHECK_FLOAT(result.x2, 0.0F); CHECK_FLOAT(result.y2, 0.0F); CHECK_FLOAT(result.z2, 0.0F); + CHECK_FLOAT(result.w2, 0.0F); + CHECK_FLOAT(result.x3, 4.0F); + CHECK_FLOAT(result.y3, 8.0F); + CHECK_FLOAT(result.z3, 12.0F); + CHECK_FLOAT(result.w3, 16.0F); } - mat_b = SC_SACD_Mat3_Identity(); + mat_b = SC_SACD_Mat4_Identity(); SC_SACD_Vec3 vec_a{1.0F, 0.0F, 0.0F}; { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_b, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_b, vec_a); CHECK_TRUE(result.x == vec_a.x); CHECK_TRUE(result.y == vec_a.y); CHECK_TRUE(result.z == vec_a.z); } // Rotations about each axis. - mat_a = SC_SACD_Rotation_Mat3_ZAxis(std::numbers::pi_v / 2.0F); + mat_a = SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v / 2.0F); { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_a, vec_a); CHECK_TRUE(result.x < 0.0001F && result.x > -0.0001F); CHECK_TRUE(result.y < 1.0001F && result.y > 0.9999F); CHECK_TRUE(result.z < 0.0001F && result.z > -0.0001F); } - mat_a = SC_SACD_Rotation_Mat3_ZAxis(std::numbers::pi_v); + mat_a = SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v); { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_a, vec_a); CHECK_TRUE(result.x < -0.9999F && result.x > -1.0001F); CHECK_TRUE(result.y < 0.0001F && result.y > -0.0001F); CHECK_TRUE(result.z < 0.0001F && result.z > -0.0001F); } mat_a = - SC_SACD_Rotation_Mat3_ZAxis(std::numbers::pi_v * 3.0F / 2.0F); + SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v * 3.0F / 2.0F); { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_a, vec_a); CHECK_TRUE(result.x < 0.0001F && result.x > -0.0001F); CHECK_TRUE(result.y < -0.9999F && result.y > -1.0001F); CHECK_TRUE(result.z < 0.0001F && result.z > -0.0001F); } - mat_a = SC_SACD_Rotation_Mat3_XAxis(std::numbers::pi_v / 2.0F); + mat_a = SC_SACD_Rotation_Mat4_XAxis(std::numbers::pi_v / 2.0F); vec_a.x = 0.0F; vec_a.y = 1.0F; vec_a.z = 0.0F; { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_a, vec_a); CHECK_TRUE(result.x < 0.0001F && result.x > -0.0001F); CHECK_TRUE(result.y < 0.0001F && result.y > -0.0001F); CHECK_TRUE(result.z < 1.0001F && result.z > 0.9999F); } - mat_a = SC_SACD_Rotation_Mat3_XAxis(std::numbers::pi_v); + mat_a = SC_SACD_Rotation_Mat4_XAxis(std::numbers::pi_v); { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_a, vec_a); CHECK_TRUE(result.x < 0.0001F && result.x > -0.0001F); CHECK_TRUE(result.y < -0.9999F && result.y > -1.0001F); CHECK_TRUE(result.z < 0.0001F && result.z > -0.0001F); } mat_a = - SC_SACD_Rotation_Mat3_XAxis(std::numbers::pi_v * 3.0F / 2.0F); + SC_SACD_Rotation_Mat4_XAxis(std::numbers::pi_v * 3.0F / 2.0F); { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_a, vec_a); CHECK_TRUE(result.x < 0.0001F && result.x > -0.0001F); CHECK_TRUE(result.y < 0.0001F && result.y > -0.0001F); CHECK_TRUE(result.z < -0.9999F && result.z > -1.0001F); } - mat_a = SC_SACD_Rotation_Mat3_YAxis(std::numbers::pi_v / 2.0F); + mat_a = SC_SACD_Rotation_Mat4_YAxis(std::numbers::pi_v / 2.0F); vec_a.x = 0.0F; vec_a.y = 0.0F; vec_a.z = 1.0F; { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_a, vec_a); CHECK_TRUE(result.x < 1.0001F && result.x > 0.9999F); CHECK_TRUE(result.y < 0.0001F && result.y > -0.0001F); CHECK_TRUE(result.z < 0.0001F && result.z > -0.0001F); } - mat_a = SC_SACD_Rotation_Mat3_YAxis(std::numbers::pi_v); + mat_a = SC_SACD_Rotation_Mat4_YAxis(std::numbers::pi_v); { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_a, vec_a); CHECK_TRUE(result.x < 0.0001F && result.x > -0.0001F); CHECK_TRUE(result.y < 0.0001F && result.y > -0.0001F); CHECK_TRUE(result.z < -0.9999F && result.z > -1.0001F); } mat_a = - SC_SACD_Rotation_Mat3_YAxis(std::numbers::pi_v * 3.0F / 2.0F); + SC_SACD_Rotation_Mat4_YAxis(std::numbers::pi_v * 3.0F / 2.0F); { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_a, vec_a); CHECK_TRUE(result.x < -0.9999F && result.x > -1.0001F); CHECK_TRUE(result.y < 0.0001F && result.y > -0.0001F); CHECK_TRUE(result.z < 0.0001F && result.z > -0.0001F); @@ -499,30 +514,30 @@ int main() { vec_a.x = 1.0F; vec_a.y = 0.0F; vec_a.z = 0.0F; - mat_a = SC_SACD_Rotation_Mat3_YAxis(std::numbers::pi_v / 4.0F); - mat_b = SC_SACD_Rotation_Mat3_ZAxis(std::numbers::pi_v / 4.0F); + mat_a = SC_SACD_Rotation_Mat4_YAxis(std::numbers::pi_v / 4.0F); + mat_b = SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v / 4.0F); // Apply mat_a, then mat_b. - mat_a = SC_SACD_Mat3_Mult(&mat_b, &mat_a); + mat_a = SC_SACD_Mat4_Mult(&mat_b, &mat_a); { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_a, vec_a); CHECK_FLOAT(result.x, 0.5F); CHECK_FLOAT(result.y, 0.5F); CHECK_FLOAT(result.z, -std::sqrt(2.0F) / 2.0F); } // Apply another rotation on combined mat_a. - mat_b = SC_SACD_Rotation_Mat3_ZAxis(std::numbers::pi_v / 4.0F); - mat_a = SC_SACD_Mat3_Mult(&mat_b, &mat_a); + mat_b = SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v / 4.0F); + mat_a = SC_SACD_Mat4_Mult(&mat_b, &mat_a); { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_a, vec_a); CHECK_FLOAT(result.x, 0.0F); CHECK_FLOAT(result.y, std::sqrt(2.0F) / 2.0F); CHECK_FLOAT(result.z, -std::sqrt(2.0F) / 2.0F); } // Apply another rotation on combined mat_a. - mat_b = SC_SACD_Rotation_Mat3_XAxis(std::numbers::pi_v / 2.0F); - mat_a = SC_SACD_Mat3_Mult(&mat_b, &mat_a); + mat_b = SC_SACD_Rotation_Mat4_XAxis(std::numbers::pi_v / 2.0F); + mat_a = SC_SACD_Mat4_Mult(&mat_b, &mat_a); { - auto result = SC_SACD_Mat3_Vec3_Mult(&mat_a, vec_a); + auto result = SC_SACD_Mat4_Vec3_Mult(&mat_a, vec_a); CHECK_FLOAT(result.x, 0.0F); CHECK_FLOAT(result.y, std::sqrt(2.0F) / 2.0F); CHECK_FLOAT(result.z, std::sqrt(2.0F) / 2.0F); From ecf5ce17457aeadc3e07e00078669954fea4ae98 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 29 Apr 2024 14:09:49 +0900 Subject: [PATCH 09/15] Add Mat4 translation function Implemented creating a Mat4 that does translation. --- src/sc_sacd.cpp | 5 +++++ src/sc_sacd.h | 2 ++ src/test.cpp | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+) diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index d7f905b..a7bebfe 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -457,6 +457,11 @@ SC_SACD_Mat4 SC_SACD_Rotation_Mat4_ZAxis(float z_radians) { return mat; } +SC_SACD_Mat4 SC_SACD_Translate_Mat4(float x, float y, float z) { + return SC_SACD_Mat4{0.0F, 0.0F, 0.0F, x, 0.0F, 1.0F, 0.0F, y, + 0.0F, 0.0F, 1.0F, z, 0.0F, 0.0F, 0.0F, 1.0F}; +} + SC_SACD_Vec3 SC_SACD_Closest_Point_Dir_Normalized(const SC_SACD_Vec3 *pos, const SC_SACD_Vec3 *dir, const SC_SACD_Vec3 *point) { diff --git a/src/sc_sacd.h b/src/sc_sacd.h index 59a632e..995894f 100644 --- a/src/sc_sacd.h +++ b/src/sc_sacd.h @@ -111,6 +111,8 @@ SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Rotation_Mat4_XAxis(float x_radians); SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Rotation_Mat4_YAxis(float y_radians); SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Rotation_Mat4_ZAxis(float z_radians); +SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Translate_Mat4(float x, float y, float z); + SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Closest_Point_Dir_Normalized( const SC_SACD_Vec3 *pos, const SC_SACD_Vec3 *dir, const SC_SACD_Vec3 *point); diff --git a/src/test.cpp b/src/test.cpp index b5e4a60..58e9c2d 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -543,6 +543,24 @@ int main() { CHECK_FLOAT(result.z, std::sqrt(2.0F) / 2.0F); } } + + // Mat4 rotation and translation. + { + SC_SACD_Mat4 mat_a = SC_SACD_Translate_Mat4(1.0F, 1.0F, 1.0F); + SC_SACD_Mat4 mat_b = + SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v / 4.0F); + mat_a = SC_SACD_Mat4_Mult(&mat_b, &mat_a); + mat_b = SC_SACD_Translate_Mat4(0.0F, 0.0F, -1.0F); + mat_a = SC_SACD_Mat4_Mult(&mat_b, &mat_a); + + { + auto result = + SC_SACD_Mat4_Vec3_Mult(&mat_a, SC_SACD_Vec3{0.0F, 0.0F, 0.0F}); + CHECK_FLOAT(result.x, 0.0F); + CHECK_FLOAT(result.z, 0.0F); + CHECK_FLOAT(result.y, std::sqrt(2.0F)); + } + } std::cout << "Checks checked: " << checks_checked << '\n' << "Checks passed: " << checks_passed << '\n'; From cca3880bed613854e2187293d52f9baa7536439c Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Tue, 30 Apr 2024 13:40:07 +0900 Subject: [PATCH 10/15] Minor fixes to doc/comments in header --- src/sc_sacd.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sc_sacd.h b/src/sc_sacd.h index 995894f..3ad66b9 100644 --- a/src/sc_sacd.h +++ b/src/sc_sacd.h @@ -80,12 +80,15 @@ SC_SACD_EXPORT int SC_SACD_Generic_Box_Collision(const SC_SACD_Generic_Box *a, SC_SACD_EXPORT int SC_SACD_AABB_Generic_Box_Collision( const SC_SACD_AABB_Box *a, const SC_SACD_Generic_Box *b); +/// Returns non-zero if there is collision. SC_SACD_EXPORT int SC_SACD_Sphere_Collision(const SC_SACD_Sphere *a, const SC_SACD_Sphere *b); +/// Returns non-zero if there is collision. SC_SACD_EXPORT int SC_SACD_Sphere_AABB_Box_Collision( const SC_SACD_Sphere *sphere, const SC_SACD_AABB_Box *box); +/// Returns non-zero if there is collision. SC_SACD_EXPORT int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere, const SC_SACD_Generic_Box *box); From 097661346dcb79a34e5ea8d18dab196a1a5493b3 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Tue, 30 Apr 2024 14:00:32 +0900 Subject: [PATCH 11/15] Replace xyz-axis with Mat4 in GenericBox --- src/sc_sacd.cpp | 128 ++++++++++++++++++++++++++++-------------------- src/sc_sacd.h | 9 ++-- src/test.cpp | 37 ++++++++------ 3 files changed, 102 insertions(+), 72 deletions(-) diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index a7bebfe..765444f 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -65,19 +65,33 @@ std::vector SC_SACD_Get_Box_Normals( std::vector normals; normals.emplace_back(SC_SACD_Vec3{1.0F, 0.0F, 0.0F}); - normals.back() = SC_SACD_Vec3_Rotate(normals.back(), box->x_radians, - box->y_radians, box->z_radians); + normals.back() = box->transform * normals.back(); normals.emplace_back(SC_SACD_Vec3{0.0F, 1.0F, 0.0F}); - normals.back() = SC_SACD_Vec3_Rotate(normals.back(), box->x_radians, - box->y_radians, box->z_radians); + normals.back() = box->transform * normals.back(); normals.emplace_back(SC_SACD_Vec3{0.0F, 0.0F, 1.0F}); - normals.back() = SC_SACD_Vec3_Rotate(normals.back(), box->x_radians, - box->y_radians, box->z_radians); + normals.back() = box->transform * normals.back(); + + return normals; +} + +std::vector SC_SACD_Get_Box_Normals_Normalized( + const SC_SACD_Generic_Box *box) { + std::vector normals; + + normals.emplace_back(SC_SACD_Vec3{1.0F, 0.0F, 0.0F}); + normals.back() = box->transform * normals.back(); + normals.back() = normals.back() / SC_SACD_Vec3_Length(normals.back()); + + normals.emplace_back(SC_SACD_Vec3{0.0F, 1.0F, 0.0F}); + normals.back() = box->transform * normals.back(); + normals.back() = normals.back() / SC_SACD_Vec3_Length(normals.back()); + + normals.emplace_back(SC_SACD_Vec3{0.0F, 0.0F, 1.0F}); + normals.back() = box->transform * normals.back(); + normals.back() = normals.back() / SC_SACD_Vec3_Length(normals.back()); - // Not normalizing the normals on purpose for optimization. It should already - // be normalized as each normal is a rotated unit vector. return normals; } @@ -85,55 +99,61 @@ std::vector SC_SACD_Get_Box_Corners( const SC_SACD_Generic_Box *box) { std::vector corners; - SC_SACD_Vec3 pos{box->x, box->y, box->z}; + corners.push_back(box->transform * SC_SACD_Vec3{-box->width / 2.0F, + -box->height / 2.0F, + -box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{-box->width / 2.0F, -box->height / 2.0F, - -box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{box->width / 2.0F, + -box->height / 2.0F, + -box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{box->width / 2.0F, -box->height / 2.0F, - -box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{-box->width / 2.0F, + box->height / 2.0F, + -box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{-box->width / 2.0F, box->height / 2.0F, - -box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{box->width / 2.0F, + box->height / 2.0F, + -box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{box->width / 2.0F, box->height / 2.0F, - -box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{-box->width / 2.0F, + -box->height / 2.0F, + box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{-box->width / 2.0F, -box->height / 2.0F, - box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{box->width / 2.0F, + -box->height / 2.0F, + box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{box->width / 2.0F, -box->height / 2.0F, - box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{-box->width / 2.0F, + box->height / 2.0F, + box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{-box->width / 2.0F, box->height / 2.0F, - box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); - - corners.push_back( - SC_SACD_Vec3_Rotate(SC_SACD_Vec3{box->width / 2.0F, box->height / 2.0F, - box->depth / 2.0F}, - box->x_radians, box->y_radians, box->z_radians) + - pos); + corners.push_back(box->transform * SC_SACD_Vec3{box->width / 2.0F, + box->height / 2.0F, + box->depth / 2.0F}); + corners.back().x += box->x; + corners.back().y += box->y; + corners.back().z += box->z; return corners; } @@ -226,9 +246,7 @@ int SC_SACD_AABB_Generic_Box_Collision(const SC_SACD_AABB_Box *a, a_conv.width = a->width; a_conv.height = a->height; a_conv.depth = a->depth; - a_conv.x_radians = 0.0F; - a_conv.y_radians = 0.0F; - a_conv.z_radians = 0.0F; + a_conv.transform = SC_SACD_Mat4_Identity(); return SC_SACD_Generic_Box_Collision(&a_conv, b); } @@ -478,3 +496,7 @@ SC_SACD_Vec3 SC_SACD_Closest_Point(const SC_SACD_Vec3 *pos, SC_SACD_Dot_Product(*dir, *dir); return *pos + *dir * alpha; } + +float SC_SACD_Vec3_Length(const SC_SACD_Vec3 vec) { + return std::sqrt(SC_SACD_Dot_Product(vec, vec)); +} diff --git a/src/sc_sacd.h b/src/sc_sacd.h index 3ad66b9..7ba1c7e 100644 --- a/src/sc_sacd.h +++ b/src/sc_sacd.h @@ -55,10 +55,8 @@ typedef struct SC_SACD_EXPORT SC_SACD_Generic_Box { float height; /// z-axis depth. float depth; - /// Rotation about center of box about axis. - float x_radians; - float y_radians; - float z_radians; + /// Local transform; expects center of box as origin. + SC_SACD_Mat4 transform; } SC_SACD_Generic_Box; typedef struct SC_SACD_EXPORT SC_SACD_Sphere { @@ -106,6 +104,7 @@ SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Mat4_Mult(const SC_SACD_Mat4 *a, SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Mat4_Vec3_Mult(const SC_SACD_Mat4 *mat, const SC_SACD_Vec3 vec); +/// Rotates by x-axis first, then y-axis, then finally z-axis. SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec, float x_axis, float y_axis, float z_axis); @@ -124,6 +123,8 @@ SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Closest_Point(const SC_SACD_Vec3 *pos, const SC_SACD_Vec3 *dir, const SC_SACD_Vec3 *point); +SC_SACD_EXPORT float SC_SACD_Vec3_Length(const SC_SACD_Vec3 vec); + #ifdef __cplusplus } #endif diff --git a/src/test.cpp b/src/test.cpp index 58e9c2d..b9b32c0 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -96,8 +96,10 @@ int main() { // Test Separating_Axis_Collision check. { - SC_SACD_Generic_Box a{0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F, 0.0F, 0.0F, 0.0F}; - SC_SACD_Generic_Box b{0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F, 0.0F, 0.0F, 0.0F}; + SC_SACD_Generic_Box a{ + 0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F, SC_SACD_Mat4_Identity()}; + SC_SACD_Generic_Box b{ + 0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F, SC_SACD_Mat4_Identity()}; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); @@ -106,37 +108,37 @@ int main() { b.x = -1.1F; CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); - a.z_radians = std::numbers::pi_v / 4.0F; - b.z_radians = a.z_radians; + a.transform = SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v / 4.0F); + b.transform = a.transform; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); b.x = 1.1F; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); b.x = 0.0F; b.y = 1.1F; - a.z_radians = 0.0F; - b.z_radians = 0.0F; + a.transform = SC_SACD_Mat4_Identity(); + b.transform = a.transform; CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); b.y = -1.1F; CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); - a.z_radians = std::numbers::pi_v / 4.0F; - b.z_radians = a.z_radians; + a.transform = SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v / 4.0F); + b.transform = a.transform; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); b.y = 1.1F; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); b.y = 0.0F; - a.z_radians = 0.0F; - b.z_radians = 0.0F; + a.transform = SC_SACD_Mat4_Identity(); + b.transform = a.transform; b.z = 1.1F; CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); b.z = -1.1F; CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); - a.y_radians = std::numbers::pi_v / 4.0F; - b.y_radians = a.y_radians; + a.transform = SC_SACD_Rotation_Mat4_YAxis(std::numbers::pi_v / 4.0F); + b.transform = a.transform; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); b.z = 1.1F; CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); @@ -236,9 +238,14 @@ int main() { // Test Sphere/Generic_Box collision check. { SC_SACD_Sphere sphere{0.0F, 0.0F, 0.0F, 1.0F}; - SC_SACD_Generic_Box box{0.0F, 0.0F, 0.0F, - 2.0F, 2.0F, 2.0F, - 0.0F, 0.0F, std::numbers::pi_v / 4.0F}; + SC_SACD_Generic_Box box{ + 0.0F, + 0.0F, + 0.0F, + 2.0F, + 2.0F, + 2.0F, + SC_SACD_Rotation_Mat4_ZAxis(std::numbers::pi_v / 4.0F)}; CHECK_TRUE(SC_SACD_Sphere_Box_Collision(&sphere, &box)); From 2f26496155d93b4818f6610b9fc7ced30cdfb970 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Tue, 30 Apr 2024 14:01:21 +0900 Subject: [PATCH 12/15] Make UnitTest return non-zero on any test failure --- src/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test.cpp b/src/test.cpp index b9b32c0..bebaccc 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -571,5 +571,5 @@ int main() { std::cout << "Checks checked: " << checks_checked << '\n' << "Checks passed: " << checks_passed << '\n'; - return 0; + return checks_checked == checks_passed ? 0 : 1; } From ff43e7c4d63325317294b15a0b2af219805665da Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Tue, 30 Apr 2024 14:03:26 +0900 Subject: [PATCH 13/15] Update Changelog.md --- Changelog.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changelog.md b/Changelog.md index db75876..8309ce9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,10 @@ Add collision detection with Spheres. Add some more vector/matrix math stuff. +Replace Mat3 with Mat4. + +Replace xyz-axis rotation floats in GenericBox with Mat4. + ## Version 1.0.0 First version of this library. From 2dcb33f39fef0fafbefc833508dbe11f8530c397 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Wed, 1 May 2024 13:34:40 +0900 Subject: [PATCH 14/15] Add default constructor for SC_SACD_Generic_Box --- src/sc_sacd.cpp | 6 ++++++ src/sc_sacd.h | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index 765444f..2713cdc 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -191,6 +191,12 @@ std::vector SC_SACD_Get_Box_MinMax( // Private Helpers END // ============================================================================= +SC_SACD_Generic_Box SC_SACD_Generic_Box_Default() { + return { + 0.0F, 0.0F, 0.0F, 2.0F, 2.0F, 2.0F, SC_SACD_Mat4_Identity(), + }; +} + int SC_SACD_AABB_Box_Collision(const SC_SACD_AABB_Box *a, const SC_SACD_AABB_Box *b) { float ax_min = a->x - a->width / 2.0F; diff --git a/src/sc_sacd.h b/src/sc_sacd.h index 7ba1c7e..3f9ed07 100644 --- a/src/sc_sacd.h +++ b/src/sc_sacd.h @@ -44,6 +44,7 @@ typedef struct SC_SACD_EXPORT SC_SACD_AABB_Box { float depth; } SC_SACD_AABB_Box; +/// Must not be zero initialized. Use SC_SACD_Generix_Box_Default() instead. typedef struct SC_SACD_EXPORT SC_SACD_Generic_Box { /// Coordinates are to center of box. float x; @@ -66,6 +67,9 @@ typedef struct SC_SACD_EXPORT SC_SACD_Sphere { float radius; } SC_SACD_Sphere; +/// Returns a box at origin with width/height/depth of 2 each. +SC_SACD_EXPORT SC_SACD_Generic_Box SC_SACD_Generic_Box_Default(void); + /// Returns non-zero if there is collision. SC_SACD_EXPORT int SC_SACD_AABB_Box_Collision(const SC_SACD_AABB_Box *a, const SC_SACD_AABB_Box *b); From 3d91dfdff393ecc5282575f38cfab21a89a60e8c Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Wed, 1 May 2024 13:38:45 +0900 Subject: [PATCH 15/15] Add some doc comments to header --- src/sc_sacd.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sc_sacd.h b/src/sc_sacd.h index 3f9ed07..9cb0e21 100644 --- a/src/sc_sacd.h +++ b/src/sc_sacd.h @@ -119,10 +119,12 @@ SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Rotation_Mat4_ZAxis(float z_radians); SC_SACD_EXPORT SC_SACD_Mat4 SC_SACD_Translate_Mat4(float x, float y, float z); +/// This variant of Closest_Point expects "dir" to be a unit vector. SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Closest_Point_Dir_Normalized( const SC_SACD_Vec3 *pos, const SC_SACD_Vec3 *dir, const SC_SACD_Vec3 *point); +/// This variant of Closest_Point expects "dir" to NOT be a unit vector. SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Closest_Point(const SC_SACD_Vec3 *pos, const SC_SACD_Vec3 *dir, const SC_SACD_Vec3 *point);