Impl Sphere/Generic_Box collision checking
This commit is contained in:
parent
c0e3ea82f3
commit
e71fd96e6a
2 changed files with 132 additions and 14 deletions
|
@ -43,7 +43,8 @@ std::vector<SC_SACD_Vec3> 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;
|
||||
}
|
||||
|
||||
|
@ -218,11 +219,9 @@ int SC_SACD_Sphere_AABB_Box_Collision(const SC_SACD_Sphere *sphere,
|
|||
box->z + box->depth / 2.0F,
|
||||
};
|
||||
|
||||
SC_SACD_Vec3 clamped{
|
||||
std::max(box_min.x, std::min(sphere->x, box_max.x)),
|
||||
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))
|
||||
};
|
||||
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,9 +232,58 @@ 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
|
||||
// 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) {
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
|
|
70
src/test.cpp
70
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<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));
|
||||
}
|
||||
|
||||
std::cout << "Checks checked: " << checks_checked << '\n'
|
||||
<< "Checks passed: " << checks_passed << '\n';
|
||||
|
||||
|
|
Loading…
Reference in a new issue