diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 6c8b6c80..18a8fffe 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -82305,9 +82305,9 @@ Address,Quality,Size,Name 0x0000007100f66938,U,000004, 0x0000007100f66948,U,000008, 0x0000007100f66950,U,000008, -0x0000007100f66958,U,000004,ksys::phys::ContactListener::contactPointAddedCallback -0x0000007100f6695c,U,000004,ksys::phys::ContactListener::contactPointRemovedCallback -0x0000007100f66960,U,000004,ksys::phys::ContactListener::contactProcessCallback +0x0000007100f66958,O,000004,_ZN4ksys4phys15ContactListener25contactPointAddedCallbackER25hkpContactPointAddedEvent +0x0000007100f6695c,O,000004,_ZN4ksys4phys15ContactListener27contactPointRemovedCallbackER27hkpContactPointRemovedEvent +0x0000007100f66960,O,000004,_ZN4ksys4phys15ContactListener22contactProcessCallbackER22hkpContactProcessEvent 0x0000007100f66964,U,000020, 0x0000007100f66978,U,000032, 0x0000007100f66998,U,000176, @@ -84301,11 +84301,11 @@ Address,Quality,Size,Name 0x0000007100fce180,O,000020,_ZN4ksys4phys15ContactListener10clearTableEv 0x0000007100fce194,O,000136,_ZN4ksys4phys15ContactListener22collisionAddedCallbackERK17hkpCollisionEvent 0x0000007100fce21c,O,000136,_ZN4ksys4phys15ContactListener24collisionRemovedCallbackERK17hkpCollisionEvent -0x0000007100fce2a4,U,000236,ksys::phys::ContactListener::x +0x0000007100fce2a4,O,000236,_ZN4ksys4phys15ContactListener22handleCollisionRemovedERK17hkpCollisionEventPNS0_9RigidBodyES6_ 0x0000007100fce390,U,000416,ksys::phys::ContactListener::m12 0x0000007100fce530,U,000028,ksys::phys::ContactListener::x_0 0x0000007100fce54c,U,000048,ksys::phys::ContactListener::x_1 -0x0000007100fce57c,U,000308,ksys::phys::ContactListener::contactPointCallback +0x0000007100fce57c,O,000308,_ZN4ksys4phys15ContactListener20contactPointCallbackERK20hkpContactPointEvent 0x0000007100fce6b0,U,000580,ksys::phys::ContactListener::m13 0x0000007100fce8f4,U,000764,ksys::phys::ContactListener::m14 0x0000007100fcebf0,U,001052,ksys::phys::ContactListener::x_2 diff --git a/lib/hkStubs/CMakeLists.txt b/lib/hkStubs/CMakeLists.txt index 03cac14c..8361d743 100644 --- a/lib/hkStubs/CMakeLists.txt +++ b/lib/hkStubs/CMakeLists.txt @@ -172,6 +172,7 @@ add_library(hkStubs OBJECT Havok/Physics2012/Internal/Collide/Mopp/Code/hkpMoppCode.h + Havok/Physics2012/Utilities/CharacterControl/CharacterRigidBody/hkpCharacterRigidBody.h Havok/Physics2012/Utilities/Collide/ShapeUtils/ShapeScaling/hkpShapeScalingUtility.h Havok/Physics2012/Utilities/Dynamics/ScaleSystem/hkpSystemScalingUtility.h Havok/Physics2012/Utilities/Serialize/hkpPhysicsData.h diff --git a/lib/hkStubs/Havok/Common/Base/Math/Vector/hkVector4f.h b/lib/hkStubs/Havok/Common/Base/Math/Vector/hkVector4f.h index 21caf846..699d1e93 100644 --- a/lib/hkStubs/Havok/Common/Base/Math/Vector/hkVector4f.h +++ b/lib/hkStubs/Havok/Common/Base/Math/Vector/hkVector4f.h @@ -187,6 +187,9 @@ public: void setZ(hkSimdFloat32Parameter val) { setComponent(2, val); } void setW(hkSimdFloat32Parameter val) { setComponent(3, val); } + HK_FORCE_INLINE void setInt24W(int value); + HK_FORCE_INLINE int getInt24W() const; + // ========== Load/store template diff --git a/lib/hkStubs/Havok/Common/Base/Math/Vector/hkVector4f.inl b/lib/hkStubs/Havok/Common/Base/Math/Vector/hkVector4f.inl index a12c1560..a4ad8c2a 100644 --- a/lib/hkStubs/Havok/Common/Base/Math/Vector/hkVector4f.inl +++ b/lib/hkStubs/Havok/Common/Base/Math/Vector/hkVector4f.inl @@ -510,6 +510,14 @@ inline hkSimdFloat32 hkVector4f::dot4xyz1(hkVector4fParameter a) const { #endif } +inline void hkVector4f::setInt24W(int value) { + reinterpret_cast(&v)[3] = hkInt32(value) | 0x3f000000; +} + +inline int hkVector4f::getInt24W() const { + return reinterpret_cast(&v)[3] & ~0x3f000000; +} + template inline const hkVector4f& hkVector4f::getConstant() { return reinterpret_cast(g_vectorfConstants[Constant]); diff --git a/lib/hkStubs/Havok/Physics2012/Utilities/CharacterControl/CharacterRigidBody/hkpCharacterRigidBody.h b/lib/hkStubs/Havok/Physics2012/Utilities/CharacterControl/CharacterRigidBody/hkpCharacterRigidBody.h new file mode 100644 index 00000000..3f192305 --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Utilities/CharacterControl/CharacterRigidBody/hkpCharacterRigidBody.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +// TODO +class hkpCharacterRigidBody { +public: + HK_DECLARE_CLASS_ALLOCATOR(hkpCharacterRigidBody) + + static const int m_magicNumber = 0x008df4a7; + static const int m_notMagicNumber = 0x00fa2bb3; +}; diff --git a/src/KingSystem/Physics/CMakeLists.txt b/src/KingSystem/Physics/CMakeLists.txt index 58d78215..cdeaec75 100644 --- a/src/KingSystem/Physics/CMakeLists.txt +++ b/src/KingSystem/Physics/CMakeLists.txt @@ -99,6 +99,7 @@ target_sources(uking PRIVATE System/physCharacterControllerParam.cpp System/physCharacterControllerParam.h + System/physCollisionInfo.h System/physConstraint.cpp System/physConstraint.h System/physContactInfoParam.cpp diff --git a/src/KingSystem/Physics/RigidBody/physRigidBody.h b/src/KingSystem/Physics/RigidBody/physRigidBody.h index b98ba414..f3fb87ba 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBody.h @@ -187,8 +187,11 @@ public: // 0x0000007100f8e3fc void x_11(); + // TODO: rename + void* get90() const { return _90; } // 0x0000007100f8e72c - void x_12(); + void x_12_setField90(void* field_90); + RigidContactPoints* getContactPoints() const { return mContactPoints; } void setContactPoints(RigidContactPoints* points); void freeze(bool should_freeze, bool preserve_velocities, bool preserve_max_impulse); @@ -206,6 +209,8 @@ public: void setContactMask(u32); void setContactAll(); void setContactNone(); + sead::BitFlag32 getContactMask() const { return mContactMask; } + sead::BitFlag32 getIgnoredLayers() const { return ~getContactMask(); } void enableGroundCollision(bool enabled); bool isGroundCollisionEnabled() const; diff --git a/src/KingSystem/Physics/System/physCollisionInfo.h b/src/KingSystem/Physics/System/physCollisionInfo.h new file mode 100644 index 00000000..9a252b01 --- /dev/null +++ b/src/KingSystem/Physics/System/physCollisionInfo.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include +#include "KingSystem/Physics/physDefines.h" + +namespace ksys::phys { + +class CollisionInfoBase { +public: + CollisionInfoBase() = default; + virtual ~CollisionInfoBase() = default; + + sead::BitFlag32& getLayerMask(ContactLayerType layer_type); + const sead::BitFlag32& getLayerMask(ContactLayerType layer_type) const; + + void lock(); + void unlock(); + +private: + // One layer mask for layer type (entity/sensor). + sead::SafeArray mLayerMasks; + sead::Mutex mMutex; +}; + +inline sead::BitFlag32& CollisionInfoBase::getLayerMask(ContactLayerType layer_type) { + return mLayerMasks[int(layer_type)]; +} + +inline const sead::BitFlag32& CollisionInfoBase::getLayerMask(ContactLayerType layer_type) const { + return mLayerMasks[int(layer_type)]; +} + +inline void CollisionInfoBase::lock() { + mMutex.lock(); +} + +inline void CollisionInfoBase::unlock() { + mMutex.unlock(); +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physContactListener.cpp b/src/KingSystem/Physics/System/physContactListener.cpp index c3ad636b..4a2a72aa 100644 --- a/src/KingSystem/Physics/System/physContactListener.cpp +++ b/src/KingSystem/Physics/System/physContactListener.cpp @@ -1,9 +1,13 @@ #include "KingSystem/Physics/System/physContactListener.h" +#include #include #include +#include #include #include #include "KingSystem/Physics/RigidBody/physRigidBody.h" +#include "KingSystem/Physics/System/physContactMgr.h" +#include "KingSystem/Physics/System/physSystem.h" namespace ksys::phys { @@ -65,4 +69,52 @@ void ContactListener::collisionRemovedCallback(const hkpCollisionEvent& event) { bodyB->onCollisionRemoved(); } +void ContactListener::contactPointCallback(const hkpContactPointEvent& event) { + RigidBody* body_a = getRigidBody(event.getBody(0)); + RigidBody* body_b = getRigidBody(event.getBody(1)); + + if (event.m_contactPoint->getPosition().getInt24W() == hkpCharacterRigidBody::m_magicNumber) { + const auto layer_a = body_a->getContactLayer(); + const auto layer_b = body_b->getContactLayer(); + const u32 ignored_layers_a = ~body_a->getContactMask(); + const u32 ignored_layers_b = ~body_b->getContactMask(); + + static_cast(System::instance()->getGroupFilter(mLayerType)); + + characterControlContactPointCallback(ignored_layers_a, ignored_layers_b, body_a, body_b, + layer_a, layer_b, event); + + } else if (event.m_type == hkpContactPointEvent::TYPE_MANIFOLD) { + manifoldContactPointCallback(event, body_a, body_b); + } else { + regularContactPointCallback(event, body_a, body_b); + } +} + +void ContactListener::handleCollisionRemoved(const hkpCollisionEvent& event, RigidBody* body_a, + RigidBody* body_b) { + unregisterForEndOfStepContactPointCallbacks(event); + + const auto layer_a = body_a->getContactLayer(); + const auto layer_b = body_b->getContactLayer(); + + if (auto* unk = body_a->get90()) + mMgr->x_19(unk, body_a, body_b); + + if (auto* unk = body_b->get90()) + mMgr->x_19(unk, body_b, body_a); + + const auto i = int(layer_a - mLayerBase); + const auto j = int(layer_b - mLayerBase); + ContactUnk1* unk = _30[i][j]; + if (unk->_68) { + const auto layer_a_ = int(layer_a); + const auto layer_unk = unk->_50; + const bool body_a_first = layer_a_ == layer_unk; + auto* body1 = body_a_first ? body_a : body_b; + auto* body2 = body_a_first ? body_b : body_a; + mMgr->x_20(unk, body1, body2); + } +} + } // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physContactListener.h b/src/KingSystem/Physics/System/physContactListener.h index a01218a3..f04aa91b 100644 --- a/src/KingSystem/Physics/System/physContactListener.h +++ b/src/KingSystem/Physics/System/physContactListener.h @@ -17,7 +17,11 @@ struct ContactUnk1 { ContactUnk1(u32 layer); virtual ~ContactUnk1(); - u8 _8[0x68]; + u8 _8[0x50 - 0x8]; + ContactLayer _50; + u8 _54[0x68 - 0x54]; + u32 _68; + u32 _6c; }; class ContactListener : public hkpContactListener, public sead::hostio::Node { @@ -32,20 +36,31 @@ public: void contactPointCallback(const hkpContactPointEvent& event) override; void collisionAddedCallback(const hkpCollisionEvent& event) override; void collisionRemovedCallback(const hkpCollisionEvent& event) override; - void contactPointAddedCallback(hkpContactPointAddedEvent& event) override; - void contactPointRemovedCallback(hkpContactPointRemovedEvent& event) override; - void contactProcessCallback(hkpContactProcessEvent& event) override; - - virtual void m10(); - virtual void m11() {} - virtual void handleCollisionAdded(const hkpCollisionEvent& event, RigidBody* bodyA, - RigidBody* bodyB); - virtual void m13(); - virtual void m14(); - virtual u32 m15() { return 0; } + void contactPointAddedCallback(hkpContactPointAddedEvent& event) override {} + void contactPointRemovedCallback(hkpContactPointRemovedEvent& event) override {} + void contactProcessCallback(hkpContactProcessEvent& event) override {} protected: - void handleCollisionRemoved(const hkpCollisionEvent& event, RigidBody* bodyA, RigidBody* bodyB); + virtual void characterControlContactPointCallback(u32 ignored_layers_a, u32 ignored_layers_b, + RigidBody* body_a, RigidBody* body_b, + ContactLayer layer_a, ContactLayer layer_b, + const hkpContactPointEvent& event); + + virtual void m11() {} + + virtual void handleCollisionAdded(const hkpCollisionEvent& event, RigidBody* body_a, + RigidBody* body_b); + + void handleCollisionRemoved(const hkpCollisionEvent& event, RigidBody* body_a, + RigidBody* body_b); + + virtual void manifoldContactPointCallback(const hkpContactPointEvent& event, RigidBody* body_a, + RigidBody* body_b); + + virtual void regularContactPointCallback(const hkpContactPointEvent& event, RigidBody* body_a, + RigidBody* body_b, void* unk = nullptr); + + virtual u32 m15() { return 0; } private: struct Unk1 { diff --git a/src/KingSystem/Physics/System/physContactMgr.h b/src/KingSystem/Physics/System/physContactMgr.h index 2e989f8a..5a868033 100644 --- a/src/KingSystem/Physics/System/physContactMgr.h +++ b/src/KingSystem/Physics/System/physContactMgr.h @@ -22,8 +22,10 @@ class Heap; namespace ksys::phys { +struct ContactUnk1; enum class IsIndoorStage; class IRigidContactPoints; +class RigidBody; class RigidContactPoints; class RigidContactPointsEx; @@ -86,6 +88,15 @@ public: void registerContactPoints(IRigidContactPoints* points); void freeContactPoints(IRigidContactPoints* points); + // 0x0000007100fb3744 + void x_17(void* unk, RigidBody* body_a, RigidBody* body_b); + // 0x0000007100fb37d4 + void x_18(ContactUnk1* unk, RigidBody* body_a, RigidBody* body_b); + // 0x0000007100fb3854 + void x_19(void* unk, RigidBody* body_a, RigidBody* body_b); + // 0x0000007100fb3938 + void x_20(ContactUnk1* unk, RigidBody* body_a, RigidBody* body_b); + private: void doLoadContactInfoTable(agl::utl::ResParameterArchive archive, ContactLayerType type, bool skip_params); diff --git a/src/KingSystem/Physics/System/physInstanceSet.h b/src/KingSystem/Physics/System/physInstanceSet.h index 5f2f2354..0f65245f 100644 --- a/src/KingSystem/Physics/System/physInstanceSet.h +++ b/src/KingSystem/Physics/System/physInstanceSet.h @@ -38,7 +38,7 @@ public: void enableCollisionMaybe_0(ContactLayer); }; -struct CollisionInfo { +struct CollisionInfoBase { u8 filler[0x50]; sead::SafeString mName; }; @@ -96,7 +96,7 @@ private: f32 mScale; u8 _34[0x40 - 0x34]; sead::PtrArray mRigidBodySets; - sead::PtrArray mCollisionInfos; + sead::PtrArray mCollisionInfos; sead::PtrArray mContactInfos; u8 _70[0x10];