engine/engine/src/utils/math/physics/narrowphase/mesh.inl
2026-05-01 11:51:24 -05:00

169 lines
5.5 KiB
C++

namespace {
bool meshAabb( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
ASSERT_COLLIDER_TYPES( MESH, AABB );
const auto& mesh = a;
const auto& aabb = b;
const auto& bvh = *mesh.collider.mesh.bvh;
const auto& meshData = *mesh.collider.mesh.mesh;
// transform to local space for BVH query
auto bounds = ::transformAabbToLocal( aabb.bounds, ::getTransform( mesh ) );
static thread_local uf::stl::vector<pod::BVH::index_t> candidates;
candidates.clear();
::queryBVH( bvh, bounds, candidates );
bool hit = false;
// do collision per triangle
for ( auto triID : candidates ) {
auto tri = ::fetchTriangle( meshData, triID, mesh ); // transform triangle to world space
if ( !::triangleAabb( tri, aabb, manifold, eps ) ) continue;
hit = true;
}
return hit;
}
bool meshSphere( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
ASSERT_COLLIDER_TYPES( MESH, SPHERE );
const auto& mesh = a;
const auto& sphere = b;
const auto& bvh = *mesh.collider.mesh.bvh;
const auto& meshData = *mesh.collider.mesh.mesh;
// transform to local space for BVH query
auto bounds = ::transformAabbToLocal( sphere.bounds, ::getTransform( mesh ) );
static thread_local uf::stl::vector<pod::BVH::index_t> candidates;
candidates.clear();
::queryBVH( bvh, bounds, candidates );
bool hit = false;
// do collision per triangle
for ( auto triID : candidates ) {
auto tri = ::fetchTriangle( meshData, triID, mesh ); // transform triangle to world space
if ( !::triangleSphere( tri, sphere, manifold, eps ) ) continue;
hit = true;
}
return hit;
}
// to-do
bool meshPlane( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
ASSERT_COLLIDER_TYPES( MESH, PLANE );
const auto& mesh = a;
const auto& plane = b;
const auto& bvh = *mesh.collider.mesh.bvh;
const auto& meshData = *mesh.collider.mesh.mesh;
// transform to local space for BVH query
auto bounds = ::transformAabbToLocal( plane.bounds, ::getTransform( mesh ) );
static thread_local uf::stl::vector<pod::BVH::index_t> candidates;
candidates.clear();
::queryBVH( bvh, bounds, candidates );
bool hit = false;
// do collision per triangle
for ( auto triID : candidates ) {
auto tri = ::fetchTriangle( meshData, triID, mesh ); // transform triangle to world space
if ( !::trianglePlane( tri, plane, manifold, eps ) ) continue;
hit = true;
}
return hit;
}
bool meshCapsule( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
ASSERT_COLLIDER_TYPES( MESH, CAPSULE );
const auto& mesh = a;
const auto& capsule = b;
const auto& bvh = *mesh.collider.mesh.bvh;
const auto& meshData = *mesh.collider.mesh.mesh;
// transform to local space for BVH query
auto bounds = ::transformAabbToLocal( capsule.bounds, ::getTransform( mesh ) );
static thread_local uf::stl::vector<pod::BVH::index_t> candidates;
candidates.clear();
::queryBVH( bvh, bounds, candidates );
bool hit = false;
// do collision per triangle
for ( auto triID : candidates ) {
auto tri = ::fetchTriangle( meshData, triID, mesh ); // transform triangle to world space
if ( !::triangleCapsule( tri, capsule, manifold, eps ) ) continue;
hit = true;
}
return hit;
}
bool meshMesh( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
ASSERT_COLLIDER_TYPES( MESH, MESH );
const auto& bvhA = *a.collider.mesh.bvh;
const auto& meshA = *a.collider.mesh.mesh;
const auto& bvhB = *b.collider.mesh.bvh;
const auto& meshB = *b.collider.mesh.mesh;
auto tA = ::getTransform( a );
auto tB = ::getTransform( b );
auto relTransform = uf::transform::relative( tA, tB );
// compute overlaps between one BVH and another BVH
static thread_local pod::BVH::pairs_t pairs;
pairs.clear();
::queryOverlaps( bvhA, bvhB, relTransform, pairs );
bool hit = false;
// do collision per triangle
for (auto [idA, idB] : pairs ) {
auto triA = ::fetchTriangle( meshA, idA, a ); // transform triangles to world space
auto triB = ::fetchTriangle( meshB, idB, b );
bool collides = ::triangleTriangle( triA, triB, manifold, eps );
if ( !collides ) continue;
hit = true;
}
return hit;
}
bool meshHull( const pod::PhysicsBody& a, const pod::PhysicsBody& b, pod::Manifold& manifold, float eps ) {
ASSERT_COLLIDER_TYPES( MESH, CONVEX_HULL );
const auto& mesh = a;
const auto& hull = b;
const auto& bvhA = *a.collider.mesh.bvh;
const auto& meshA = *a.collider.mesh.mesh;
const auto& bvhB = *b.collider.convexHull.bvh;
const auto& meshB = *b.collider.convexHull.mesh;
auto tA = ::getTransform( a );
auto tB = ::getTransform( b );
auto relTransform = uf::transform::relative( tA, tB );
// compute overlaps between one BVH and another BVH
static thread_local pod::BVH::pairs_t pairs;
pairs.clear();
::queryOverlaps( bvhA, bvhB, relTransform, pairs );
bool hit = false;
// do collision per hull and triangle
for (auto [ triID, hullID ] : pairs ) {
auto triView = ::physicsBodyTriView( mesh, triID );
auto hullView = ::physicsBodyHullView( hull, hullID );
bool collides = ::triangleHull( triView, hullView, manifold, eps );
if ( !collides ) continue;
hit = true;
}
return hit;
}
}