From e219eccf0d6fd539c117a51045e96f969eb5166d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 28 Feb 2022 19:14:39 +0100 Subject: [PATCH] ksys/phys: Start implementing SensorGroupFilter --- data/uking_functions.csv | 60 ++++----- .../Physics/RigidBody/physRigidBody.cpp | 2 +- .../RigidBody/physRigidBodyFromShape.cpp | 2 +- .../Physics/RigidBody/physRigidBodyParam.h | 2 +- .../Physics/System/physSensorGroupFilter.cpp | 70 ++++++++++ .../Physics/System/physSensorGroupFilter.h | 121 +++++++++++++++++- src/KingSystem/Physics/physDefines.h | 38 +++++- 7 files changed, 257 insertions(+), 38 deletions(-) diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 37dbc534..61a57b57 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -84117,18 +84117,18 @@ Address,Quality,Size,Name 0x0000007100fc77c8,U,000044,phys::SomeClass::ctor_0 0x0000007100fc77f4,U,000260,phys::SomeClass::someCalc 0x0000007100fc78f8,U,000056,phys::SomeClass::x -0x0000007100fc7930,U,000140,makeSensorLayerTable -0x0000007100fc79bc,U,000004,phys::SensorGroupFilter::dtor -0x0000007100fc79c0,U,000008, -0x0000007100fc79c8,U,000008, -0x0000007100fc79d0,U,000008, -0x0000007100fc79d8,U,000008, -0x0000007100fc79e0,U,000088,phys::SensorGroupFilter::dtorDelete -0x0000007100fc7a38,U,000096, -0x0000007100fc7a98,U,000096, -0x0000007100fc7af8,U,000096, -0x0000007100fc7b58,U,000096, -0x0000007100fc7bb8,U,000004,phys::SensorGroupFilter::m13_n +0x0000007100fc7930,O,000140,_ZN4ksys4phys17SensorGroupFilter4makeENS0_12ContactLayer9ValueTypeEPN4sead4HeapE +0x0000007100fc79bc,O,000004,_ZN4ksys4phys17SensorGroupFilterD1Ev +0x0000007100fc79c0,O,000008,_ZThn16_N4ksys4phys17SensorGroupFilterD1Ev +0x0000007100fc79c8,O,000008,_ZThn24_N4ksys4phys17SensorGroupFilterD1Ev +0x0000007100fc79d0,O,000008,_ZThn32_N4ksys4phys17SensorGroupFilterD1Ev +0x0000007100fc79d8,O,000008,_ZThn40_N4ksys4phys17SensorGroupFilterD1Ev +0x0000007100fc79e0,O,000088,_ZN4ksys4phys17SensorGroupFilterD0Ev +0x0000007100fc7a38,O,000096,_ZThn16_N4ksys4phys17SensorGroupFilterD0Ev +0x0000007100fc7a98,O,000096,_ZThn24_N4ksys4phys17SensorGroupFilterD0Ev +0x0000007100fc7af8,O,000096,_ZThn32_N4ksys4phys17SensorGroupFilterD0Ev +0x0000007100fc7b58,O,000096,_ZThn40_N4ksys4phys17SensorGroupFilterD0Ev +0x0000007100fc7bb8,O,000004,_ZN4ksys4phys17SensorGroupFilter7doInit_EPN4sead4HeapE 0x0000007100fc7bbc,U,000432,phys::SensorGroupFilter::x 0x0000007100fc7d6c,U,000032,phys::SensorGroupFilter::isCollisionEnabled 0x0000007100fc7d8c,U,000036, @@ -84140,27 +84140,27 @@ Address,Quality,Size,Name 0x0000007100fc812c,U,000208, 0x0000007100fc81fc,U,000188,phys::SensorGroupFilter::isCollisionEnabled4 0x0000007100fc82b8,U,000188, -0x0000007100fc8374,U,000192,phys::SensorGroupFilter::m11 -0x0000007100fc8434,U,000016,phys::SensorGroupFilter::m12 +0x0000007100fc8374,O,000192,_ZN4ksys4phys17SensorGroupFilter30doInitSystemGroupHandlerLists_EPN4sead4HeapE +0x0000007100fc8434,O,000016,_ZN4ksys4phys17SensorGroupFilter16getFreeListIndexEPKNS0_18SystemGroupHandlerE 0x0000007100fc8444,O,000072,_ZN4ksys4phys26sensorReceiverMaskSetLayerENS0_12ContactLayerEj 0x0000007100fc848c,O,000060,_ZN4ksys4phys27sensorReceiverMaskSetLayer2EbNS0_12ContactLayerEj -0x0000007100fc84c8,U,000056,SensorGroupFilter::Handler::m5 -0x0000007100fc8500,U,000020,SensorGroupFilter::Handler::m6 -0x0000007100fc8514,U,000020,SensorGroupFilter::Handler::m8 -0x0000007100fc8528,U,000004,j__ZdlPv_1010 -0x0000007100fc852c,U,000204,phys::SensorGroupFilter::rtti1 -0x0000007100fc85f8,U,000092,phys::SensorGroupFilter::rtti2 -0x0000007100fc8654,U,000008,phys::GroupFilter::m2 -0x0000007100fc865c,U,000048,phys::SensorGroupFilter::m3 -0x0000007100fc868c,U,000024,phys::SensorGroupFilter::m4 -0x0000007100fc86a4,U,000008,phys::SensorGroupFilter::m5 -0x0000007100fc86ac,U,000008,phys::SensorGroupFilter::m6 -0x0000007100fc86b4,U,000032,phys::SensorGroupFilter::m7 -0x0000007100fc86d4,U,000032,phys::SensorGroupFilter::m8 +0x0000007100fc84c8,O,000056,_ZN4ksys4phys24SensorSystemGroupHandler23makeCollisionFilterInfoEjNS0_12ContactLayerENS0_9GroundHitE +0x0000007100fc8500,O,000020,_ZN4ksys4phys24SensorSystemGroupHandler22makeQueryCollisionMaskEjNS0_9GroundHitEb +0x0000007100fc8514,O,000020,_ZN4ksys4phys24SensorSystemGroupHandler2m8Ev +0x0000007100fc8528,O,000004,_ZN4ksys4phys24SensorSystemGroupHandlerD0Ev +0x0000007100fc852c,O,000204,_ZNK4ksys4phys17SensorGroupFilter27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100fc85f8,O,000092,_ZNK4ksys4phys17SensorGroupFilter18getRuntimeTypeInfoEv +0x0000007100fc8654,O,000008,_ZN4ksys4phys11GroupFilter2m2ENS0_12ContactLayerES2_ +0x0000007100fc865c,O,000048,_ZN4ksys4phys17SensorGroupFilter23makeCollisionFilterInfoENS0_12ContactLayerENS0_9GroundHitE +0x0000007100fc868c,O,000024,_ZN4ksys4phys17SensorGroupFilter27getCollisionFilterInfoLayerEj +0x0000007100fc86a4,O,000008,_ZN4ksys4phys17SensorGroupFilter22makeQueryCollisionMaskEjNS0_9GroundHitEb +0x0000007100fc86ac,O,000008,_ZN4ksys4phys17SensorGroupFilter30getQueryCollisionMaskGroundHitEj +0x0000007100fc86b4,O,000032,_ZN4ksys4phys17SensorGroupFilter39getCollisionFilterInfoLayerAndGroundHitEjPNS0_12ContactLayerEPNS0_9GroundHitE +0x0000007100fc86d4,O,000032,_ZN4ksys4phys17SensorGroupFilter31getCollisionFilterInfoLayerTextEj 0x0000007100fc86f4,O,000004,_ZN4ksys4phys11GroupFilter18setLayerCustomMaskENS0_12ContactLayerEj -0x0000007100fc86f8,U,000008,phys::SensorGroupFilter::m10 -0x0000007100fc8700,U,000008,phys::SensorGroupFilter::m14 -0x0000007100fc8708,U,000036,phys::SensorGroupFilter::m15 +0x0000007100fc86f8,O,000008,_ZN4ksys4phys17SensorGroupFilter37getCollisionFilterInfoGroupHandlerIdxEj +0x0000007100fc8700,O,000008,_ZN4ksys4phys17SensorGroupFilter23makeCollisionFilterInfoENS0_12ContactLayerENS0_9GroundHitEjj +0x0000007100fc8708,O,000036,_ZN4ksys4phys17SensorGroupFilter34setSensorLayerCollisionEnabledMaskENS0_12ContactLayerEj 0x0000007100fc872c,U,000172, 0x0000007100fc87d8,U,000004,nullsub_4250 0x0000007100fc87dc,U,000004,j__ZdlPv_1011 diff --git a/src/KingSystem/Physics/RigidBody/physRigidBody.cpp b/src/KingSystem/Physics/RigidBody/physRigidBody.cpp index 4bbee758..48fb016d 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBody.cpp +++ b/src/KingSystem/Physics/RigidBody/physRigidBody.cpp @@ -794,7 +794,7 @@ void RigidBody::setSensorCustomReceiver(const ReceiverMask& mask, info.raw = sensorReceiverMaskSetLayer(ContactLayer::SensorCustomReceiver, info.raw); if (handler) { - info.custom_receiver_data.group_handler_index.SetUnsafe(handler->getIndex()); + info.group_handler_index.SetUnsafe(handler->getIndex()); } setCollisionFilterInfo(info.raw); } diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.cpp b/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.cpp index 7e1de581..75497e41 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.cpp +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyFromShape.cpp @@ -351,7 +351,7 @@ RigidBodyT* RigidBodyFromShape::make(const Shape& shape, RigidBodyInstanceParam* const u32 idx = group_handler ? group_handler->getIndex() : 0; collision_filter_info = [&] { ReceiverMask info{collision_filter_info}; - info.custom_receiver_data.group_handler_index.SetUnsafe(idx); + info.group_handler_index.SetUnsafe(idx); return info.raw; }(); } diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyParam.h b/src/KingSystem/Physics/RigidBody/physRigidBodyParam.h index d561b056..33af6380 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyParam.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyParam.h @@ -82,7 +82,7 @@ public: GroundHit groundhit = GroundHit::HitAll; u32 groundhit_mask = 0; u32 contact_mask = 0; - ReceiverMask receiver_mask; + ReceiverMask receiver_mask{ReceiverMask::CustomReceiverTag{}}; bool ignore_normal_for_impulse = false; bool no_hit_ground = false; bool no_hit_water = false; diff --git a/src/KingSystem/Physics/System/physSensorGroupFilter.cpp b/src/KingSystem/Physics/System/physSensorGroupFilter.cpp index 09cf19ee..2ccb3212 100644 --- a/src/KingSystem/Physics/System/physSensorGroupFilter.cpp +++ b/src/KingSystem/Physics/System/physSensorGroupFilter.cpp @@ -1,8 +1,78 @@ #include "KingSystem/Physics/System/physSensorGroupFilter.h" #include +#include "KingSystem/Utils/HeapUtil.h" namespace ksys::phys { +constexpr int NumSensorHandlersInList0 = 0x10; +constexpr int NumSensorHandlers = 0x400; + +SensorGroupFilter* SensorGroupFilter::make(ContactLayer::ValueType last, sead::Heap* heap) { + auto* filter = util::alloc(heap, FirstSensor, last); + filter->initFilter(heap); + return filter; +} + +SensorGroupFilter::SensorGroupFilter(ContactLayer::ValueType first, ContactLayer::ValueType last) + : GroupFilter(ContactLayerType::Sensor, first, last) {} + +SensorGroupFilter::~SensorGroupFilter() = default; + +void SensorGroupFilter::doInit_(sead::Heap* heap) {} + +// TODO +hkBool SensorGroupFilter::isCollisionEnabled(const hkpCollidable& a, const hkpCollidable& b) const { + return hkpGroupFilter::isCollisionEnabled(a, b); +} + +// TODO +hkBool SensorGroupFilter::isCollisionEnabled(const hkpCollisionInput& input, + const hkpCdBody& collectionBodyA, + const hkpCdBody& collectionBodyB, + const hkpShapeContainer& containerShapeA, + const hkpShapeContainer& containerShapeB, + hkpShapeKey keyA, hkpShapeKey keyB) const { + return hkpGroupFilter::isCollisionEnabled(input, collectionBodyA, collectionBodyB, + containerShapeA, containerShapeB, keyA, keyB); +} + +// TODO +hkBool SensorGroupFilter::isCollisionEnabled(const hkpCollisionInput& input, const hkpCdBody& a, + const hkpCdBody& b, + const hkpShapeContainer& bContainer, + hkpShapeKey bKey) const { + return hkpGroupFilter::isCollisionEnabled(input, a, b, bContainer, bKey); +} + +// TODO +hkBool SensorGroupFilter::isCollisionEnabled(const hkpShapeRayCastInput& aInput, + const hkpShapeContainer& bContainer, + hkpShapeKey bKey) const { + return hkpGroupFilter::isCollisionEnabled(aInput, bContainer, bKey); +} + +// TODO +hkBool SensorGroupFilter::isCollisionEnabled(const hkpWorldRayCastInput& inputA, + const hkpCollidable& collidableB) const { + return hkpGroupFilter::isCollisionEnabled(inputA, collidableB); +} + +void SensorGroupFilter::doInitSystemGroupHandlerLists_(sead::Heap* heap) { + for (auto& list : mFreeLists) + list.initOffset(SystemGroupHandler::getFreeListNodeOffset()); + + mUsedList.initOffset(SystemGroupHandler::getUsedListNodeOffset()); + + for (int i = 1; i < NumSensorHandlers; ++i) { + auto& list = mFreeLists[i < NumSensorHandlersInList0]; + list.pushBack(new (heap) SensorSystemGroupHandler(i)); + } +} + +int SensorGroupFilter::getFreeListIndex(const SystemGroupHandler* handler) { + return handler->getIndex() < NumSensorHandlersInList0; +} + u32 sensorReceiverMaskSetLayer(ContactLayer layer, u32 mask) { SEAD_ASSERT(getContactLayerType(layer) == ContactLayerType::Sensor); diff --git a/src/KingSystem/Physics/System/physSensorGroupFilter.h b/src/KingSystem/Physics/System/physSensorGroupFilter.h index 4762d65b..9735bbab 100644 --- a/src/KingSystem/Physics/System/physSensorGroupFilter.h +++ b/src/KingSystem/Physics/System/physSensorGroupFilter.h @@ -5,11 +5,57 @@ namespace ksys::phys { -// FIXME +class SensorSystemGroupHandler : public SystemGroupHandler { +public: + explicit SensorSystemGroupHandler(int i) : SystemGroupHandler(i, ContactLayerType::Sensor) {} + + u32 makeCollisionFilterInfo(u32 info, ContactLayer layer, GroundHit ground_hit) override; + u32 makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, bool unk) override; + bool m8() override; +}; + class SensorGroupFilter : public GroupFilter { SEAD_RTTI_OVERRIDE(SensorGroupFilter, GroupFilter) public: static SensorGroupFilter* make(ContactLayer::ValueType last, sead::Heap* heap); + + SensorGroupFilter(ContactLayer::ValueType first, ContactLayer::ValueType last); + ~SensorGroupFilter() override; + + hkBool isCollisionEnabled(const hkpCollidable& a, const hkpCollidable& b) const override; + hkBool isCollisionEnabled(const hkpCollisionInput& input, const hkpCdBody& a, + const hkpCdBody& b, const hkpShapeContainer& bContainer, + hkpShapeKey bKey) const override; + hkBool isCollisionEnabled(const hkpCollisionInput& input, const hkpCdBody& collectionBodyA, + const hkpCdBody& collectionBodyB, + const hkpShapeContainer& containerShapeA, + const hkpShapeContainer& containerShapeB, hkpShapeKey keyA, + hkpShapeKey keyB) const override; + hkBool isCollisionEnabled(const hkpShapeRayCastInput& aInput, + const hkpShapeContainer& bContainer, hkpShapeKey bKey) const override; + hkBool isCollisionEnabled(const hkpWorldRayCastInput& inputA, + const hkpCollidable& collidableB) const override; + + u32 makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit) override; + ContactLayer getCollisionFilterInfoLayer(u32 info) override; + u32 makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, bool unk) override; + GroundHit getQueryCollisionMaskGroundHit(u32 info) override; + void getCollisionFilterInfoLayerAndGroundHit(u32 info, ContactLayer* layer, + GroundHit* ground_hit) override; + const char* getCollisionFilterInfoLayerText(u32 info) override; + u32 getCollisionFilterInfoGroupHandlerIdx(u32 info) override; + + virtual u32 makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit, u32 unk5, + u32 unk10); + virtual void setSensorLayerCollisionEnabledMask(ContactLayer layer, u32 mask); + +protected: + /// Checks whether two sensors are colliding. + hkBool testCollisionForSensors(u32 infoA, u32 infoB) const; + + void doInitSystemGroupHandlerLists_(sead::Heap* heap) override; + int getFreeListIndex(const SystemGroupHandler* handler) override; + void doInit_(sead::Heap* heap) override; }; /// Set the contact layer in a sensor receiver mask. @@ -25,4 +71,77 @@ u32 sensorReceiverMaskSetLayer(ContactLayer layer, u32 mask); // TODO: rename once we figure out what this layer is used for u32 sensorReceiverMaskSetLayer2(bool set, ContactLayer layer, u32 mask); +inline u32 SensorSystemGroupHandler::makeCollisionFilterInfo(u32 info, ContactLayer layer, + GroundHit ground_hit) { + const ReceiverMask current_info{info}; + ReceiverMask result; + + if (layer == ContactLayer::SensorCustomReceiver) { + result.is_custom_receiver = true; + result.group_handler_index.Init(getIndex()); + result.custom_receiver_data.layer.Init(current_info.custom_receiver_data.layer); + } else { + result.is_custom_receiver = false; + result.group_handler_index.Init(getIndex()); + result.data.layer.Init(layer - FirstSensor); + } + return result.raw; +} + +inline u32 SensorSystemGroupHandler::makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, + bool unk) { + SensorQueryCollisionMask mask; + mask.layer_mask = layer_mask; + mask.group_handler_index.Init(getIndex()); + return mask.raw; +} + +inline bool SensorSystemGroupHandler::m8() { + return getIndex() > 0 && getIndex() < 0x400; +} + +inline u32 SensorGroupFilter::makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit) { + return ReceiverMask::make(layer).raw; +} + +inline ContactLayer SensorGroupFilter::getCollisionFilterInfoLayer(u32 info) { + return ReceiverMask(info).getLayer(); +} + +inline u32 SensorGroupFilter::makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, + bool unk) { + SensorQueryCollisionMask mask; + mask.layer_mask = layer_mask; + return mask.raw; +} + +inline GroundHit SensorGroupFilter::getQueryCollisionMaskGroundHit(u32 info) { + return GroundHit::HitAll; +} + +inline void SensorGroupFilter::getCollisionFilterInfoLayerAndGroundHit(u32 info, + ContactLayer* layer, + GroundHit* ground_hit) { + ReceiverMask mask{info}; + *layer = mask.getLayer(); + *ground_hit = {}; +} + +inline const char* SensorGroupFilter::getCollisionFilterInfoLayerText(u32 info) { + return contactLayerToText(getCollisionFilterInfoLayer(info)); +} + +inline u32 SensorGroupFilter::getCollisionFilterInfoGroupHandlerIdx(u32 info) { + return ReceiverMask(info).group_handler_index; +} + +inline u32 SensorGroupFilter::makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit, + u32 unk5, u32 unk10) { + return 0; +} + +inline void SensorGroupFilter::setSensorLayerCollisionEnabledMask(ContactLayer layer, u32 mask) { + m_collisionLookupTable[layer - mLayerFirst] = mask; +} + } // namespace ksys::phys diff --git a/src/KingSystem/Physics/physDefines.h b/src/KingSystem/Physics/physDefines.h index 04147d0b..72a12317 100644 --- a/src/KingSystem/Physics/physDefines.h +++ b/src/KingSystem/Physics/physDefines.h @@ -201,8 +201,14 @@ enum class WaterCollisionMode { IgnoreWater = 1, }; +// TODO: rename to SensorCollisionFilterInfo. union ReceiverMask { + struct CustomReceiverTag {}; + union Data { + ContactLayer getLayer() const { return int(layer) + FirstSensor; } + + /// ContactLayer minus FirstSensor. util::BitField<0, 5, u32> layer; // TODO: rename once we figure out what this layer is used for util::BitField<5, 1, bool, u32> has_layer2; @@ -211,10 +217,10 @@ union ReceiverMask { union CustomReceiverData { util::BitField<0, 21, u32> layer; - util::BitField<21, 10, u32> group_handler_index; }; - constexpr ReceiverMask() : raw(0) { is_custom_receiver = true; } + constexpr ReceiverMask() : raw(0) {} + constexpr explicit ReceiverMask(CustomReceiverTag) : raw(0) { is_custom_receiver = true; } constexpr explicit ReceiverMask(u32 raw_) : raw(raw_) {} constexpr ReceiverMask(const ReceiverMask&) = default; constexpr ReceiverMask& operator=(const ReceiverMask& m) { @@ -234,11 +240,17 @@ union ReceiverMask { return mask; } + ContactLayer getLayer() const { + return is_custom_receiver ? ContactLayer::SensorCustomReceiver : data.getLayer(); + } + u32 raw; Data data; CustomReceiverData custom_receiver_data; - // FIXME: is this a sensor layer mask? + /// Sensor layer mask. + // TODO: add a constant for 21. util::BitField<0, 21, u32> layer_mask; + util::BitField<21, 10, u32> group_handler_index; util::BitField<31, 1, bool, u32> is_custom_receiver; }; @@ -319,7 +331,8 @@ union EntityCollisionFilterInfo { }; static_assert(sizeof(EntityCollisionFilterInfo) == sizeof(u32)); -/// Collision mask that is used for raycast-based queries. +/// Collision mask that is used for raycast-based queries against entities. +// TODO: rename to make it clear this is used for entities, not sensors union RayCastCollisionMask { constexpr explicit RayCastCollisionMask(u32 raw_ = 0) : raw(raw_) {} constexpr RayCastCollisionMask(const RayCastCollisionMask&) = default; @@ -337,6 +350,23 @@ union RayCastCollisionMask { u32 raw; }; +/// Collision mask that is used for raycast-based queries against sensors. +union SensorQueryCollisionMask { + constexpr explicit SensorQueryCollisionMask(u32 raw_ = 0) : raw(raw_) {} + constexpr SensorQueryCollisionMask(const SensorQueryCollisionMask&) = default; + constexpr SensorQueryCollisionMask& operator=(const SensorQueryCollisionMask& m) { + raw = m.raw; + return *this; + } + constexpr bool operator==(SensorQueryCollisionMask rhs) const { return raw == rhs.raw; } + constexpr bool operator!=(SensorQueryCollisionMask rhs) const { return raw != rhs.raw; } + + // TODO: add a constant for 21. + util::BitField<0, 21, u32> layer_mask; + util::BitField<22, 10, u32> group_handler_index; + u32 raw; +}; + ContactLayerType getContactLayerType(ContactLayer layer); u32 makeContactLayerMask(ContactLayer layer); u32 getContactLayerBase(ContactLayerType type);