Compare commits

...

6 commits

Author SHA1 Message Date
c8fdf38438 Bump version to 2.0.0 since API changed
Mat3 struct changed.
2024-04-27 19:18:57 +09:00
281e4cecff 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.
2024-04-27 19:11:36 +09:00
69d398919e Add more testing to UnitTest 2024-04-27 17:16:15 +09:00
e71fd96e6a Impl Sphere/Generic_Box collision checking 2024-04-27 17:12:16 +09:00
c0e3ea82f3 Fix Sphere/AABB collision 2024-04-26 19:48:43 +09:00
cc4e67ace1 Impl Sphere/Sphere and Sphere/AABB collision
TODO: Impl Sphere/Generic-Box collision
2024-04-26 17:36:57 +09:00
4 changed files with 637 additions and 37 deletions

View file

@ -6,7 +6,7 @@ set(SC_3D_CollisionDetectionHelpers_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/src/sc_
add_library(SC_3D_CollisionDetectionHelpers ${SC_3D_CollisionDetectionHelpers_SOURCES}) 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 "") if(NOT DEFINED CMAKE_BUILD_TYPE OR "${CMAKE_BUILD_TYPE}" STREQUAL "")
message("Defaulting to \"Debug\" build type.") message("Defaulting to \"Debug\" build type.")

View file

@ -9,10 +9,48 @@
// Private Helpers BEGIN // Private Helpers BEGIN
// ============================================================================= // =============================================================================
constexpr float INV_SQRT2 = 0.70710678118654752440F;
SC_SACD_Vec3 operator+(const SC_SACD_Vec3 &a, const SC_SACD_Vec3 &b) { 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}; 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};
}
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_Vec3> SC_SACD_Get_Box_Normals( std::vector<SC_SACD_Vec3> SC_SACD_Get_Box_Normals(
const SC_SACD_Generic_Box *box) { const SC_SACD_Generic_Box *box) {
std::vector<SC_SACD_Vec3> normals; std::vector<SC_SACD_Vec3> normals;
@ -29,7 +67,8 @@ std::vector<SC_SACD_Vec3> SC_SACD_Get_Box_Normals(
normals.back() = SC_SACD_Vec3_Rotate(normals.back(), box->x_radians, normals.back() = SC_SACD_Vec3_Rotate(normals.back(), box->x_radians,
box->y_radians, box->z_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; return normals;
} }
@ -184,6 +223,92 @@ int SC_SACD_AABB_Generic_Box_Collision(const SC_SACD_AABB_Box *a,
return SC_SACD_Generic_Box_Collision(&a_conv, b); 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) {
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,
};
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};
float dist = std::sqrt(SC_SACD_Dot_Product(diff, diff));
return dist < sphere->radius;
}
int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere,
const SC_SACD_Generic_Box *box) {
// 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<SC_SACD_Vec3> normals{sphere_box_normal};
std::vector<SC_SACD_MinMax> 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) { 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; return a.x * b.x + a.y * b.y + a.z * b.z;
} }
@ -193,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}; 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, SC_SACD_Vec3 SC_SACD_Mat3_Vec3_Mult(const SC_SACD_Mat3 *mat,
const SC_SACD_Vec3 vec) { const SC_SACD_Vec3 vec) {
return SC_SACD_Vec3{ return (*mat) * vec;
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,
};
} }
SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec, float x_axis, SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec, float x_axis,
@ -225,41 +354,82 @@ SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec, float x_axis,
SC_SACD_Vec3 result; SC_SACD_Vec3 result;
// About x_axis. // About x_axis.
mat.x0 = 1.0F; mat = SC_SACD_Rotation_Mat3_XAxis(x_axis);
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;
result = SC_SACD_Mat3_Vec3_Mult(&mat, vec); result = SC_SACD_Mat3_Vec3_Mult(&mat, vec);
// About y_axis. // About y_axis.
mat.x0 = std::cos(y_axis); mat = SC_SACD_Rotation_Mat3_YAxis(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;
result = SC_SACD_Mat3_Vec3_Mult(&mat, result); result = SC_SACD_Mat3_Vec3_Mult(&mat, result);
// About z_axis. // About z_axis.
mat.x0 = std::cos(z_axis); mat = SC_SACD_Rotation_Mat3_ZAxis(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;
return SC_SACD_Mat3_Vec3_Mult(&mat, result); 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) {
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;
}

View file

@ -25,9 +25,9 @@ typedef struct SC_SACD_EXPORT SC_SACD_Vec3 {
} SC_SACD_Vec3; } SC_SACD_Vec3;
typedef struct SC_SACD_EXPORT SC_SACD_Mat3 { typedef struct SC_SACD_EXPORT SC_SACD_Mat3 {
float x0, y0, z0; float x0, x1, x2;
float x1, y1, z1; float y0, y1, y2;
float x2, y2, z2; float z0, z1, z2;
} SC_SACD_Mat3; } SC_SACD_Mat3;
typedef struct SC_SACD_EXPORT SC_SACD_AABB_Box { typedef struct SC_SACD_EXPORT SC_SACD_AABB_Box {
@ -60,6 +60,13 @@ typedef struct SC_SACD_EXPORT SC_SACD_Generic_Box {
float z_radians; float z_radians;
} SC_SACD_Generic_Box; } 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. /// Returns non-zero if there is collision.
SC_SACD_EXPORT int SC_SACD_AABB_Box_Collision(const SC_SACD_AABB_Box *a, SC_SACD_EXPORT int SC_SACD_AABB_Box_Collision(const SC_SACD_AABB_Box *a,
const SC_SACD_AABB_Box *b); const SC_SACD_AABB_Box *b);
@ -72,12 +79,26 @@ 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( SC_SACD_EXPORT int SC_SACD_AABB_Generic_Box_Collision(
const SC_SACD_AABB_Box *a, const SC_SACD_Generic_Box *b); 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, SC_SACD_EXPORT float SC_SACD_Dot_Product(const SC_SACD_Vec3 a,
const SC_SACD_Vec3 b); const SC_SACD_Vec3 b);
SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Cross_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); 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, SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Mat3_Vec3_Mult(const SC_SACD_Mat3 *mat,
const SC_SACD_Vec3 vec); const SC_SACD_Vec3 vec);
@ -85,6 +106,18 @@ SC_SACD_EXPORT SC_SACD_Vec3 SC_SACD_Vec3_Rotate(const SC_SACD_Vec3 vec,
float x_axis, float y_axis, float x_axis, float y_axis,
float z_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);
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 #ifdef __cplusplus
} }
#endif #endif

View file

@ -1,3 +1,4 @@
#include <cmath>
#include <iostream> #include <iostream>
#include <numbers> #include <numbers>
@ -25,6 +26,16 @@ static int checks_passed = 0;
} \ } \
} while (false); } 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" #include "sc_sacd.h"
int main() { int main() {
@ -131,6 +142,392 @@ int main() {
CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b)); 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 = 2.0F;
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<float> / 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));
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));
}
// 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<float> / 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<float>);
{
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<float> * 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<float> / 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<float>);
{
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<float> * 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<float> / 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<float>);
{
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<float> * 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<float> / 4.0F);
mat_b = SC_SACD_Rotation_Mat3_ZAxis(std::numbers::pi_v<float> / 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<float> / 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<float> / 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' std::cout << "Checks checked: " << checks_checked << '\n'
<< "Checks passed: " << checks_passed << '\n'; << "Checks passed: " << checks_passed << '\n';