Impl Generic_Box_Collision
Also added some helpers for use in Generic_Box_Collision.
This commit is contained in:
parent
9a5634f0da
commit
01c56d8d4c
3 changed files with 229 additions and 40 deletions
|
@ -40,6 +40,7 @@ $<IF:$<CONFIG:Debug>,-Og,-fno-delete-null-pointer-checks -fno-strict-overflow -f
|
||||||
add_executable(UnitTest src/test.cpp)
|
add_executable(UnitTest src/test.cpp)
|
||||||
target_link_libraries(UnitTest SC_SeparatingAxisCollisionDetection)
|
target_link_libraries(UnitTest SC_SeparatingAxisCollisionDetection)
|
||||||
target_include_directories(UnitTest PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
target_include_directories(UnitTest PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||||
|
target_compile_features(UnitTest PUBLIC cxx_std_20)
|
||||||
|
|
||||||
target_compile_options(UnitTest PUBLIC
|
target_compile_options(UnitTest PUBLIC
|
||||||
$<IF:$<CONFIG:Debug>,-Og,-fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -ftrivial-auto-var-init=zero>
|
$<IF:$<CONFIG:Debug>,-Og,-fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -ftrivial-auto-var-init=zero>
|
||||||
|
|
139
src/sd_sacd.cpp
139
src/sd_sacd.cpp
|
@ -2,6 +2,126 @@
|
||||||
|
|
||||||
// Standard library includes.
|
// Standard library includes.
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <stdfloat>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Private Helpers BEGIN
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
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};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SC_SACD_Vec3> SC_SACD_Get_Box_Normals(
|
||||||
|
const SC_SACD_Generic_Box *box) {
|
||||||
|
std::vector<SC_SACD_Vec3> 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.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.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);
|
||||||
|
|
||||||
|
// Not normalizing the normals on purpose for optimization. (No unit vectors.)
|
||||||
|
return normals;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SC_SACD_Vec3> SC_SACD_Get_Box_Corners(
|
||||||
|
const SC_SACD_Generic_Box *box) {
|
||||||
|
std::vector<SC_SACD_Vec3> corners;
|
||||||
|
|
||||||
|
SC_SACD_Vec3 pos{box->x, box->y, 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(
|
||||||
|
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(
|
||||||
|
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(
|
||||||
|
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);
|
||||||
|
|
||||||
|
return corners;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SC_SACD_MinMax {
|
||||||
|
float min, max;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<SC_SACD_MinMax> SC_SACD_Get_Box_MinMax(
|
||||||
|
const SC_SACD_Generic_Box *box, const std::vector<SC_SACD_Vec3> &normals) {
|
||||||
|
std::vector<SC_SACD_MinMax> minmaxes;
|
||||||
|
|
||||||
|
std::vector<SC_SACD_Vec3> 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) {
|
||||||
|
SC_SACD_MinMax minmax{INFINITY, -INFINITY};
|
||||||
|
for (const auto &corner : corners) {
|
||||||
|
float projected = SC_SACD_Dot_Product(corner, normal);
|
||||||
|
if (projected > minmax.max) {
|
||||||
|
minmax.max = projected;
|
||||||
|
}
|
||||||
|
if (projected < minmax.min) {
|
||||||
|
minmax.min = projected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
minmaxes.push_back(minmax);
|
||||||
|
}
|
||||||
|
|
||||||
|
return minmaxes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// Private Helpers END
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
int SC_SACD_AABB_Box_Collision(const SC_SACD_AABB_Box *a,
|
int SC_SACD_AABB_Box_Collision(const SC_SACD_AABB_Box *a,
|
||||||
const SC_SACD_AABB_Box *b) {
|
const SC_SACD_AABB_Box *b) {
|
||||||
|
@ -27,8 +147,25 @@ int SC_SACD_AABB_Box_Collision(const SC_SACD_AABB_Box *a,
|
||||||
|
|
||||||
int SC_SACD_Generic_Box_Collision(const SC_SACD_Generic_Box *a,
|
int SC_SACD_Generic_Box_Collision(const SC_SACD_Generic_Box *a,
|
||||||
const SC_SACD_Generic_Box *b) {
|
const SC_SACD_Generic_Box *b) {
|
||||||
// TODO
|
// Get all normals.
|
||||||
|
std::vector<SC_SACD_Vec3> normals = SC_SACD_Get_Box_Normals(a);
|
||||||
|
for (const auto &normal : SC_SACD_Get_Box_Normals(b)) {
|
||||||
|
normals.push_back(normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all minmaxes.
|
||||||
|
std::vector<SC_SACD_MinMax> minmaxes_a = SC_SACD_Get_Box_MinMax(a, normals);
|
||||||
|
std::vector<SC_SACD_MinMax> minmaxes_b = SC_SACD_Get_Box_MinMax(b, normals);
|
||||||
|
|
||||||
|
// Check minmaxes.
|
||||||
|
for (unsigned int i = 0; i < normals.size(); ++i) {
|
||||||
|
if (minmaxes_a[i].max < minmaxes_b[i].min ||
|
||||||
|
minmaxes_b[i].max < minmaxes_a[i].min) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SC_SACD_AABB_Generic_Box_Collision(const SC_SACD_AABB_Box *a,
|
int SC_SACD_AABB_Generic_Box_Collision(const SC_SACD_AABB_Box *a,
|
||||||
|
|
51
src/test.cpp
51
src/test.cpp
|
@ -1,4 +1,5 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <numbers>
|
||||||
|
|
||||||
static int checks_checked = 0;
|
static int checks_checked = 0;
|
||||||
static int checks_passed = 0;
|
static int checks_passed = 0;
|
||||||
|
@ -28,6 +29,7 @@ static int checks_passed = 0;
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
// Test 2D AABB.
|
// Test 2D AABB.
|
||||||
|
{
|
||||||
SC_SACD_AABB_Box a{0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F};
|
SC_SACD_AABB_Box a{0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F};
|
||||||
SC_SACD_AABB_Box b{2.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F};
|
SC_SACD_AABB_Box b{2.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F};
|
||||||
|
|
||||||
|
@ -79,6 +81,55 @@ int main() {
|
||||||
|
|
||||||
b.y = -2.0F;
|
b.y = -2.0F;
|
||||||
CHECK_FALSE(SC_SACD_AABB_Box_Collision(&a, &b));
|
CHECK_FALSE(SC_SACD_AABB_Box_Collision(&a, &b));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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};
|
||||||
|
|
||||||
|
CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b));
|
||||||
|
|
||||||
|
b.x = 1.1F;
|
||||||
|
CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b));
|
||||||
|
b.x = -1.1F;
|
||||||
|
CHECK_FALSE(SC_SACD_Generic_Box_Collision(&a, &b));
|
||||||
|
|
||||||
|
a.z_radians = std::numbers::pi_v<float> / 4.0F;
|
||||||
|
b.z_radians = a.z_radians;
|
||||||
|
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;
|
||||||
|
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<float> / 4.0F;
|
||||||
|
b.z_radians = a.z_radians;
|
||||||
|
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;
|
||||||
|
|
||||||
|
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<float> / 4.0F;
|
||||||
|
b.y_radians = a.y_radians;
|
||||||
|
CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b));
|
||||||
|
b.z = 1.1F;
|
||||||
|
CHECK_TRUE(SC_SACD_Generic_Box_Collision(&a, &b));
|
||||||
|
}
|
||||||
|
|
||||||
std::cout << "Checks checked: " << checks_checked << '\n'
|
std::cout << "Checks checked: " << checks_checked << '\n'
|
||||||
<< "Checks passed: " << checks_passed << '\n';
|
<< "Checks passed: " << checks_passed << '\n';
|
||||||
|
|
Loading…
Reference in a new issue