// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics) // SPDX-FileCopyrightText: 2021 Jorrit Rouwe // SPDX-License-Identifier: MIT #pragma once #include #include /// Layer that objects can be in, determines which other objects it can collide with namespace Layers { static constexpr ObjectLayer UNUSED1 = 0; // 5 unused values so that broadphase layers values don't match with object layer values (for testing purposes) static constexpr ObjectLayer UNUSED2 = 1; static constexpr ObjectLayer UNUSED3 = 2; static constexpr ObjectLayer UNUSED4 = 3; static constexpr ObjectLayer UNUSED5 = 4; static constexpr ObjectLayer NON_MOVING = 5; static constexpr ObjectLayer MOVING = 6; static constexpr ObjectLayer HQ_DEBRIS = 7; // High quality debris collides with MOVING and NON_MOVING but not with any debris static constexpr ObjectLayer LQ_DEBRIS = 8; // Low quality debris only collides with NON_MOVING static constexpr ObjectLayer SENSOR = 9; // Sensors only collide with MOVING objects static constexpr ObjectLayer NUM_LAYERS = 10; }; /// Class that determines if two object layers can collide class ObjectLayerPairFilterImpl : public ObjectLayerPairFilter { public: virtual bool ShouldCollide(ObjectLayer inObject1, ObjectLayer inObject2) const override { 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 || inObject2 == Layers::SENSOR; case Layers::HQ_DEBRIS: return inObject2 == Layers::NON_MOVING || inObject2 == Layers::MOVING; case Layers::LQ_DEBRIS: return inObject2 == Layers::NON_MOVING; case Layers::SENSOR: return inObject2 == Layers::MOVING; default: JPH_ASSERT(false); return false; } } }; /// Broadphase layers namespace BroadPhaseLayers { static constexpr BroadPhaseLayer NON_MOVING(0); static constexpr BroadPhaseLayer MOVING(1); static constexpr BroadPhaseLayer LQ_DEBRIS(2); static constexpr BroadPhaseLayer UNUSED(3); static constexpr BroadPhaseLayer SENSOR(4); static constexpr uint NUM_LAYERS(5); }; /// BroadPhaseLayerInterface implementation class BPLayerInterfaceImpl final : public BroadPhaseLayerInterface { public: BPLayerInterfaceImpl() { // Create a mapping table from object to broad phase layer mObjectToBroadPhase[Layers::UNUSED1] = BroadPhaseLayers::UNUSED; mObjectToBroadPhase[Layers::UNUSED2] = BroadPhaseLayers::UNUSED; mObjectToBroadPhase[Layers::UNUSED3] = BroadPhaseLayers::UNUSED; mObjectToBroadPhase[Layers::UNUSED4] = BroadPhaseLayers::UNUSED; mObjectToBroadPhase[Layers::UNUSED5] = BroadPhaseLayers::UNUSED; mObjectToBroadPhase[Layers::NON_MOVING] = BroadPhaseLayers::NON_MOVING; mObjectToBroadPhase[Layers::MOVING] = BroadPhaseLayers::MOVING; mObjectToBroadPhase[Layers::HQ_DEBRIS] = BroadPhaseLayers::MOVING; // HQ_DEBRIS is also in the MOVING layer as an example on how to map multiple layers onto the same broadphase layer mObjectToBroadPhase[Layers::LQ_DEBRIS] = BroadPhaseLayers::LQ_DEBRIS; mObjectToBroadPhase[Layers::SENSOR] = BroadPhaseLayers::SENSOR; } virtual uint GetNumBroadPhaseLayers() const override { return BroadPhaseLayers::NUM_LAYERS; } virtual BroadPhaseLayer GetBroadPhaseLayer(ObjectLayer inLayer) const override { JPH_ASSERT(inLayer < Layers::NUM_LAYERS); return mObjectToBroadPhase[inLayer]; } #if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED) virtual const char * GetBroadPhaseLayerName(BroadPhaseLayer inLayer) const override { switch ((BroadPhaseLayer::Type)inLayer) { case (BroadPhaseLayer::Type)BroadPhaseLayers::NON_MOVING: return "NON_MOVING"; case (BroadPhaseLayer::Type)BroadPhaseLayers::MOVING: return "MOVING"; case (BroadPhaseLayer::Type)BroadPhaseLayers::LQ_DEBRIS: return "LQ_DEBRIS"; case (BroadPhaseLayer::Type)BroadPhaseLayers::UNUSED: return "UNUSED"; case (BroadPhaseLayer::Type)BroadPhaseLayers::SENSOR: return "SENSOR"; default: JPH_ASSERT(false); return "INVALID"; } } #endif // JPH_EXTERNAL_PROFILE || JPH_PROFILE_ENABLED private: BroadPhaseLayer mObjectToBroadPhase[Layers::NUM_LAYERS]; }; /// Class that determines if an object layer can collide with a broadphase layer class ObjectVsBroadPhaseLayerFilterImpl : public ObjectVsBroadPhaseLayerFilter { public: virtual bool ShouldCollide(ObjectLayer inLayer1, BroadPhaseLayer inLayer2) const override { 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 || inLayer2 == BroadPhaseLayers::SENSOR; case Layers::LQ_DEBRIS: return inLayer2 == BroadPhaseLayers::NON_MOVING; case Layers::SENSOR: return inLayer2 == BroadPhaseLayers::MOVING; case Layers::UNUSED1: case Layers::UNUSED2: case Layers::UNUSED3: case Layers::UNUSED4: case Layers::UNUSED5: return false; default: JPH_ASSERT(false); return false; } } };