Fix issue with filters being ignored for two controllers colliding
This commit is contained in:
@@ -173,6 +173,7 @@ CharacterController::CollisionFlags CharacterController::Move(const Vector3& dis
|
||||
filters.mFilterData = (PxFilterData*)&_filterData;
|
||||
filters.mFilterCallback = Physics::GetCharacterQueryFilterCallback();
|
||||
filters.mFilterFlags = PxQueryFlag::eDYNAMIC | PxQueryFlag::eSTATIC | PxQueryFlag::ePREFILTER;
|
||||
filters.mCCTFilterCallback = Physics::GetCharacterControllerFilterCallback();
|
||||
|
||||
result = (CollisionFlags)(byte)_controller->move(C2P(displacement), _minMoveDistance, deltaTime, filters);
|
||||
_lastFlags = result;
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "Actors/PhysicsColliderActor.h"
|
||||
#include <ThirdParty/PhysX/PxScene.h>
|
||||
#include <ThirdParty/PhysX/PxQueryFiltering.h>
|
||||
#include <ThirdParty/PhysX/PxRigidDynamic.h>
|
||||
#include <ThirdParty/PhysX/characterkinematic/PxController.h>
|
||||
|
||||
// Temporary result buffer size
|
||||
#define HIT_BUFFER_SIZE 128
|
||||
@@ -217,6 +219,52 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class CharacterControllerFilter : public PxControllerFilterCallback
|
||||
{
|
||||
private:
|
||||
|
||||
PxShape* getShape(const PxController& controller)
|
||||
{
|
||||
PxRigidDynamic* actor = controller.getActor();
|
||||
|
||||
// Early out if no actor or no shapes
|
||||
if (!actor || actor->getNbShapes() < 1)
|
||||
return nullptr;
|
||||
|
||||
// Get first shape only.
|
||||
PxShape* shape = nullptr;
|
||||
actor->getShapes(&shape, 1);
|
||||
|
||||
return shape;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
bool filter(const PxController& a, const PxController& b) override
|
||||
{
|
||||
// Early out to avoid crashing
|
||||
PxShape* shapeA = getShape(a);
|
||||
if (!shapeA)
|
||||
return false;
|
||||
|
||||
PxShape* shapeB = getShape(b);
|
||||
if (!shapeB)
|
||||
return false;
|
||||
|
||||
// Let triggers through
|
||||
if (PxFilterObjectIsTrigger(shapeB->getFlags()))
|
||||
return false;
|
||||
|
||||
// Trigger the contact callback for pairs (A,B) where the filtermask of A contains the ID of B and vice versa
|
||||
const PxFilterData shapeFilterA = shapeA->getQueryFilterData();
|
||||
const PxFilterData shapeFilterB = shapeB->getQueryFilterData();
|
||||
if (shapeFilterA.word0 & shapeFilterB.word1)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
PxQueryFilterCallback* Physics::GetQueryFilterCallback()
|
||||
{
|
||||
static QueryFilter Filter;
|
||||
@@ -229,6 +277,12 @@ PxQueryFilterCallback* Physics::GetCharacterQueryFilterCallback()
|
||||
return &Filter;
|
||||
}
|
||||
|
||||
PxControllerFilterCallback* Physics::GetCharacterControllerFilterCallback()
|
||||
{
|
||||
static CharacterControllerFilter Filter;
|
||||
return &Filter;
|
||||
}
|
||||
|
||||
bool Physics::RayCast(const Vector3& origin, const Vector3& direction, const float maxDistance, uint32 layerMask, bool hitTriggers)
|
||||
{
|
||||
// Prepare data
|
||||
|
||||
@@ -112,6 +112,11 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(Physics);
|
||||
/// </summary>
|
||||
static PxQueryFilterCallback* GetCharacterQueryFilterCallback();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default controller filter callback used for the character controller collisions detection.
|
||||
/// </summary>
|
||||
static PxControllerFilterCallback* GetCharacterControllerFilterCallback();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default physical material.
|
||||
/// </summary>
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace physx
|
||||
class PxController;
|
||||
class PxCapsuleController;
|
||||
class PxQueryFilterCallback;
|
||||
class PxControllerFilterCallback;
|
||||
class PxHeightField;
|
||||
struct PxFilterData;
|
||||
struct PxRaycastHit;
|
||||
|
||||
Reference in New Issue
Block a user