Quellcode durchsuchen

Made remaining filter functions objects to provide context (#381)

Fixes #54
Jorrit Rouwe vor 2 Jahren
Ursprung
Commit
4315ad53e3

+ 38 - 22
HelloWorld/HelloWorld.cpp

@@ -73,18 +73,22 @@ namespace Layers
 	static constexpr uint8 NUM_LAYERS = 2;
 };
 
-// Function that determines if two object layers can collide
-static bool MyObjectCanCollide(ObjectLayer inObject1, ObjectLayer inObject2)
+/// Class that determines if two object layers can collide
+class ObjectLayerPairFilterImpl : public ObjectLayerPairFilter
 {
-	switch (inObject1)
+public:
+	virtual bool					ShouldCollide(ObjectLayer inObject1, ObjectLayer inObject2) const override
 	{
-	case Layers::NON_MOVING:
-		return inObject2 == Layers::MOVING; // Non moving only collides with moving
-	case Layers::MOVING:
-		return true; // Moving collides with everything
-	default:
-		JPH_ASSERT(false);
-		return false;
+		switch (inObject1)
+		{
+		case Layers::NON_MOVING:
+			return inObject2 == Layers::MOVING; // Non moving only collides with moving
+		case Layers::MOVING:
+			return true; // Moving collides with everything
+		default:
+			JPH_ASSERT(false);
+			return false;
+		}
 	}
 };
 
@@ -139,20 +143,24 @@ private:
 	BroadPhaseLayer					mObjectToBroadPhase[Layers::NUM_LAYERS];
 };
 
-// Function that determines if two broadphase layers can collide
-static bool MyBroadPhaseCanCollide(ObjectLayer inLayer1, BroadPhaseLayer inLayer2)
+/// Class that determines if an object layer can collide with a broadphase layer
+class ObjectVsBroadPhaseLayerFilterImpl : public ObjectVsBroadPhaseLayerFilter
 {
-	switch (inLayer1)
+public:
+	virtual bool				ShouldCollide(ObjectLayer inLayer1, BroadPhaseLayer inLayer2) const override
 	{
-	case Layers::NON_MOVING:
-		return inLayer2 == BroadPhaseLayers::MOVING;
-	case Layers::MOVING:
-		return true;	
-	default:
-		JPH_ASSERT(false);
-		return false;
+		switch (inLayer1)
+		{
+		case Layers::NON_MOVING:
+			return inLayer2 == BroadPhaseLayers::MOVING;
+		case Layers::MOVING:
+			return true;	
+		default:
+			JPH_ASSERT(false);
+			return false;
+		}
 	}
-}
+};
 
 // An example contact listener
 class MyContactListener : public ContactListener
@@ -248,9 +256,17 @@ int main(int argc, char** argv)
 	// Note: As this is an interface, PhysicsSystem will take a reference to this so this instance needs to stay alive!
 	BPLayerInterfaceImpl broad_phase_layer_interface;
 
+	// Create class that filters object vs broadphase layers
+	// Note: As this is an interface, PhysicsSystem will take a reference to this so this instance needs to stay alive!
+	ObjectVsBroadPhaseLayerFilterImpl object_vs_broadphase_layer_filter;
+
+	// Create class that filters object vs object layers
+	// Note: As this is an interface, PhysicsSystem will take a reference to this so this instance needs to stay alive!
+	ObjectLayerPairFilterImpl object_vs_object_layer_filter;
+
 	// Now we can create the actual physics system.
 	PhysicsSystem physics_system;
-	physics_system.Init(cMaxBodies, cNumBodyMutexes, cMaxBodyPairs, cMaxContactConstraints, broad_phase_layer_interface, MyBroadPhaseCanCollide, MyObjectCanCollide);
+	physics_system.Init(cMaxBodies, cNumBodyMutexes, cMaxBodyPairs, cMaxContactConstraints, broad_phase_layer_interface, object_vs_broadphase_layer_filter, object_vs_object_layer_filter);
 
 	// A body activation listener gets notified when bodies activate and go to sleep
 	// Note that this is called from a job so whatever you do here needs to be thread safe.

+ 1 - 1
Jolt/Physics/Collision/BroadPhase/BroadPhase.h

@@ -89,7 +89,7 @@ public:
 	/// @param inObjectVsBroadPhaseLayerFilter is the filter that determines if an object can collide with a broadphase layer.
 	/// @param inObjectLayerPairFilter is the filter that determines if two objects can collide.
 	/// @param ioPairCollector receives callbacks for every body pair found.
-	virtual void		FindCollidingPairs(BodyID *ioActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, ObjectVsBroadPhaseLayerFilter inObjectVsBroadPhaseLayerFilter, ObjectLayerPairFilter inObjectLayerPairFilter, BodyPairCollector &ioPairCollector) const = 0;
+	virtual void		FindCollidingPairs(BodyID *ioActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, const ObjectVsBroadPhaseLayerFilter &inObjectVsBroadPhaseLayerFilter, const ObjectLayerPairFilter &inObjectLayerPairFilter, BodyPairCollector &ioPairCollector) const = 0;
 
 	/// Same as BroadPhaseQuery::CastAABox but can be implemented in a way to take no broad phase locks.
 	virtual void		CastAABoxNoLock(const AABoxCast &inBox, CastShapeBodyCollector &ioCollector, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter) const = 0; 

+ 2 - 2
Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.cpp

@@ -258,7 +258,7 @@ void BroadPhaseBruteForce::CastAABox(const AABoxCast &inBox, CastShapeBodyCollec
 	CastAABoxNoLock(inBox, ioCollector, inBroadPhaseLayerFilter, inObjectLayerFilter);
 }
 
-void BroadPhaseBruteForce::FindCollidingPairs(BodyID *ioActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, ObjectVsBroadPhaseLayerFilter inObjectVsBroadPhaseLayerFilter, ObjectLayerPairFilter inObjectLayerPairFilter, BodyPairCollector &ioPairCollector) const
+void BroadPhaseBruteForce::FindCollidingPairs(BodyID *ioActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, const ObjectVsBroadPhaseLayerFilter &inObjectVsBroadPhaseLayerFilter, const ObjectLayerPairFilter &inObjectLayerPairFilter, BodyPairCollector &ioPairCollector) const
 {
 	shared_lock lock(mMutex);
 
@@ -285,7 +285,7 @@ void BroadPhaseBruteForce::FindCollidingPairs(BodyID *ioActiveBodies, int inNumA
 
 			// Check if layers can collide
 			const ObjectLayer layer2 = body2.GetObjectLayer();
-			if (!inObjectLayerPairFilter(layer1, layer2))
+			if (!inObjectLayerPairFilter.ShouldCollide(layer1, layer2))
 				continue;
 
 			// Check if bounds overlap

+ 1 - 1
Jolt/Physics/Collision/BroadPhase/BroadPhaseBruteForce.h

@@ -26,7 +26,7 @@ public:
 	virtual void		CollideOrientedBox(const OrientedBox &inBox, CollideShapeBodyCollector &ioCollector, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter) const override;
 	virtual void		CastAABoxNoLock(const AABoxCast &inBox, CastShapeBodyCollector &ioCollector, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter) const override; 
 	virtual void		CastAABox(const AABoxCast &inBox, CastShapeBodyCollector &ioCollector, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter) const override;
-	virtual void		FindCollidingPairs(BodyID *ioActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, ObjectVsBroadPhaseLayerFilter inObjectVsBroadPhaseLayerFilter, ObjectLayerPairFilter inObjectLayerPairFilter, BodyPairCollector &ioPairCollector) const override;
+	virtual void		FindCollidingPairs(BodyID *ioActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, const ObjectVsBroadPhaseLayerFilter &inObjectVsBroadPhaseLayerFilter, const ObjectLayerPairFilter &inObjectLayerPairFilter, BodyPairCollector &ioPairCollector) const override;
 
 private:
 	Array<BodyID>		mBodyIDs;

+ 16 - 5
Jolt/Physics/Collision/BroadPhase/BroadPhaseLayer.h

@@ -69,8 +69,19 @@ public:
 #endif // JPH_EXTERNAL_PROFILE || JPH_PROFILE_ENABLED
 };
 
-/// Function to test if an object can collide with a broadphase layer. Used while finding collision pairs.
-using ObjectVsBroadPhaseLayerFilter = bool (*)(ObjectLayer inLayer1, BroadPhaseLayer inLayer2);
+/// Class to test if an object can collide with a broadphase layer. Used while finding collision pairs.
+class ObjectVsBroadPhaseLayerFilter : public NonCopyable
+{
+public:
+	/// Destructor
+	virtual							~ObjectVsBroadPhaseLayerFilter() = default;
+
+	/// Returns true if an object layer should collide with a broadphase layer
+	virtual bool					ShouldCollide(ObjectLayer inLayer1, BroadPhaseLayer inLayer2) const
+	{
+		return true;
+	}
+};
 
 /// Filter class for broadphase layers
 class BroadPhaseLayerFilter : public NonCopyable
@@ -91,7 +102,7 @@ class DefaultBroadPhaseLayerFilter : public BroadPhaseLayerFilter
 {
 public:
 	/// Constructor
-									DefaultBroadPhaseLayerFilter(ObjectVsBroadPhaseLayerFilter inObjectVsBroadPhaseLayerFilter, ObjectLayer inLayer) :
+									DefaultBroadPhaseLayerFilter(const ObjectVsBroadPhaseLayerFilter &inObjectVsBroadPhaseLayerFilter, ObjectLayer inLayer) :
 		mObjectVsBroadPhaseLayerFilter(inObjectVsBroadPhaseLayerFilter),
 		mLayer(inLayer)
 	{
@@ -100,11 +111,11 @@ public:
 	// See BroadPhaseLayerFilter::ShouldCollide
 	virtual bool					ShouldCollide(BroadPhaseLayer inLayer) const override
 	{
-		return mObjectVsBroadPhaseLayerFilter(mLayer, inLayer);
+		return mObjectVsBroadPhaseLayerFilter.ShouldCollide(mLayer, inLayer);
 	}
 
 private:
-	ObjectVsBroadPhaseLayerFilter	mObjectVsBroadPhaseLayerFilter;
+	const ObjectVsBroadPhaseLayerFilter &mObjectVsBroadPhaseLayerFilter;
 	ObjectLayer						mLayer;
 };
 

+ 2 - 2
Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.cpp

@@ -535,7 +535,7 @@ void BroadPhaseQuadTree::CastAABox(const AABoxCast &inBox, CastShapeBodyCollecto
 	CastAABoxNoLock(inBox, ioCollector, inBroadPhaseLayerFilter, inObjectLayerFilter);
 }
 
-void BroadPhaseQuadTree::FindCollidingPairs(BodyID *ioActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, ObjectVsBroadPhaseLayerFilter inObjectVsBroadPhaseLayerFilter, ObjectLayerPairFilter inObjectLayerPairFilter, BodyPairCollector &ioPairCollector) const 
+void BroadPhaseQuadTree::FindCollidingPairs(BodyID *ioActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, const ObjectVsBroadPhaseLayerFilter &inObjectVsBroadPhaseLayerFilter, const ObjectLayerPairFilter &inObjectLayerPairFilter, BodyPairCollector &ioPairCollector) const 
 { 
 	JPH_PROFILE_FUNCTION();
 
@@ -562,7 +562,7 @@ void BroadPhaseQuadTree::FindCollidingPairs(BodyID *ioActiveBodies, int inNumAct
 		for (BroadPhaseLayer::Type l = 0; l < mNumLayers; ++l)
 		{
 			const QuadTree &tree = mLayers[l];
-			if (tree.HasBodies() && inObjectVsBroadPhaseLayerFilter(object_layer, BroadPhaseLayer(l)))
+			if (tree.HasBodies() && inObjectVsBroadPhaseLayerFilter.ShouldCollide(object_layer, BroadPhaseLayer(l)))
 			{
 				JPH_PROFILE(tree.GetName());
 				tree.FindCollidingPairs(bodies, b_start, int(b_mid - b_start), inSpeculativeContactDistance, ioPairCollector, inObjectLayerPairFilter);

+ 1 - 1
Jolt/Physics/Collision/BroadPhase/BroadPhaseQuadTree.h

@@ -38,7 +38,7 @@ public:
 	virtual void			CollideOrientedBox(const OrientedBox &inBox, CollideShapeBodyCollector &ioCollector, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter) const override;
 	virtual void			CastAABoxNoLock(const AABoxCast &inBox, CastShapeBodyCollector &ioCollector, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter) const override; 
 	virtual void			CastAABox(const AABoxCast &inBox, CastShapeBodyCollector &ioCollector, const BroadPhaseLayerFilter &inBroadPhaseLayerFilter, const ObjectLayerFilter &inObjectLayerFilter) const override;
-	virtual void			FindCollidingPairs(BodyID *ioActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, ObjectVsBroadPhaseLayerFilter inObjectVsBroadPhaseLayerFilter, ObjectLayerPairFilter inObjectLayerPairFilter, BodyPairCollector &ioPairCollector) const override;
+	virtual void			FindCollidingPairs(BodyID *ioActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, const ObjectVsBroadPhaseLayerFilter &inObjectVsBroadPhaseLayerFilter, const ObjectLayerPairFilter &inObjectLayerPairFilter, BodyPairCollector &ioPairCollector) const override;
 #ifdef JPH_TRACK_BROADPHASE_STATS
 	virtual void			ReportStats() override;
 #endif // JPH_TRACK_BROADPHASE_STATS

+ 2 - 2
Jolt/Physics/Collision/BroadPhase/QuadTree.cpp

@@ -1347,7 +1347,7 @@ void QuadTree::CastAABox(const AABoxCast &inBox, CastShapeBodyCollector &ioColle
 	WalkTree(inObjectLayerFilter, inTracking, visitor JPH_IF_TRACK_BROADPHASE_STATS(, mCastAABoxStats));
 }
 
-void QuadTree::FindCollidingPairs(const BodyVector &inBodies, const BodyID *inActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, BodyPairCollector &ioPairCollector, ObjectLayerPairFilter inObjectLayerPairFilter) const
+void QuadTree::FindCollidingPairs(const BodyVector &inBodies, const BodyID *inActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, BodyPairCollector &ioPairCollector, const ObjectLayerPairFilter &inObjectLayerPairFilter) const
 {
 	// Note that we don't lock the tree at this point. We know that the tree is not going to be swapped or deleted while finding collision pairs due to the way the jobs are scheduled in the PhysicsSystem::Update.
 	// We double check this at the end of the function.
@@ -1386,7 +1386,7 @@ void QuadTree::FindCollidingPairs(const BodyVector &inBodies, const BodyID *inAc
 				{			
 					// Collision between dynamic pairs need to be picked up only once
 					const Body &body2 = *inBodies[b2_id.GetIndex()];
-					if (inObjectLayerPairFilter(body1.GetObjectLayer(), body2.GetObjectLayer())
+					if (inObjectLayerPairFilter.ShouldCollide(body1.GetObjectLayer(), body2.GetObjectLayer())
 						&& Body::sFindCollidingPairsCanCollide(body1, body2)
 						&& bounds1.Overlaps(body2.GetWorldSpaceBounds())) // In the broadphase we widen the bounding box when a body moves, do a final check to see if the bounding boxes actually overlap
 					{

+ 1 - 1
Jolt/Physics/Collision/BroadPhase/QuadTree.h

@@ -245,7 +245,7 @@ public:
 	void						CastAABox(const AABoxCast &inBox, CastShapeBodyCollector &ioCollector, const ObjectLayerFilter &inObjectLayerFilter, const TrackingVector &inTracking) const;
 
 	/// Find all colliding pairs between dynamic bodies, calls ioPairCollector for every pair found
-	void						FindCollidingPairs(const BodyVector &inBodies, const BodyID *inActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, BodyPairCollector &ioPairCollector, ObjectLayerPairFilter inObjectLayerPairFilter) const;
+	void						FindCollidingPairs(const BodyVector &inBodies, const BodyID *inActiveBodies, int inNumActiveBodies, float inSpeculativeContactDistance, BodyPairCollector &ioPairCollector, const ObjectLayerPairFilter &inObjectLayerPairFilter) const;
 
 #ifdef JPH_TRACK_BROADPHASE_STATS
 	/// Trace the stats of this tree to the TTY

+ 16 - 5
Jolt/Physics/Collision/ObjectLayer.h

@@ -35,15 +35,26 @@ public:
 #endif // JPH_TRACK_BROADPHASE_STATS
 };
 
-/// Function to test if two objects can collide based on their object layer. Used while finding collision pairs.
-using ObjectLayerPairFilter = bool (*)(ObjectLayer inLayer1, ObjectLayer inLayer2);
+/// Filter class to test if two objects can collide based on their object layer. Used while finding collision pairs.
+class ObjectLayerPairFilter : public NonCopyable
+{
+public:
+	/// Destructor
+	virtual					~ObjectLayerPairFilter() = default;
+
+	/// Returns true if two layers can collide
+	virtual bool			ShouldCollide(ObjectLayer inLayer1, ObjectLayer inLayer2) const
+	{
+		return true;
+	}
+};
 
 /// Default filter class that uses the pair filter in combination with a specified layer to filter layers
 class DefaultObjectLayerFilter : public ObjectLayerFilter
 {
 public:
 	/// Constructor
-							DefaultObjectLayerFilter(ObjectLayerPairFilter inObjectLayerPairFilter, ObjectLayer inLayer) :
+							DefaultObjectLayerFilter(const ObjectLayerPairFilter &inObjectLayerPairFilter, ObjectLayer inLayer) :
 		mObjectLayerPairFilter(inObjectLayerPairFilter),
 		mLayer(inLayer)
 	{
@@ -59,11 +70,11 @@ public:
 	// See ObjectLayerFilter::ShouldCollide
 	virtual bool			ShouldCollide(ObjectLayer inLayer) const override
 	{
-		return mObjectLayerPairFilter(mLayer, inLayer);
+		return mObjectLayerPairFilter.ShouldCollide(mLayer, inLayer);
 	}
 
 private:
-	ObjectLayerPairFilter	mObjectLayerPairFilter;
+	const ObjectLayerPairFilter & mObjectLayerPairFilter;
 	ObjectLayer				mLayer;
 };
 

+ 4 - 4
Jolt/Physics/PhysicsSystem.cpp

@@ -64,10 +64,10 @@ PhysicsSystem::~PhysicsSystem()
 	delete mBroadPhase;
 }
 
-void PhysicsSystem::Init(uint inMaxBodies, uint inNumBodyMutexes, uint inMaxBodyPairs, uint inMaxContactConstraints, const BroadPhaseLayerInterface &inBroadPhaseLayerInterface, ObjectVsBroadPhaseLayerFilter inObjectVsBroadPhaseLayerFilter, ObjectLayerPairFilter inObjectLayerPairFilter)
+void PhysicsSystem::Init(uint inMaxBodies, uint inNumBodyMutexes, uint inMaxBodyPairs, uint inMaxContactConstraints, const BroadPhaseLayerInterface &inBroadPhaseLayerInterface, const ObjectVsBroadPhaseLayerFilter &inObjectVsBroadPhaseLayerFilter, const ObjectLayerPairFilter &inObjectLayerPairFilter)
 { 
-	mObjectVsBroadPhaseLayerFilter = inObjectVsBroadPhaseLayerFilter;
-	mObjectLayerPairFilter = inObjectLayerPairFilter;
+	mObjectVsBroadPhaseLayerFilter = &inObjectVsBroadPhaseLayerFilter;
+	mObjectLayerPairFilter = &inObjectLayerPairFilter;
 
 	// Initialize body manager
 	mBodyManager.Init(inMaxBodies, inNumBodyMutexes, inBroadPhaseLayerInterface); 
@@ -867,7 +867,7 @@ void PhysicsSystem::JobFindCollisions(PhysicsUpdateContext::Step *ioStep, int in
 				memcpy(active_bodies, mBodyManager.GetActiveBodiesUnsafe() + active_bodies_read_idx, batch_size * sizeof(BodyID));
 
 				// Find pairs in the broadphase
-				mBroadPhase->FindCollidingPairs(active_bodies, batch_size, mPhysicsSettings.mSpeculativeContactDistance, mObjectVsBroadPhaseLayerFilter, mObjectLayerPairFilter, add_pair);
+				mBroadPhase->FindCollidingPairs(active_bodies, batch_size, mPhysicsSettings.mSpeculativeContactDistance, *mObjectVsBroadPhaseLayerFilter, *mObjectLayerPairFilter, add_pair);
 
 				// Check if we have enough pairs in the buffer to start a new job
 				const PhysicsUpdateContext::BodyPairQueue &queue = ioStep->mBodyPairQueues[inJobIndex];

+ 10 - 10
Jolt/Physics/PhysicsSystem.h

@@ -34,12 +34,12 @@ public:
 	/// Initialize the system.
 	/// @param inMaxBodies Maximum number of bodies to support.
 	/// @param inNumBodyMutexes Number of body mutexes to use. Should be a power of 2 in the range [1, 64], use 0 to auto detect.
-	/// @param inMaxBodyPairs Maximum amount of body pairs to process (anything else will fall through the world), this number should generally be much higher than the max amount of contact points as there will be lots of bodies close that are not actually touching
-	/// @param inMaxContactConstraints Maximum amount of contact constraints to process (anything else will fall through the world)
-	/// @param inBroadPhaseLayerInterface Information on the mapping of object layers to broad phase layers, note since this is a virtual interface, the instance needs to stay alive during the lifetime of the PhysicsSystem
-	/// @param inObjectVsBroadPhaseLayerFilter Filter callback function that is used to determine if an object layer collides with a broad phase layer.
-	/// @param inObjectLayerPairFilter Filter callback function that is used to determine if two object layers collide.
-	void						Init(uint inMaxBodies, uint inNumBodyMutexes, uint inMaxBodyPairs, uint inMaxContactConstraints, const BroadPhaseLayerInterface &inBroadPhaseLayerInterface, ObjectVsBroadPhaseLayerFilter inObjectVsBroadPhaseLayerFilter, ObjectLayerPairFilter inObjectLayerPairFilter);
+	/// @param inMaxBodyPairs Maximum amount of body pairs to process (anything else will fall through the world), this number should generally be much higher than the max amount of contact points as there will be lots of bodies close that are not actually touching.
+	/// @param inMaxContactConstraints Maximum amount of contact constraints to process (anything else will fall through the world).
+	/// @param inBroadPhaseLayerInterface Information on the mapping of object layers to broad phase layers. Since this is a virtual interface, the instance needs to stay alive during the lifetime of the PhysicsSystem.
+	/// @param inObjectVsBroadPhaseLayerFilter Filter callback function that is used to determine if an object layer collides with a broad phase layer. Since this is a virtual interface, the instance needs to stay alive during the lifetime of the PhysicsSystem.
+	/// @param inObjectLayerPairFilter Filter callback function that is used to determine if two object layers collide. Since this is a virtual interface, the instance needs to stay alive during the lifetime of the PhysicsSystem.
+	void						Init(uint inMaxBodies, uint inNumBodyMutexes, uint inMaxBodyPairs, uint inMaxContactConstraints, const BroadPhaseLayerInterface &inBroadPhaseLayerInterface, const ObjectVsBroadPhaseLayerFilter &inObjectVsBroadPhaseLayerFilter, const ObjectLayerPairFilter &inObjectLayerPairFilter);
 	
 	/// Listener that is notified whenever a body is activated/deactivated
 	void						SetBodyActivationListener(BodyActivationListener *inListener) { mBodyManager.SetBodyActivationListener(inListener); }
@@ -137,10 +137,10 @@ public:
 	inline const BodyLockInterfaceLocking &	GetBodyLockInterface() const					{ return mBodyLockInterfaceLocking; }
 
 	/// Get an broadphase layer filter that uses the default pair filter and a specified object layer to determine if broadphase layers collide
-	DefaultBroadPhaseLayerFilter GetDefaultBroadPhaseLayerFilter(ObjectLayer inLayer) const	{ return DefaultBroadPhaseLayerFilter(mObjectVsBroadPhaseLayerFilter, inLayer); }
+	DefaultBroadPhaseLayerFilter GetDefaultBroadPhaseLayerFilter(ObjectLayer inLayer) const	{ return DefaultBroadPhaseLayerFilter(*mObjectVsBroadPhaseLayerFilter, inLayer); }
 
 	/// Get an object layer filter that uses the default pair filter and a specified layer to determine if layers collide
-	DefaultObjectLayerFilter	GetDefaultLayerFilter(ObjectLayer inLayer) const			{ return DefaultObjectLayerFilter(mObjectLayerPairFilter, inLayer); }
+	DefaultObjectLayerFilter	GetDefaultLayerFilter(ObjectLayer inLayer) const			{ return DefaultObjectLayerFilter(*mObjectLayerPairFilter, inLayer); }
 
 	/// Gets the current amount of bodies that are in the body manager
 	uint						GetNumBodies() const										{ return mBodyManager.GetNumBodies(); }
@@ -218,10 +218,10 @@ private:
 	static constexpr int		cNumCCDBodiesPerJob = 4;
 
 	/// Broadphase layer filter that decides if two objects can collide
-	ObjectVsBroadPhaseLayerFilter mObjectVsBroadPhaseLayerFilter = nullptr;
+	const ObjectVsBroadPhaseLayerFilter *mObjectVsBroadPhaseLayerFilter = nullptr;
 
 	/// Object layer filter that decides if two objects can collide
-	ObjectLayerPairFilter		mObjectLayerPairFilter = nullptr;
+	const ObjectLayerPairFilter *mObjectLayerPairFilter = nullptr;
 
 	/// The body manager keeps track which bodies are in the simulation
 	BodyManager					mBodyManager;

+ 29 - 21
PerformanceTest/Layers.h

@@ -14,18 +14,22 @@ namespace Layers
 	static constexpr uint8 NUM_LAYERS = 2;
 };
 
-/// Function that determines if two object layers can collide
-inline bool ObjectCanCollide(ObjectLayer inObject1, ObjectLayer inObject2)
+/// Class that determines if two object layers can collide
+class ObjectLayerPairFilterImpl : public ObjectLayerPairFilter
 {
-	switch (inObject1)
+public:
+	virtual bool					ShouldCollide(ObjectLayer inObject1, ObjectLayer inObject2) const override
 	{
-	case Layers::NON_MOVING:
-		return inObject2 == Layers::MOVING; // Non moving only collides with moving
-	case Layers::MOVING:
-		return true; // Moving collides with everything
-	default:
-		JPH_ASSERT(false);
-		return false;
+		switch (inObject1)
+		{
+		case Layers::NON_MOVING:
+			return inObject2 == Layers::MOVING; // Non moving only collides with moving
+		case Layers::MOVING:
+			return true; // Moving collides with everything
+		default:
+			JPH_ASSERT(false);
+			return false;
+		}
 	}
 };
 
@@ -75,17 +79,21 @@ private:
 	BroadPhaseLayer					mObjectToBroadPhase[Layers::NUM_LAYERS];
 };
 
-/// Function that determines if two broadphase layers can collide
-inline bool BroadPhaseCanCollide(ObjectLayer inLayer1, BroadPhaseLayer inLayer2)
+/// Class that determines if an object layer can collide with a broadphase layer
+class ObjectVsBroadPhaseLayerFilterImpl : public ObjectVsBroadPhaseLayerFilter
 {
-	switch (inLayer1)
+public:
+	virtual bool					ShouldCollide(ObjectLayer inLayer1, BroadPhaseLayer inLayer2) const override
 	{
-	case Layers::NON_MOVING:
-		return inLayer2 == BroadPhaseLayers::MOVING;
-	case Layers::MOVING:
-		return true;	
-	default:
-		JPH_ASSERT(false);
-		return false;
+		switch (inLayer1)
+		{
+		case Layers::NON_MOVING:
+			return inLayer2 == BroadPhaseLayers::MOVING;
+		case Layers::MOVING:
+			return true;	
+		default:
+			JPH_ASSERT(false);
+			return false;
+		}
 	}
-}
+};

+ 7 - 1
PerformanceTest/PerformanceTest.cpp

@@ -186,6 +186,12 @@ int main(int argc, char** argv)
 	// Create mapping table from object layer to broadphase layer
 	BPLayerInterfaceImpl broad_phase_layer_interface;
 
+	// Create class that filters object vs broadphase layers
+	ObjectVsBroadPhaseLayerFilterImpl object_vs_broadphase_layer_filter;
+
+	// Create class that filters object vs object layers
+	ObjectLayerPairFilterImpl object_vs_object_layer_filter;
+
 	// Start profiling this program
 	JPH_PROFILE_START("Main");
 
@@ -219,7 +225,7 @@ int main(int argc, char** argv)
 
 			// Create physics system
 			PhysicsSystem physics_system;
-			physics_system.Init(10240, 0, 65536, 10240, broad_phase_layer_interface, BroadPhaseCanCollide, ObjectCanCollide);
+			physics_system.Init(10240, 0, 65536, 10240, broad_phase_layer_interface, object_vs_broadphase_layer_filter, object_vs_object_layer_filter);
 
 			// Start test scene
 			scene->StartTest(physics_system, motion_quality);

+ 46 - 38
Samples/Layers.h

@@ -20,27 +20,31 @@ namespace Layers
 	static constexpr uint8 NUM_LAYERS = 8;
 };
 
-/// Function that determines if two object layers can collide
-inline bool ObjectCanCollide(ObjectLayer inObject1, ObjectLayer inObject2)
+/// Class that determines if two object layers can collide
+class ObjectLayerPairFilterImpl : public ObjectLayerPairFilter
 {
-	switch (inObject1)
+public:
+	virtual bool					ShouldCollide(ObjectLayer inObject1, ObjectLayer inObject2) const override
 	{
-	case Layers::UNUSED1:
-	case Layers::UNUSED2:
-	case Layers::UNUSED3:
-	case Layers::UNUSED4:
-		return false;
-	case Layers::NON_MOVING:
-		return inObject2 == Layers::MOVING || inObject2 == Layers::DEBRIS;
-	case Layers::MOVING:
-		return inObject2 == Layers::NON_MOVING || inObject2 == Layers::MOVING || inObject2 == Layers::SENSOR;
-	case Layers::DEBRIS:
-		return inObject2 == Layers::NON_MOVING;
-	case Layers::SENSOR:
-		return inObject2 == Layers::MOVING;
-	default:
-		JPH_ASSERT(false);
-		return false;
+		switch (inObject1)
+		{
+		case Layers::UNUSED1:
+		case Layers::UNUSED2:
+		case Layers::UNUSED3:
+		case Layers::UNUSED4:
+			return false;
+		case Layers::NON_MOVING:
+			return inObject2 == Layers::MOVING || inObject2 == Layers::DEBRIS;
+		case Layers::MOVING:
+			return inObject2 == Layers::NON_MOVING || inObject2 == Layers::MOVING || inObject2 == Layers::SENSOR;
+		case Layers::DEBRIS:
+			return inObject2 == Layers::NON_MOVING;
+		case Layers::SENSOR:
+			return inObject2 == Layers::MOVING;
+		default:
+			JPH_ASSERT(false);
+			return false;
+		}
 	}
 };
 
@@ -102,25 +106,29 @@ private:
 	BroadPhaseLayer					mObjectToBroadPhase[Layers::NUM_LAYERS];
 };
 
-/// Function that determines if two broadphase layers can collide
-inline bool BroadPhaseCanCollide(ObjectLayer inLayer1, BroadPhaseLayer inLayer2)
+/// Class that determines if an object layer can collide with a broadphase layer
+class ObjectVsBroadPhaseLayerFilterImpl : public ObjectVsBroadPhaseLayerFilter
 {
-	switch (inLayer1)
+public:
+	virtual bool					ShouldCollide(ObjectLayer inLayer1, BroadPhaseLayer inLayer2) const override
 	{
-	case Layers::NON_MOVING:
-		return inLayer2 == BroadPhaseLayers::MOVING;
-	case Layers::MOVING:
-		return inLayer2 == BroadPhaseLayers::NON_MOVING || inLayer2 == BroadPhaseLayers::MOVING || inLayer2 == BroadPhaseLayers::SENSOR;
-	case Layers::DEBRIS:
-		return inLayer2 == BroadPhaseLayers::NON_MOVING;
-	case Layers::SENSOR:
-		return inLayer2 == BroadPhaseLayers::MOVING;
-	case Layers::UNUSED1:
-	case Layers::UNUSED2:
-	case Layers::UNUSED3:
-		return false;			
-	default:
-		JPH_ASSERT(false);
-		return false;
+		switch (inLayer1)
+		{
+		case Layers::NON_MOVING:
+			return inLayer2 == BroadPhaseLayers::MOVING;
+		case Layers::MOVING:
+			return inLayer2 == BroadPhaseLayers::NON_MOVING || inLayer2 == BroadPhaseLayers::MOVING || inLayer2 == BroadPhaseLayers::SENSOR;
+		case Layers::DEBRIS:
+			return inLayer2 == BroadPhaseLayers::NON_MOVING;
+		case Layers::SENSOR:
+			return inLayer2 == BroadPhaseLayers::MOVING;
+		case Layers::UNUSED1:
+		case Layers::UNUSED2:
+		case Layers::UNUSED3:
+			return false;			
+		default:
+			JPH_ASSERT(false);
+			return false;
+		}
 	}
-}
+};

+ 1 - 1
Samples/SamplesApp.cpp

@@ -563,7 +563,7 @@ void SamplesApp::StartTest(const RTTI *inRTTI)
 
 	// Create physics system
 	mPhysicsSystem = new PhysicsSystem();
-	mPhysicsSystem->Init(cNumBodies, cNumBodyMutexes, cMaxBodyPairs, cMaxContactConstraints, mBroadPhaseLayerInterface, BroadPhaseCanCollide, ObjectCanCollide);
+	mPhysicsSystem->Init(cNumBodies, cNumBodyMutexes, cMaxBodyPairs, cMaxContactConstraints, mBroadPhaseLayerInterface, mObjectVsBroadPhaseLayerFilter, mObjectVsObjectLayerFilter);
 	mPhysicsSystem->SetPhysicsSettings(mPhysicsSettings);
 
 	// Restore gravity

+ 2 - 0
Samples/SamplesApp.h

@@ -93,6 +93,8 @@ private:
 	JobSystem *				mJobSystem = nullptr;										// The job system that runs physics jobs
 	JobSystem *				mJobSystemValidating = nullptr;								// The job system to use when validating determinism
 	BPLayerInterfaceImpl	mBroadPhaseLayerInterface;									// The broadphase layer interface that maps object layers to broadphase layers
+	ObjectVsBroadPhaseLayerFilterImpl mObjectVsBroadPhaseLayerFilter;					// Class that filters object vs broadphase layers
+	ObjectLayerPairFilterImpl mObjectVsObjectLayerFilter;								// Class that filters object vs object layers
 	PhysicsSystem *			mPhysicsSystem = nullptr;									// The physics system that simulates the world
 	ContactListenerImpl *	mContactListener = nullptr;									// Contact listener implementation
 	PhysicsSettings			mPhysicsSettings;											// Main physics simulation settings

+ 3 - 1
Samples/Tests/General/LoadSaveBinaryTest.cpp

@@ -24,7 +24,9 @@ void LoadSaveBinaryTest::Initialize()
 		// Create a new scene by instantiating the scene in a physics system and then converting it back to a scene
 		PhysicsSystem system;
 		BPLayerInterfaceImpl layer_interface;
-		system.Init(mPhysicsSystem->GetMaxBodies(), 0, 1024, 1024, layer_interface, BroadPhaseCanCollide, ObjectCanCollide);
+		ObjectVsBroadPhaseLayerFilterImpl object_vs_broadphase_layer_filter;
+		ObjectLayerPairFilterImpl object_vs_object_layer_filter;
+		system.Init(mPhysicsSystem->GetMaxBodies(), 0, 1024, 1024, layer_interface, object_vs_broadphase_layer_filter, object_vs_object_layer_filter);
 		scene->CreateBodies(&system);
 		Ref<PhysicsScene> scene_copy = new PhysicsScene();
 		scene_copy->FromPhysicsSystem(&system);

+ 48 - 40
UnitTests/Layers.h

@@ -21,28 +21,32 @@ namespace Layers
 	static constexpr uint8 NUM_LAYERS = 9;
 };
 
-/// Function that determines if two object layers can collide
-inline bool ObjectCanCollide(ObjectLayer inObject1, ObjectLayer inObject2)
+/// Class that determines if two object layers can collide
+class ObjectLayerPairFilterImpl : public ObjectLayerPairFilter
 {
-	switch (inObject1)
+public:
+	virtual bool					ShouldCollide(ObjectLayer inObject1, ObjectLayer inObject2) const override
 	{
-	case Layers::UNUSED1:
-	case Layers::UNUSED2:
-	case Layers::UNUSED3:
-	case Layers::UNUSED4:
-	case Layers::UNUSED5:
-		return false;
-	case Layers::NON_MOVING:
-		return inObject2 == Layers::MOVING || inObject2 == Layers::HQ_DEBRIS || inObject2 == Layers::LQ_DEBRIS;
-	case Layers::MOVING:
-		return inObject2 == Layers::NON_MOVING || inObject2 == Layers::MOVING || inObject2 == Layers::HQ_DEBRIS;
-	case Layers::HQ_DEBRIS:
-		return inObject2 == Layers::NON_MOVING || inObject2 == Layers::MOVING;
-	case Layers::LQ_DEBRIS:
-		return inObject2 == Layers::NON_MOVING;
-	default:
-		JPH_ASSERT(false);
-		return false;
+		switch (inObject1)
+		{
+		case Layers::UNUSED1:
+		case Layers::UNUSED2:
+		case Layers::UNUSED3:
+		case Layers::UNUSED4:
+		case Layers::UNUSED5:
+			return false;
+		case Layers::NON_MOVING:
+			return inObject2 == Layers::MOVING || inObject2 == Layers::HQ_DEBRIS || inObject2 == Layers::LQ_DEBRIS;
+		case Layers::MOVING:
+			return inObject2 == Layers::NON_MOVING || inObject2 == Layers::MOVING || inObject2 == Layers::HQ_DEBRIS;
+		case Layers::HQ_DEBRIS:
+			return inObject2 == Layers::NON_MOVING || inObject2 == Layers::MOVING;
+		case Layers::LQ_DEBRIS:
+			return inObject2 == Layers::NON_MOVING;
+		default:
+			JPH_ASSERT(false);
+			return false;
+		}
 	}
 };
 
@@ -103,26 +107,30 @@ private:
 	BroadPhaseLayer					mObjectToBroadPhase[Layers::NUM_LAYERS];
 };
 
-/// Function that determines if two broadphase layers can collide
-inline bool BroadPhaseCanCollide(ObjectLayer inLayer1, BroadPhaseLayer inLayer2)
+/// Class that determines if an object layer can collide with a broadphase layer
+class ObjectVsBroadPhaseLayerFilterImpl : public ObjectVsBroadPhaseLayerFilter
 {
-	switch (inLayer1)
+public:
+	virtual bool					ShouldCollide(ObjectLayer inLayer1, BroadPhaseLayer inLayer2) const override
 	{
-	case Layers::NON_MOVING:
-		return inLayer2 == BroadPhaseLayers::MOVING;
-	case Layers::MOVING:
-	case Layers::HQ_DEBRIS:
-		return inLayer2 == BroadPhaseLayers::NON_MOVING || inLayer2 == BroadPhaseLayers::MOVING;
-	case Layers::LQ_DEBRIS:
-		return inLayer2 == BroadPhaseLayers::NON_MOVING;
-	case Layers::UNUSED1:
-	case Layers::UNUSED2:
-	case Layers::UNUSED3:
-	case Layers::UNUSED4:
-	case Layers::UNUSED5:
-		return false;			
-	default:
-		JPH_ASSERT(false);
-		return false;
+		switch (inLayer1)
+		{
+		case Layers::NON_MOVING:
+			return inLayer2 == BroadPhaseLayers::MOVING;
+		case Layers::MOVING:
+		case Layers::HQ_DEBRIS:
+			return inLayer2 == BroadPhaseLayers::NON_MOVING || inLayer2 == BroadPhaseLayers::MOVING;
+		case Layers::LQ_DEBRIS:
+			return inLayer2 == BroadPhaseLayers::NON_MOVING;
+		case Layers::UNUSED1:
+		case Layers::UNUSED2:
+		case Layers::UNUSED3:
+		case Layers::UNUSED4:
+		case Layers::UNUSED5:
+			return false;			
+		default:
+			JPH_ASSERT(false);
+			return false;
+		}
 	}
-}
+};

+ 3 - 1
UnitTests/Physics/RayShapeTests.cpp

@@ -273,8 +273,10 @@ TEST_SUITE("RayShapeTests")
 
 		// Make the shape part of a body and insert it into the physics system
 		BPLayerInterfaceImpl broad_phase_layer_interface;
+		ObjectVsBroadPhaseLayerFilter object_vs_broadphase_layer_filter;
+		ObjectLayerPairFilter object_vs_object_layer_filter;
 		PhysicsSystem system;
-		system.Init(1, 0, 4, 4, broad_phase_layer_interface, [](ObjectLayer, BroadPhaseLayer) { return true; }, [](ObjectLayer, ObjectLayer) { return true; });
+		system.Init(1, 0, 4, 4, broad_phase_layer_interface, object_vs_broadphase_layer_filter, object_vs_object_layer_filter);
 		system.GetBodyInterface().CreateAndAddBody(BodyCreationSettings(inShape, RVec3(cShapePosition), cShapeRotation, EMotionType::Static, 0), EActivation::DontActivate);
 			   
 

+ 1 - 1
UnitTests/PhysicsTestContext.cpp

@@ -22,7 +22,7 @@ PhysicsTestContext::PhysicsTestContext(float inDeltaTime, int inCollisionSteps,
 {
 	// Create physics system
 	mSystem = new PhysicsSystem();
-	mSystem->Init(1024, 0, 4096, 1024, mBroadPhaseLayerInterface, BroadPhaseCanCollide, ObjectCanCollide);
+	mSystem->Init(1024, 0, 4096, 1024, mBroadPhaseLayerInterface, mObjectVsBroadPhaseLayerFilter, mObjectVsObjectLayerFilter);
 }
 
 PhysicsTestContext::~PhysicsTestContext()

+ 2 - 0
UnitTests/PhysicsTestContext.h

@@ -85,6 +85,8 @@ private:
 	TempAllocator *		mTempAllocator;
 	JobSystem *			mJobSystem;
 	BPLayerInterfaceImpl mBroadPhaseLayerInterface;
+	ObjectVsBroadPhaseLayerFilterImpl mObjectVsBroadPhaseLayerFilter;
+	ObjectLayerPairFilterImpl mObjectVsObjectLayerFilter;
 	PhysicsSystem *		mSystem;
 	float				mDeltaTime;
 	int					mCollisionSteps;