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,
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,11 +219,9 @@ int SC_SACD_Sphere_AABB_Box_Collision(const SC_SACD_Sphere *sphere,
|
||||||
box->z + box->depth / 2.0F,
|
box->z + box->depth / 2.0F,
|
||||||
};
|
};
|
||||||
|
|
||||||
SC_SACD_Vec3 clamped{
|
SC_SACD_Vec3 clamped{std::max(box_min.x, std::min(sphere->x, box_max.x)),
|
||||||
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.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};
|
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,
|
int SC_SACD_Sphere_Box_Collision(const SC_SACD_Sphere *sphere,
|
||||||
const SC_SACD_Generic_Box *box) {
|
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;
|
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;
|
||||||
|
|
70
src/test.cpp
70
src/test.cpp
|
@ -222,6 +222,76 @@ int main() {
|
||||||
CHECK_FALSE(SC_SACD_Sphere_AABB_Box_Collision(&sphere, &box));
|
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'
|
std::cout << "Checks checked: " << checks_checked << '\n'
|
||||||
<< "Checks passed: " << checks_passed << '\n';
|
<< "Checks passed: " << checks_passed << '\n';
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue