From 9e8c5f0c3987bf4e93eef23db21632802a3f60ca Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Fri, 3 May 2024 17:40:21 +0900 Subject: [PATCH 1/8] ret std::array not std::vector in get-box-normals "Get Box Normals" function always returns three vectors, so use std::array instead of std::vector. Minor changes related to usage of this function. --- src/sc_sacd.cpp | 57 ++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index 337b466..048c27e 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -1,6 +1,7 @@ #include "sc_sacd.h" // Standard library includes. +#include #include #include #include @@ -60,9 +61,8 @@ SC_SACD_Vec3 operator*(const SC_SACD_Mat4 &mat, const SC_SACD_Vec3 &vec) { vec.x * mat.z0 + vec.y * mat.z1 + vec.z * mat.z2 + mat.z3}; } -std::vector SC_SACD_Get_Box_Normals( +std::array SC_SACD_Get_Box_Normals( const SC_SACD_Generic_Box *box) { - std::vector normals; SC_SACD_Vec3 a, b, c; // Facing positive x-axis. @@ -85,7 +85,7 @@ std::vector SC_SACD_Get_Box_Normals( b = b - a; c = c - a; - normals.push_back(SC_SACD_Cross_Product(b, c)); + auto normal_x = SC_SACD_Cross_Product(b, c); // Facing positive y-axis. a.x = 0.0F; @@ -107,7 +107,7 @@ std::vector SC_SACD_Get_Box_Normals( b = b - a; c = c - a; - normals.push_back(SC_SACD_Cross_Product(b, c)); + auto normal_y = SC_SACD_Cross_Product(b, c); // Facing positive z-axis. a.x = 0.0F; @@ -129,14 +129,14 @@ std::vector SC_SACD_Get_Box_Normals( b = b - a; c = c - a; - normals.push_back(SC_SACD_Cross_Product(b, c)); + auto normal_z = SC_SACD_Cross_Product(b, c); - return normals; + return {normal_x, normal_y, normal_z}; } -std::vector SC_SACD_Get_Box_Normals_Normalized( +std::array SC_SACD_Get_Box_Normals_Normalized( const SC_SACD_Generic_Box *box) { - std::vector normals = SC_SACD_Get_Box_Normals(box); + auto normals = SC_SACD_Get_Box_Normals(box); for (auto &normal : normals) { normal = normal / std::sqrt(SC_SACD_Dot_Product(normal, normal)); @@ -213,17 +213,18 @@ struct SC_SACD_MinMax { }; std::vector SC_SACD_Get_Box_MinMax( - const SC_SACD_Generic_Box *box, const std::vector &normals) { + const SC_SACD_Generic_Box *box, const SC_SACD_Vec3 *normals, + std::size_t size) { std::vector minmaxes; std::vector corners = SC_SACD_Get_Box_Corners(box); // Assuming normals are not normalized, and will not normalize anyway. // MinMax count should be same as normals count. - for (const auto &normal : normals) { + for (std::size_t idx = 0; idx < size; ++idx) { SC_SACD_MinMax minmax{INFINITY, -INFINITY}; for (const auto &corner : corners) { - float projected = SC_SACD_Dot_Product(corner, normal); + float projected = SC_SACD_Dot_Product(corner, normals[idx]); if (projected > minmax.max) { minmax.max = projected; } @@ -272,14 +273,21 @@ int SC_SACD_AABB_Box_Collision(const SC_SACD_AABB_Box *a, int SC_SACD_Generic_Box_Collision(const SC_SACD_Generic_Box *a, const SC_SACD_Generic_Box *b) { // Get all normals. - std::vector normals = SC_SACD_Get_Box_Normals(a); - for (const auto &normal : SC_SACD_Get_Box_Normals(b)) { - normals.push_back(normal); + std::vector normals; + { + for (const auto &normal : SC_SACD_Get_Box_Normals(a)) { + normals.push_back(normal); + } + for (const auto &normal : SC_SACD_Get_Box_Normals(b)) { + normals.push_back(normal); + } } // Get all minmaxes. - std::vector minmaxes_a = SC_SACD_Get_Box_MinMax(a, normals); - std::vector minmaxes_b = SC_SACD_Get_Box_MinMax(b, normals); + std::vector minmaxes_a = + SC_SACD_Get_Box_MinMax(a, normals.data(), normals.size()); + std::vector minmaxes_b = + SC_SACD_Get_Box_MinMax(b, normals.data(), normals.size()); // Check minmaxes. for (unsigned int i = 0; i < normals.size(); ++i) { @@ -359,7 +367,7 @@ int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere, std::vector normals{sphere_box_normal}; std::vector box_minmaxes = - SC_SACD_Get_Box_MinMax(box, normals); + SC_SACD_Get_Box_MinMax(box, normals.data(), normals.size()); float projected_0 = SC_SACD_Dot_Product( sphere_box_normal, sphere_pos + sphere_box_normal * sphere->radius); @@ -377,13 +385,14 @@ int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere, // 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); + auto box_normals = SC_SACD_Get_Box_Normals(box); + box_minmaxes = + SC_SACD_Get_Box_MinMax(box, box_normals.data(), box_normals.size()); + for (unsigned int i = 0; i < box_normals.size(); ++i) { + projected_0 = SC_SACD_Dot_Product( + box_normals[i], sphere_pos + box_normals[i] * sphere->radius); + projected_1 = SC_SACD_Dot_Product( + box_normals[i], sphere_pos - box_normals[i] * sphere->radius); if (projected_0 < projected_1) { if (box_minmaxes[i].max < projected_0 || box_minmaxes[i].min > projected_1) { From 763b2d3a6d365c4e1d28592f587f3e747fc6ba40 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Fri, 3 May 2024 17:42:16 +0900 Subject: [PATCH 2/8] Update Changelog.md --- Changelog.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Changelog.md b/Changelog.md index 825366e..9889e3b 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,9 @@ # Changelog +## Upcoming Changes + +Refactoring of internally used function(s). + ## Version 2.0.2 Fix SC_SACD_Translate_Mat4(...). It was missing a "1" in the first element of From 376ad44e67b73b0e8e98257fd61f22bfab4d088f Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Fri, 3 May 2024 17:54:55 +0900 Subject: [PATCH 3/8] Use std::span instead of ptr + size in MinMax fn Note that std::span requires C++20. --- CMakeLists.txt | 1 + src/sc_sacd.cpp | 19 ++++++++----------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c226a8..54c7ff9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,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 2.0.2 SOVERSION 2) +target_compile_features(SC_3D_CollisionDetectionHelpers PUBLIC cxx_std_20) if(NOT DEFINED CMAKE_BUILD_TYPE OR "${CMAKE_BUILD_TYPE}" STREQUAL "") message("Defaulting to \"Debug\" build type.") diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index 048c27e..3e347f6 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -3,6 +3,7 @@ // Standard library includes. #include #include +#include #include #include @@ -213,18 +214,17 @@ struct SC_SACD_MinMax { }; std::vector SC_SACD_Get_Box_MinMax( - const SC_SACD_Generic_Box *box, const SC_SACD_Vec3 *normals, - std::size_t size) { + const SC_SACD_Generic_Box *box, const std::span normals) { std::vector minmaxes; std::vector corners = SC_SACD_Get_Box_Corners(box); // Assuming normals are not normalized, and will not normalize anyway. // MinMax count should be same as normals count. - for (std::size_t idx = 0; idx < size; ++idx) { + for (const auto &normal : normals) { SC_SACD_MinMax minmax{INFINITY, -INFINITY}; for (const auto &corner : corners) { - float projected = SC_SACD_Dot_Product(corner, normals[idx]); + float projected = SC_SACD_Dot_Product(corner, normal); if (projected > minmax.max) { minmax.max = projected; } @@ -284,10 +284,8 @@ int SC_SACD_Generic_Box_Collision(const SC_SACD_Generic_Box *a, } // Get all minmaxes. - std::vector minmaxes_a = - SC_SACD_Get_Box_MinMax(a, normals.data(), normals.size()); - std::vector minmaxes_b = - SC_SACD_Get_Box_MinMax(b, normals.data(), normals.size()); + std::vector minmaxes_a = SC_SACD_Get_Box_MinMax(a, normals); + std::vector minmaxes_b = SC_SACD_Get_Box_MinMax(b, normals); // Check minmaxes. for (unsigned int i = 0; i < normals.size(); ++i) { @@ -367,7 +365,7 @@ int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere, std::vector normals{sphere_box_normal}; std::vector box_minmaxes = - SC_SACD_Get_Box_MinMax(box, normals.data(), normals.size()); + SC_SACD_Get_Box_MinMax(box, normals); float projected_0 = SC_SACD_Dot_Product( sphere_box_normal, sphere_pos + sphere_box_normal * sphere->radius); @@ -386,8 +384,7 @@ int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere, // Next check the planes for the 3 normals of the box. auto box_normals = SC_SACD_Get_Box_Normals(box); - box_minmaxes = - SC_SACD_Get_Box_MinMax(box, box_normals.data(), box_normals.size()); + box_minmaxes = SC_SACD_Get_Box_MinMax(box, box_normals); for (unsigned int i = 0; i < box_normals.size(); ++i) { projected_0 = SC_SACD_Dot_Product( box_normals[i], sphere_pos + box_normals[i] * sphere->radius); From 12aee049c01d333b8bbb4d6a376dc0ba402bf137 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Fri, 3 May 2024 17:55:18 +0900 Subject: [PATCH 4/8] Update Changelog.md --- Changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog.md b/Changelog.md index 9889e3b..9d1df59 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,8 @@ Refactoring of internally used function(s). +This library now requires a compiler that supports C++20. + ## Version 2.0.2 Fix SC_SACD_Translate_Mat4(...). It was missing a "1" in the first element of From 8378707f211ac95b86c01ddbad8607048c99d76e Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Fri, 3 May 2024 18:09:58 +0900 Subject: [PATCH 5/8] Minor refactoring --- src/sc_sacd.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index 3e347f6..7c6244c 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -362,10 +362,8 @@ int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere, 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); + SC_SACD_Get_Box_MinMax(box, {&sphere_box_normal, 1}); float projected_0 = SC_SACD_Dot_Product( sphere_box_normal, sphere_pos + sphere_box_normal * sphere->radius); From a0b41ba2745ac09908cc28c08bba0ae7fb4b7a06 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 6 May 2024 11:23:21 +0900 Subject: [PATCH 6/8] Minor refactoring Instead of passing ptr + size to a span, pass a 1-size array that is automatically coerced into a span (when calling Get_Box_MinMax(...)). --- src/sc_sacd.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index 7c6244c..a67e620 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -350,25 +350,25 @@ int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere, // 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; - if (sphere_box_normal.x < 0.0001F && sphere_box_normal.x > -0.0001F && - sphere_box_normal.y < 0.0001F && sphere_box_normal.y > -0.0001F && - sphere_box_normal.z < 0.0001F && sphere_box_normal.z > -0.0001F) { + std::array sphere_box_normal = { + SC_SACD_Vec3{box->x, box->y, box->z} - sphere_pos}; + if (sphere_box_normal[0].x < 0.0001F && sphere_box_normal[0].x > -0.0001F && + sphere_box_normal[0].y < 0.0001F && sphere_box_normal[0].y > -0.0001F && + sphere_box_normal[0].z < 0.0001F && sphere_box_normal[0].z > -0.0001F) { // Sphere center is box center. return 1; } - sphere_box_normal = - sphere_box_normal / - std::sqrt(SC_SACD_Dot_Product(sphere_box_normal, sphere_box_normal)); + sphere_box_normal[0] = + sphere_box_normal[0] / std::sqrt(SC_SACD_Dot_Product( + sphere_box_normal[0], sphere_box_normal[0])); std::vector box_minmaxes = - SC_SACD_Get_Box_MinMax(box, {&sphere_box_normal, 1}); + SC_SACD_Get_Box_MinMax(box, sphere_box_normal); float projected_0 = SC_SACD_Dot_Product( - sphere_box_normal, sphere_pos + sphere_box_normal * sphere->radius); + sphere_box_normal[0], sphere_pos + sphere_box_normal[0] * sphere->radius); float projected_1 = SC_SACD_Dot_Product( - sphere_box_normal, sphere_pos - sphere_box_normal * sphere->radius); + sphere_box_normal[0], sphere_pos - sphere_box_normal[0] * sphere->radius); if (projected_0 < projected_1) { if (box_minmaxes[0].max < projected_0 || box_minmaxes[0].min > projected_1) { From e0bd54742df6b1108131006e13fda28ca81baa18 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 6 May 2024 11:30:33 +0900 Subject: [PATCH 7/8] Add Scale Mat4 creation function Also added some relevant UnitTests. --- src/sc_sacd.cpp | 5 +++++ src/sc_sacd.h | 2 ++ src/test.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/src/sc_sacd.cpp b/src/sc_sacd.cpp index a67e620..f6f8e94 100644 --- a/src/sc_sacd.cpp +++ b/src/sc_sacd.cpp @@ -546,6 +546,11 @@ SC_SACD_Mat4 SC_SACD_Translate_Mat4(float x, float y, float z) { 0.0F, 0.0F, 1.0F, z, 0.0F, 0.0F, 0.0F, 1.0F}; } +SC_SACD_Mat4 SC_SACD_Scale_Mat4(float x, float y, float z) { + return SC_SACD_Mat4{x, 0.0F, 0.0F, 0.0F, 0.0F, y, 0.0F, 0.0F, + 0.0F, 0.0F, z, 0.0F, 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 9cb0e21..e0bddb5 100644 --- a/src/sc_sacd.h +++ b/src/sc_sacd.h @@ -119,6 +119,8 @@ 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_Mat4 SC_SACD_Scale_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, diff --git a/src/test.cpp b/src/test.cpp index 77acd62..a759639 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -591,6 +591,48 @@ int main() { CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); } + // Box with Scale Mat4. + { + SC_SACD_Generic_Box a = SC_SACD_Generic_Box_Default(); + SC_SACD_Generic_Box b = SC_SACD_Generic_Box_Default(); + + a.x = 1.1F; + b.x = -1.1F; + CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); + + a.transform = SC_SACD_Scale_Mat4(2.0F, 1.0F, 1.0F); + CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); + + a.transform = SC_SACD_Scale_Mat4(-2.0F, 1.0F, 1.0F); + CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); + + a.x = 0.0F; + b.x = 0.0F; + a.y = 1.1F; + b.y = -1.1F; + a.transform = SC_SACD_Mat4_Identity(); + CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); + + a.transform = SC_SACD_Scale_Mat4(1.0F, 2.0F, 1.0F); + CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); + + a.transform = SC_SACD_Scale_Mat4(1.0F, -2.0F, 1.0F); + CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); + + a.y = 0.0F; + b.y = 0.0F; + a.z = 1.1F; + b.z = -1.1F; + a.transform = SC_SACD_Mat4_Identity(); + CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b)); + + a.transform = SC_SACD_Scale_Mat4(1.0F, 1.0F, 2.0F); + CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); + + a.transform = SC_SACD_Scale_Mat4(1.0F, 1.0F, -2.0F); + CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); + } + std::cout << "Checks checked: " << checks_checked << '\n' << "Checks passed: " << checks_passed << '\n'; From 30a24e72a12112da533a75fd157ce9ae8bf52575 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Mon, 6 May 2024 11:31:59 +0900 Subject: [PATCH 8/8] Update Changelog, version to 2.1.0 Version minor bump due to new feature SC_SACD_Scale_Mat4. --- CMakeLists.txt | 2 +- Changelog.md | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 54c7ff9..da2d589 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 2.0.2 SOVERSION 2) +set_target_properties(SC_3D_CollisionDetectionHelpers PROPERTIES VERSION 2.1.0 SOVERSION 2) target_compile_features(SC_3D_CollisionDetectionHelpers PUBLIC cxx_std_20) if(NOT DEFINED CMAKE_BUILD_TYPE OR "${CMAKE_BUILD_TYPE}" STREQUAL "") diff --git a/Changelog.md b/Changelog.md index 9d1df59..4952563 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,11 +1,13 @@ # Changelog -## Upcoming Changes +## Version 2.1.0 Refactoring of internally used function(s). This library now requires a compiler that supports C++20. +Add SC_SACD_Scale_Mat4(...) fn. + ## Version 2.0.2 Fix SC_SACD_Translate_Mat4(...). It was missing a "1" in the first element of