add collisionFilterMask to rayTestBatch and rayTest

This will allow to exclude (filter) certain bodies.
By default, static bodies have collision group 2, and dynamic (mass=1) bodies have collision group 1.
As long as mask & group != 0, a raytest will be performed.
This commit is contained in:
Erwin Coumans
2020-05-08 11:57:25 -07:00
parent 8f380b3fd2
commit f0cccf0faa
5 changed files with 87 additions and 12 deletions

View File

@@ -5934,6 +5934,53 @@ struct CastSyncInfo
};
#endif // __cplusplus >= 201103L
struct FilteredClosestRayResultCallback : public btCollisionWorld::ClosestRayResultCallback
{
FilteredClosestRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, int collisionFilterMask)
: btCollisionWorld::ClosestRayResultCallback(rayFromWorld, rayToWorld),
m_collisionFilterMask(collisionFilterMask)
{
}
int m_collisionFilterMask;
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
{
if (m_collisionFilterMask >= 0)
{
bool collides = (rayResult.m_collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & m_collisionFilterMask) != 0;
if (!collides)
return m_closestHitFraction;
}
return btCollisionWorld::ClosestRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
}
};
struct FilteredAllHitsRayResultCallback: public btCollisionWorld::AllHitsRayResultCallback
{
FilteredAllHitsRayResultCallback(const btVector3& rayFromWorld, const btVector3& rayToWorld, int collisionFilterMask)
: btCollisionWorld::AllHitsRayResultCallback(rayFromWorld, rayToWorld),
m_collisionFilterMask(collisionFilterMask)
{
}
int m_collisionFilterMask;
virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult, bool normalInWorldSpace)
{
if (m_collisionFilterMask >= 0)
{
bool collides = (rayResult.m_collisionObject->getBroadphaseHandle()->m_collisionFilterGroup & m_collisionFilterMask) != 0;
if (!collides)
return m_closestHitFraction;
}
return btCollisionWorld::AllHitsRayResultCallback::addSingleResult(rayResult, normalInWorldSpace);
}
};
struct BatchRayCaster
{
b3ThreadPool* m_threadPool;
@@ -5943,9 +5990,11 @@ struct BatchRayCaster
b3RayHitInfo* m_hitInfoOutputBuffer;
int m_numRays;
int m_reportHitNumber;
int m_collisionFilterMask;
BatchRayCaster(b3ThreadPool* threadPool, const btCollisionWorld* world, const b3RayData* rayInputBuffer, b3RayHitInfo* hitInfoOutputBuffer, int numRays, int reportHitNumber)
: m_threadPool(threadPool), m_world(world), m_rayInputBuffer(rayInputBuffer), m_hitInfoOutputBuffer(hitInfoOutputBuffer), m_numRays(numRays), m_reportHitNumber(reportHitNumber)
BatchRayCaster(b3ThreadPool* threadPool, const btCollisionWorld* world, const b3RayData* rayInputBuffer, b3RayHitInfo* hitInfoOutputBuffer, int numRays, int reportHitNumber, int collisionFilterMask)
: m_threadPool(threadPool), m_world(world), m_rayInputBuffer(rayInputBuffer), m_hitInfoOutputBuffer(hitInfoOutputBuffer), m_numRays(numRays), m_reportHitNumber(reportHitNumber),
m_collisionFilterMask(collisionFilterMask)
{
m_syncInfo = new CastSyncInfo;
}
@@ -6018,12 +6067,12 @@ struct BatchRayCaster
btVector3 rayFromWorld(from[0], from[1], from[2]);
btVector3 rayToWorld(to[0], to[1], to[2]);
btCollisionWorld::ClosestRayResultCallback rayResultCallback(rayFromWorld, rayToWorld);
FilteredClosestRayResultCallback rayResultCallback(rayFromWorld, rayToWorld, m_collisionFilterMask);
rayResultCallback.m_flags |= btTriangleRaycastCallback::kF_UseGjkConvexCastRaytest;
if (m_reportHitNumber >= 0)
{
//compute all hits, and select the m_reportHitNumber, if available
btCollisionWorld::AllHitsRayResultCallback allResultsCallback(rayFromWorld, rayToWorld);
FilteredAllHitsRayResultCallback allResultsCallback(rayFromWorld, rayToWorld, m_collisionFilterMask);
allResultsCallback.m_flags |= btTriangleRaycastCallback::kF_UseGjkConvexCastRaytest;
m_world->rayTest(rayFromWorld, rayToWorld, allResultsCallback);
if (allResultsCallback.m_collisionObjects.size() > m_reportHitNumber)
@@ -6115,6 +6164,7 @@ bool PhysicsServerCommandProcessor::processRequestRaycastIntersectionsCommand(co
const int totalRays = numCommandRays + numStreamingRays;
int numThreads = clientCmd.m_requestRaycastIntersections.m_numThreads;
int reportHitNumber = clientCmd.m_requestRaycastIntersections.m_reportHitNumber;
int collisionFilterMask = clientCmd.m_requestRaycastIntersections.m_collisionFilterMask;
if (numThreads == 0)
{
// When 0 is specified, Bullet can decide how many threads to use.
@@ -6183,7 +6233,7 @@ bool PhysicsServerCommandProcessor::processRequestRaycastIntersectionsCommand(co
}
}
BatchRayCaster batchRayCaster(m_data->m_threadPool, m_data->m_dynamicsWorld, &rays[0], (b3RayHitInfo*)bufferServerToClient, totalRays, reportHitNumber);
BatchRayCaster batchRayCaster(m_data->m_threadPool, m_data->m_dynamicsWorld, &rays[0], (b3RayHitInfo*)bufferServerToClient, totalRays, reportHitNumber, collisionFilterMask);
batchRayCaster.castRays(numThreads);
serverStatusOut.m_numDataStreamBytes = totalRays * sizeof(b3RayData);