From a222e401805340c7909a1bdddee670389f2ee943 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Tue, 1 Mar 2022 21:22:10 +0100 Subject: [PATCH] ksys/phys: Add more ContactListener functions and Havok prereqs --- data/uking_functions.csv | 36 +-- lib/hkStubs/CMakeLists.txt | 2 + .../Collide/Agent/ContactMgr/hkpContactMgr.h | 117 ++++++++++ .../Dynamics/Collide/hkpDynamicsContactMgr.h | 49 +++++ lib/sead | 2 +- .../RigidBody/Shape/Box/physBoxRigidBody.cpp | 3 +- .../RigidBody/Shape/Box/physBoxRigidBody.h | 3 +- .../Shape/BoxWater/physBoxWaterRigidBody.cpp | 3 +- .../Shape/BoxWater/physBoxWaterRigidBody.h | 3 +- .../Shape/Capsule/physCapsuleRigidBody.cpp | 3 +- .../Shape/Capsule/physCapsuleRigidBody.h | 3 +- .../Shape/Cylinder/physCylinderRigidBody.cpp | 3 +- .../Shape/Cylinder/physCylinderRigidBody.h | 3 +- .../physCylinderWaterRigidBody.cpp | 3 +- .../physCylinderWaterRigidBody.h | 3 +- .../Shape/List/physListShapeRigidBody.cpp | 3 +- .../Shape/List/physListShapeRigidBody.h | 3 +- .../Shape/Polytope/physPolytopeRigidBody.cpp | 3 +- .../Shape/Polytope/physPolytopeRigidBody.h | 3 +- .../Shape/Sphere/physSphereRigidBody.h | 3 +- .../TeraMesh/physTeraMeshRigidBody.h | 3 +- .../Physics/RigidBody/physRigidBody.h | 5 +- .../RigidBody/physRigidBodyFromResource.cpp | 3 +- .../RigidBody/physRigidBodyFromResource.h | 3 +- .../Physics/System/physCollisionInfo.h | 7 + .../Physics/System/physContactListener.cpp | 206 +++++++++++++++++- .../Physics/System/physContactListener.h | 43 +++- .../Physics/System/physContactMgr.h | 10 +- .../Physics/System/physContactPointInfo.h | 22 +- .../System/physLayerContactPointInfo.h | 15 +- src/KingSystem/Physics/System/physSystem.cpp | 4 +- 31 files changed, 500 insertions(+), 72 deletions(-) create mode 100644 lib/hkStubs/Havok/Physics2012/Collide/Agent/ContactMgr/hkpContactMgr.h create mode 100644 lib/hkStubs/Havok/Physics2012/Dynamics/Collide/hkpDynamicsContactMgr.h diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 8dddb375..b28e3dd2 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -83163,7 +83163,7 @@ Address,Quality,Size,Name 0x0000007100f97408,O,000016,_ZN4ksys4phys12BoxRigidBody9getVolumeEv 0x0000007100f97418,O,000008,_ZN4ksys4phys12BoxRigidBody9getShape_Ev 0x0000007100f97420,O,000008,_ZNK4ksys4phys12BoxRigidBody9getShape_Ev -0x0000007100f97428,O,000068,_ZN4ksys4phys12BoxRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKj +0x0000007100f97428,O,000068,_ZN4ksys4phys12BoxRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKjRKN4sead7Vector3IfEE 0x0000007100f9746c,O,000288,_ZNK4ksys4phys12BoxRigidBody27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100f9758c,O,000092,_ZNK4ksys4phys12BoxRigidBody18getRuntimeTypeInfoEv 0x0000007100f975e8,O,000004,_ZN4ksys4phys17BoxWaterRigidBody4makeEPNS0_22RigidBodyInstanceParamEPN4sead4HeapE @@ -83180,7 +83180,7 @@ Address,Quality,Size,Name 0x0000007100f97814,O,000016,_ZN4ksys4phys17BoxWaterRigidBody9getVolumeEv 0x0000007100f97824,O,000008,_ZN4ksys4phys17BoxWaterRigidBody9getShape_Ev 0x0000007100f9782c,O,000008,_ZNK4ksys4phys17BoxWaterRigidBody9getShape_Ev -0x0000007100f97834,O,000068,_ZN4ksys4phys17BoxWaterRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKj +0x0000007100f97834,O,000068,_ZN4ksys4phys17BoxWaterRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKjRKN4sead7Vector3IfEE 0x0000007100f97878,O,000288,_ZNK4ksys4phys17BoxWaterRigidBody27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100f97998,O,000092,_ZNK4ksys4phys17BoxWaterRigidBody18getRuntimeTypeInfoEv 0x0000007100f979f4,O,000004,_ZN4ksys4phys16CapsuleRigidBody4makeEPNS0_22RigidBodyInstanceParamEPN4sead4HeapE @@ -83199,7 +83199,7 @@ Address,Quality,Size,Name 0x0000007100f97c9c,O,000016,_ZN4ksys4phys16CapsuleRigidBody9getVolumeEv 0x0000007100f97cac,O,000008,_ZN4ksys4phys16CapsuleRigidBody9getShape_Ev 0x0000007100f97cb4,O,000008,_ZNK4ksys4phys16CapsuleRigidBody9getShape_Ev -0x0000007100f97cbc,O,000068,_ZN4ksys4phys16CapsuleRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKj +0x0000007100f97cbc,O,000068,_ZN4ksys4phys16CapsuleRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKjRKN4sead7Vector3IfEE 0x0000007100f97d00,O,000288,_ZNK4ksys4phys16CapsuleRigidBody27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100f97e20,O,000092,_ZNK4ksys4phys16CapsuleRigidBody18getRuntimeTypeInfoEv 0x0000007100f97e7c,O,000004,_ZN4ksys4phys18ListShapeRigidBody4makeEPNS0_22RigidBodyInstanceParamEPN4sead4HeapE @@ -83218,7 +83218,7 @@ Address,Quality,Size,Name 0x0000007100f9808c,O,000016,_ZN4ksys4phys18ListShapeRigidBody9getVolumeEv 0x0000007100f9809c,O,000008,_ZN4ksys4phys18ListShapeRigidBody9getShape_Ev 0x0000007100f980a4,O,000008,_ZNK4ksys4phys18ListShapeRigidBody9getShape_Ev -0x0000007100f980ac,O,000100,_ZN4ksys4phys18ListShapeRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKj +0x0000007100f980ac,O,000100,_ZN4ksys4phys18ListShapeRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKjRKN4sead7Vector3IfEE 0x0000007100f98110,O,000288,_ZNK4ksys4phys18ListShapeRigidBody27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100f98230,O,000092,_ZNK4ksys4phys18ListShapeRigidBody18getRuntimeTypeInfoEv 0x0000007100f9828c,O,000004,_ZN4ksys4phys17CylinderRigidBody4makeEPNS0_22RigidBodyInstanceParamEPN4sead4HeapE @@ -83237,7 +83237,7 @@ Address,Quality,Size,Name 0x0000007100f98538,O,000016,_ZN4ksys4phys17CylinderRigidBody9getVolumeEv 0x0000007100f98548,O,000008,_ZN4ksys4phys17CylinderRigidBody9getShape_Ev 0x0000007100f98550,O,000008,_ZNK4ksys4phys17CylinderRigidBody9getShape_Ev -0x0000007100f98558,O,000068,_ZN4ksys4phys17CylinderRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKj +0x0000007100f98558,O,000068,_ZN4ksys4phys17CylinderRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKjRKN4sead7Vector3IfEE 0x0000007100f9859c,O,000288,_ZNK4ksys4phys17CylinderRigidBody27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100f986bc,O,000092,_ZNK4ksys4phys17CylinderRigidBody18getRuntimeTypeInfoEv 0x0000007100f98718,O,000004,_ZN4ksys4phys22CylinderWaterRigidBody4makeEPNS0_22RigidBodyInstanceParamEPN4sead4HeapE @@ -83255,7 +83255,7 @@ Address,Quality,Size,Name 0x0000007100f9897c,O,000016,_ZN4ksys4phys22CylinderWaterRigidBody9getVolumeEv 0x0000007100f9898c,O,000008,_ZN4ksys4phys22CylinderWaterRigidBody9getShape_Ev 0x0000007100f98994,O,000008,_ZNK4ksys4phys22CylinderWaterRigidBody9getShape_Ev -0x0000007100f9899c,O,000068,_ZN4ksys4phys22CylinderWaterRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKj +0x0000007100f9899c,O,000068,_ZN4ksys4phys22CylinderWaterRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKjRKN4sead7Vector3IfEE 0x0000007100f989e0,O,000288,_ZNK4ksys4phys22CylinderWaterRigidBody27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100f98b00,O,000092,_ZNK4ksys4phys22CylinderWaterRigidBody18getRuntimeTypeInfoEv 0x0000007100f98b5c,O,000168,_ZN4ksys4phys21RigidBodyFromResourceC1EfP12hkpRigidBodyNS0_16ContactLayerTypeEPN4sead4HeapENS0_9RigidBody4TypeE @@ -83266,7 +83266,7 @@ Address,Quality,Size,Name 0x0000007100f98c5c,O,000108,_ZN4ksys4phys21RigidBodyFromResource4initERKNS0_22RigidBodyInstanceParamEPN4sead4HeapE 0x0000007100f98cc8,O,000048,_ZNK4ksys4phys21RigidBodyFromResource24isBvTreeOrStaticCompoundEv 0x0000007100f98cf8,O,000312,_ZNK4ksys4phys21RigidBodyFromResource10isMaterialENS0_8MaterialE -0x0000007100f98e30,O,000076,_ZN4ksys4phys21RigidBodyFromResource17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKj +0x0000007100f98e30,O,000076,_ZN4ksys4phys21RigidBodyFromResource17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKjRKN4sead7Vector3IfEE 0x0000007100f98e7c,O,000076,_ZN4ksys4phys21RigidBodyFromResource12updateScale_Eff 0x0000007100f98ec8,O,000392,_ZN4ksys4phys21RigidBodyFromResource17getNewHavokShape_Ev 0x0000007100f99050,O,000008,_ZN4ksys4phys21RigidBodyFromResource9getVolumeEv @@ -83355,7 +83355,7 @@ Address,Quality,Size,Name 0x0000007100fa18f8,O,000016,_ZN4ksys4phys17PolytopeRigidBody9getVolumeEv 0x0000007100fa1908,O,000008,_ZN4ksys4phys17PolytopeRigidBody9getShape_Ev 0x0000007100fa1910,O,000008,_ZNK4ksys4phys17PolytopeRigidBody9getShape_Ev -0x0000007100fa1918,O,000068,_ZN4ksys4phys17PolytopeRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKj +0x0000007100fa1918,O,000068,_ZN4ksys4phys17PolytopeRigidBody17getCollisionMasksEPNS0_9RigidBody14CollisionMasksEPKjRKN4sead7Vector3IfEE 0x0000007100fa195c,O,000008,_ZN4ksys4phys17PolytopeRigidBody9setVolumeEf 0x0000007100fa1964,O,000288,_ZNK4ksys4phys17PolytopeRigidBody27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100fa1a84,O,000092,_ZNK4ksys4phys17PolytopeRigidBody18getRuntimeTypeInfoEv @@ -84302,20 +84302,20 @@ Address,Quality,Size,Name 0x0000007100fce194,O,000136,_ZN4ksys4phys15ContactListener22collisionAddedCallbackERK17hkpCollisionEvent 0x0000007100fce21c,O,000136,_ZN4ksys4phys15ContactListener24collisionRemovedCallbackERK17hkpCollisionEvent 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 +0x0000007100fce390,O,000416,_ZN4ksys4phys15ContactListener20handleCollisionAddedERK17hkpCollisionEventPNS0_9RigidBodyES6_ +0x0000007100fce530,O,000028,_ZNK4ksys4phys15ContactListener30areContactsTrackedForLayerPairEjj +0x0000007100fce54c,O,000048,_ZN4ksys4phys15ContactListener28getContactLayerCollisionInfoEjj 0x0000007100fce57c,O,000308,_ZN4ksys4phys15ContactListener20contactPointCallbackERK20hkpContactPointEvent -0x0000007100fce6b0,U,000580,ksys::phys::ContactListener::m13 +0x0000007100fce6b0,O,000580,_ZN4ksys4phys15ContactListener28manifoldContactPointCallbackERK20hkpContactPointEventPNS0_9RigidBodyES6_ 0x0000007100fce8f4,U,000764,ksys::phys::ContactListener::m14 0x0000007100fcebf0,U,001052,ksys::phys::ContactListener::x_2 0x0000007100fcf00c,U,000660,ksys::phys::ContactListener::x_3 -0x0000007100fcf2a0,U,000356,ksys::phys::ContactListener::x_4 -0x0000007100fcf404,U,000112,ksys::phys::ContactListener::x_5 -0x0000007100fcf474,U,000576,ksys::phys::ContactListener::x_6 -0x0000007100fcf6b4,U,000124,ksys::phys::ContactListener::x_7 -0x0000007100fcf730,U,000156,ksys::phys::ContactListener::x_8 -0x0000007100fcf7cc,U,000024,ksys::phys::ContactListener::m10 +0x0000007100fcf2a0,O,000356,_ZN4ksys4phys15ContactListener31addLayerPairForContactPointInfoEPNS0_21LayerContactPointInfoENS0_12ContactLayerES4_b +0x0000007100fcf404,O,000112,_ZN4ksys4phys15ContactListener35removeLayerPairsForContactPointInfoEPNS0_21LayerContactPointInfoE +0x0000007100fcf474,m,000576,_ZN4ksys4phys15ContactListener34removeLayerPairForContactPointInfoEPNS0_21LayerContactPointInfoENS0_12ContactLayerES4_ +0x0000007100fcf6b4,O,000124,_ZN4ksys4phys15ContactListener14trackLayerPairENS0_12ContactLayerES2_ +0x0000007100fcf730,O,000156,_ZN4ksys4phys15ContactListener17registerRigidBodyEPNS0_9RigidBodyE +0x0000007100fcf7cc,O,000024,_ZN4ksys4phys15ContactListener36characterControlContactPointCallbackEjjPNS0_9RigidBodyES3_NS0_12ContactLayerES4_RK20hkpContactPointEvent 0x0000007100fcf7e4,O,000112,_ZNK4ksys4phys15ContactListener27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100fcf854,O,000092,_ZNK4ksys4phys15ContactListener18getRuntimeTypeInfoEv 0x0000007100fcf8b0,O,000004,_ZN4ksys4phys15ContactListener3m11Ev diff --git a/lib/hkStubs/CMakeLists.txt b/lib/hkStubs/CMakeLists.txt index 8361d743..3f5d23bb 100644 --- a/lib/hkStubs/CMakeLists.txt +++ b/lib/hkStubs/CMakeLists.txt @@ -92,6 +92,7 @@ add_library(hkStubs OBJECT Havok/Physics2012/Collide/Agent/Collidable/hkpCdBody.h Havok/Physics2012/Collide/Agent/Collidable/hkpCollidable.h Havok/Physics2012/Collide/Agent/Collidable/hkpCollidableQualityType.h + Havok/Physics2012/Collide/Agent/ContactMgr/hkpContactMgr.h Havok/Physics2012/Collide/Agent3/BvTree3/hkpBvTreeAgent3.h Havok/Physics2012/Collide/Agent3/Machine/Nn/hkpAgentNnTrack.h Havok/Physics2012/Collide/Agent3/Machine/Nn/hkpLinkedCollidable.h @@ -133,6 +134,7 @@ add_library(hkStubs OBJECT Havok/Physics2012/Collide/Util/Welding/hkpWeldingUtility.h Havok/Physics2012/Dynamics/Action/hkpAction.h + Havok/Physics2012/Dynamics/Collide/hkpDynamicsContactMgr.h Havok/Physics2012/Dynamics/Collide/hkpResponseModifier.h Havok/Physics2012/Dynamics/Collide/ContactListener/hkpCollisionEvent.h Havok/Physics2012/Dynamics/Collide/ContactListener/hkpContactListener.h diff --git a/lib/hkStubs/Havok/Physics2012/Collide/Agent/ContactMgr/hkpContactMgr.h b/lib/hkStubs/Havok/Physics2012/Collide/Agent/ContactMgr/hkpContactMgr.h new file mode 100644 index 00000000..30132920 --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Collide/Agent/ContactMgr/hkpContactMgr.h @@ -0,0 +1,117 @@ +#pragma once + +#include +#include "Havok/Common/Base/Types/Physics/ContactPoint/hkContactPoint.h" + +class hkCollisionConstraintOwner; + +class hkpCdBody; +class hkpCollidable; +class hkpContactPointProperties; +class hkpGskCache; +struct hkpProcessCollisionData; +struct hkpProcessCollisionInput; +struct hkpProcessCollisionOutput; + +class hkpContactMgr : public hkReferencedObject { +public: + HK_DECLARE_CLASS_ALLOCATOR(hkpContactMgr) + + enum Type { + TYPE_SIMPLE_CONSTRAINT_CONTACT_MGR, + TYPE_REPORT_CONTACT_MGR, + TYPE_CONVEX_LIST_CONTACT_MGR, + TYPE_NULL_CONTACT_MGR, + TYPE_USER_CONTACT_MGR, + TYPE_MAX + }; + + enum ToiAccept { TOI_ACCEPT = 0, TOI_REJECT = 1 }; + + explicit hkpContactMgr(Type type) : m_type(type) {} + + HK_FORCE_INLINE hkContactPointId addContactPoint(const hkpCdBody& a, const hkpCdBody& b, + const hkpProcessCollisionInput& input, + hkpProcessCollisionOutput& output, + const hkpGskCache* contactCache, + hkContactPoint& cp); + + HK_FORCE_INLINE hkResult reserveContactPoints(int numPoints); + + HK_FORCE_INLINE void removeContactPoint(hkContactPointId cpId, + hkCollisionConstraintOwner& constraintOwner); + + HK_FORCE_INLINE void processContact(const hkpCollidable& a, const hkpCollidable& b, + const hkpProcessCollisionInput& input, + hkpProcessCollisionData& collisionData); + + HK_FORCE_INLINE ToiAccept addToi(const hkpCdBody& a, const hkpCdBody& b, + const hkpProcessCollisionInput& input, + hkpProcessCollisionOutput& output, hkTime toi, + hkContactPoint& cp, const hkpGskCache* gskCache, + hkReal& projectedVelocity, + hkpContactPointProperties& propertiesOut); + + HK_FORCE_INLINE void removeToi(class hkCollisionConstraintOwner& constraintOwner, + hkpContactPointProperties& properties); + +protected: + virtual hkContactPointId addContactPointImpl(const hkpCdBody& a, const hkpCdBody& b, + const hkpProcessCollisionInput& input, + hkpProcessCollisionOutput& output, + const hkpGskCache* contactCache, + hkContactPoint& cp) = 0; + virtual hkResult reserveContactPointsImpl(int numPoints) = 0; + virtual void removeContactPointImpl(hkContactPointId cpId, + hkCollisionConstraintOwner& constraintOwner) = 0; + virtual void processContactImpl(const hkpCollidable& a, const hkpCollidable& b, + const hkpProcessCollisionInput& input, + hkpProcessCollisionData& collisionData) = 0; + virtual ToiAccept addToiImpl(const hkpCdBody& a, const hkpCdBody& b, + const hkpProcessCollisionInput& input, + hkpProcessCollisionOutput& output, hkTime toi, hkContactPoint& cp, + const hkpGskCache* gskCache, hkReal& projectedVelocity, + hkpContactPointProperties& propertiesOut) = 0; + virtual void removeToiImpl(class hkCollisionConstraintOwner& constraintOwner, + hkpContactPointProperties& properties) = 0; + virtual void cleanup() {} + +public: + Type m_type; +}; + +inline hkContactPointId hkpContactMgr::addContactPoint(const hkpCdBody& a, const hkpCdBody& b, + const hkpProcessCollisionInput& input, + hkpProcessCollisionOutput& output, + const hkpGskCache* contactCache, + hkContactPoint& cp) { + return addContactPointImpl(a, b, input, output, contactCache, cp); +} + +inline hkResult hkpContactMgr::reserveContactPoints(int numPoints) { + return reserveContactPointsImpl(numPoints); +} + +inline void hkpContactMgr::removeContactPoint(hkContactPointId cpId, + hkCollisionConstraintOwner& constraintOwner) { + removeContactPointImpl(cpId, constraintOwner); +} + +inline void hkpContactMgr::processContact(const hkpCollidable& a, const hkpCollidable& b, + const hkpProcessCollisionInput& input, + hkpProcessCollisionData& collisionData) { + processContactImpl(a, b, input, collisionData); +} + +inline hkpContactMgr::ToiAccept +hkpContactMgr::addToi(const hkpCdBody& a, const hkpCdBody& b, const hkpProcessCollisionInput& input, + hkpProcessCollisionOutput& output, hkTime toi, hkContactPoint& cp, + const hkpGskCache* gskCache, hkReal& projectedVelocity, + hkpContactPointProperties& propertiesOut) { + return addToiImpl(a, b, input, output, toi, cp, gskCache, projectedVelocity, propertiesOut); +} + +inline void hkpContactMgr::removeToi(hkCollisionConstraintOwner& constraintOwner, + hkpContactPointProperties& properties) { + removeToiImpl(constraintOwner, properties); +} diff --git a/lib/hkStubs/Havok/Physics2012/Dynamics/Collide/hkpDynamicsContactMgr.h b/lib/hkStubs/Havok/Physics2012/Dynamics/Collide/hkpDynamicsContactMgr.h new file mode 100644 index 00000000..66bf6a56 --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Dynamics/Collide/hkpDynamicsContactMgr.h @@ -0,0 +1,49 @@ +#pragma once + +#include + +class hkContactPoint; +class hkpContactPointProperties; +class hkpWorld; + +/// An interface to access contact point information. +class hkpDynamicsContactMgr : public hkpContactMgr { +public: + HK_DECLARE_CLASS_ALLOCATOR(hkpDynamicsContactMgr) + + explicit hkpDynamicsContactMgr(Type type) : hkpContactMgr(type) {} + + virtual hkpContactPointProperties* getContactPointProperties(hkContactPointId id) { + return nullptr; + } + + virtual hkContactPoint* getContactPoint(hkContactPointId id) { return nullptr; } + + virtual void getAllContactPointIds(hkArray& contactPointIds) const {} + + virtual Type getType() const = 0; + + virtual void toiCollisionResponseBeginCallback(const hkContactPoint& cp, + struct hkpSimpleConstraintInfoInitInput& inA, + struct hkpBodyVelocity& velA, + hkpSimpleConstraintInfoInitInput& inB, + hkpBodyVelocity& velB) {} + + virtual void toiCollisionResponseEndCallback(const hkContactPoint& cp, hkReal impulseApplied, + struct hkpSimpleConstraintInfoInitInput& inA, + struct hkpBodyVelocity& velA, + hkpSimpleConstraintInfoInitInput& inB, + hkpBodyVelocity& velB) {} + + virtual class hkpConstraintInstance* getConstraintInstance() { return nullptr; } + + virtual hkBool fireCallbacksForEarliestToi(struct hkpToiEvent& event, hkReal& rotateNormal) { + return false; + } + + virtual void confirmToi(struct hkpToiEvent& event, hkReal rotateNormal, + class hkArray& outToBeActivated) {} + +protected: + hkpWorld* m_world; +}; diff --git a/lib/sead b/lib/sead index 1b10f7f5..5327840d 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit 1b10f7f596f15999b7f6d10b96f69081a961f907 +Subproject commit 5327840d10d79c9adb61e2d2575447cbaea67ea6 diff --git a/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxRigidBody.cpp b/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxRigidBody.cpp index e4a611c9..9e38ba43 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxRigidBody.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxRigidBody.cpp @@ -64,7 +64,8 @@ const Shape* BoxRigidBody::getShape_() const { return mShape; } -u32 BoxRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) { +u32 BoxRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) { masks->ignored_layers = ~mContactMask.getDirect(); masks->collision_filter_info = getCollisionFilterInfo(); masks->material_mask = getMaterialMask().getRawData(); diff --git a/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxRigidBody.h index a0373b6c..2e92404b 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Box/physBoxRigidBody.h @@ -33,7 +33,8 @@ public: protected: Shape* getShape_() override; const Shape* getShape_() const override; - u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override; + u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) override; BoxShape* mShape; }; diff --git a/src/KingSystem/Physics/RigidBody/Shape/BoxWater/physBoxWaterRigidBody.cpp b/src/KingSystem/Physics/RigidBody/Shape/BoxWater/physBoxWaterRigidBody.cpp index 9c7385f3..3f30214f 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/BoxWater/physBoxWaterRigidBody.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/BoxWater/physBoxWaterRigidBody.cpp @@ -54,7 +54,8 @@ const Shape* BoxWaterRigidBody::getShape_() const { return mShape; } -u32 BoxWaterRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) { +u32 BoxWaterRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) { masks->ignored_layers = ~mContactMask.getDirect(); masks->collision_filter_info = getCollisionFilterInfo(); masks->material_mask = getMaterialMask().getRawData(); diff --git a/src/KingSystem/Physics/RigidBody/Shape/BoxWater/physBoxWaterRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/BoxWater/physBoxWaterRigidBody.h index 35c173a4..1d281c66 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/BoxWater/physBoxWaterRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/Shape/BoxWater/physBoxWaterRigidBody.h @@ -31,7 +31,8 @@ public: protected: Shape* getShape_() override; const Shape* getShape_() const override; - u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override; + u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) override; BoxWaterShape* mShape; u32 _d8{}; diff --git a/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleRigidBody.cpp b/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleRigidBody.cpp index afc1528a..b4a2663b 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleRigidBody.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleRigidBody.cpp @@ -65,7 +65,8 @@ const Shape* CapsuleRigidBody::getShape_() const { return mShape; } -u32 CapsuleRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) { +u32 CapsuleRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) { masks->ignored_layers = ~mContactMask.getDirect(); masks->collision_filter_info = getCollisionFilterInfo(); masks->material_mask = getMaterialMask().getRawData(); diff --git a/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleRigidBody.h index 1ab1501a..d4a996fe 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Capsule/physCapsuleRigidBody.h @@ -31,7 +31,8 @@ public: protected: Shape* getShape_() override; const Shape* getShape_() const override; - u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override; + u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) override; CapsuleShape* mShape{}; }; diff --git a/src/KingSystem/Physics/RigidBody/Shape/Cylinder/physCylinderRigidBody.cpp b/src/KingSystem/Physics/RigidBody/Shape/Cylinder/physCylinderRigidBody.cpp index b5ea8f40..48764205 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Cylinder/physCylinderRigidBody.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/Cylinder/physCylinderRigidBody.cpp @@ -64,7 +64,8 @@ const Shape* CylinderRigidBody::getShape_() const { return mShape; } -u32 CylinderRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) { +u32 CylinderRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) { masks->ignored_layers = ~mContactMask.getDirect(); masks->collision_filter_info = getCollisionFilterInfo(); masks->material_mask = getMaterialMask().getRawData(); diff --git a/src/KingSystem/Physics/RigidBody/Shape/Cylinder/physCylinderRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/Cylinder/physCylinderRigidBody.h index 26702c3e..e5cac790 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Cylinder/physCylinderRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Cylinder/physCylinderRigidBody.h @@ -30,7 +30,8 @@ public: protected: Shape* getShape_() override; const Shape* getShape_() const override; - u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override; + u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) override; private: CylinderShape* mShape; diff --git a/src/KingSystem/Physics/RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.cpp b/src/KingSystem/Physics/RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.cpp index 4b315d42..154f70e8 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.cpp @@ -58,7 +58,8 @@ const Shape* CylinderWaterRigidBody::getShape_() const { return mShape; } -u32 CylinderWaterRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) { +u32 CylinderWaterRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) { masks->ignored_layers = ~mContactMask.getDirect(); masks->collision_filter_info = getCollisionFilterInfo(); masks->material_mask = getMaterialMask().getRawData(); diff --git a/src/KingSystem/Physics/RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.h index 44850c07..cc4c8201 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/Shape/CylinderWater/physCylinderWaterRigidBody.h @@ -30,7 +30,8 @@ public: protected: Shape* getShape_() override; const Shape* getShape_() const override; - u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override; + u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) override; private: CylinderWaterShape* mShape{}; diff --git a/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.cpp b/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.cpp index ad4d64fd..3bb9c3b9 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.cpp @@ -70,7 +70,8 @@ const Shape* ListShapeRigidBody::getShape_() const { return mShape; } -u32 ListShapeRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) { +u32 ListShapeRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) { masks->ignored_layers = ~mContactMask; masks->collision_filter_info = getCollisionFilterInfo(); masks->material_mask = getMaterialMask(unk != nullptr ? int(*unk) : 0).getRawData(); diff --git a/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h index dad7141f..8eb340a1 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/Shape/List/physListShapeRigidBody.h @@ -58,7 +58,8 @@ public: protected: Shape* getShape_() override; const Shape* getShape_() const override; - u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override; + u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) override; private: ListShape* mShape{}; diff --git a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.cpp b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.cpp index 010c612d..97a3ca0c 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.cpp +++ b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.cpp @@ -55,7 +55,8 @@ const Shape* PolytopeRigidBody::getShape_() const { return mShape; } -u32 PolytopeRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) { +u32 PolytopeRigidBody::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) { masks->ignored_layers = ~mContactMask.getDirect(); masks->collision_filter_info = getCollisionFilterInfo(); masks->material_mask = getMaterialMask().getRawData(); diff --git a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.h index b5b462f8..a112435a 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Polytope/physPolytopeRigidBody.h @@ -28,7 +28,8 @@ public: protected: Shape* getShape_() override; const Shape* getShape_() const override; - u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override; + u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) override; private: PolytopeShape* mShape{}; diff --git a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h index 4b4b0eab..addaa3b9 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h @@ -22,7 +22,8 @@ public: protected: Shape* getShape_() override; const Shape* getShape_() const override; - u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override; + u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) override; private: SphereShape* mShape{}; diff --git a/src/KingSystem/Physics/RigidBody/TeraMesh/physTeraMeshRigidBody.h b/src/KingSystem/Physics/RigidBody/TeraMesh/physTeraMeshRigidBody.h index a2ae39d4..9952e3fd 100644 --- a/src/KingSystem/Physics/RigidBody/TeraMesh/physTeraMeshRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/TeraMesh/physTeraMeshRigidBody.h @@ -9,7 +9,8 @@ class TeraMeshRigidBody : public RigidBody { public: TeraMeshRigidBody(hkpRigidBody* hk_body, sead::Heap* heap); - u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override; + u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) override; }; } // namespace ksys::phys diff --git a/src/KingSystem/Physics/RigidBody/physRigidBody.h b/src/KingSystem/Physics/RigidBody/physRigidBody.h index 3f219a4e..404d79df 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBody.h @@ -523,10 +523,11 @@ public: void setEntityMotionFlag200(bool set); bool isEntityMotionFlag200On() const; -protected: // FIXME: return type - virtual u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) = 0; + virtual u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) = 0; +protected: /// Called whenever a shape update is requested. /// @return the new shape to use for the Havok rigid body or null to keep the current hkpShape virtual const hkpShape* getNewHavokShape_(); diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyFromResource.cpp b/src/KingSystem/Physics/RigidBody/physRigidBodyFromResource.cpp index a17d16b9..bb4af731 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyFromResource.cpp +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyFromResource.cpp @@ -86,7 +86,8 @@ bool RigidBodyFromResource::isMaterial(Material material) const { u32 getCollisionFilterInfoFromCollidable(u32* material_mask, u32* collision_filter_info, const hkpCollidable* collidable, const u32* unk); -u32 RigidBodyFromResource::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) { +u32 RigidBodyFromResource::getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) { masks->ignored_layers = ~mContactMask; auto* collidable = getHkBody()->getCollidable(); if (unk != nullptr) { diff --git a/src/KingSystem/Physics/RigidBody/physRigidBodyFromResource.h b/src/KingSystem/Physics/RigidBody/physRigidBodyFromResource.h index 0f109157..f9709faa 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBodyFromResource.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBodyFromResource.h @@ -17,7 +17,8 @@ public: bool isMaterial(Material material) const; float getVolume() override; - u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk) override; + u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + const sead::Vector3f& contact_point) override; protected: float updateScale_(float scale, float old_scale) override; diff --git a/src/KingSystem/Physics/System/physCollisionInfo.h b/src/KingSystem/Physics/System/physCollisionInfo.h index 7a96a2fe..dd2e3265 100644 --- a/src/KingSystem/Physics/System/physCollisionInfo.h +++ b/src/KingSystem/Physics/System/physCollisionInfo.h @@ -18,6 +18,8 @@ public: sead::BitFlag32& getLayerMask(ContactLayerType layer_type); const sead::BitFlag32& getLayerMask(ContactLayerType layer_type) const; + bool isLayerEnabled(ContactLayer layer) const; + void lock(); void unlock(); @@ -53,6 +55,11 @@ inline const sead::BitFlag32& CollisionInfoBase::getLayerMask(ContactLayerType l return mLayerMasks[int(layer_type)]; } +inline bool CollisionInfoBase::isLayerEnabled(ContactLayer layer) const { + const auto& mask = getLayerMask(getContactLayerType(layer)); + return mask.isOnBit(int(getContactLayerBaseRelativeValue(layer))); +} + inline void CollisionInfoBase::lock() { mMutex.lock(); } diff --git a/src/KingSystem/Physics/System/physContactListener.cpp b/src/KingSystem/Physics/System/physContactListener.cpp index d41ec16c..370116b7 100644 --- a/src/KingSystem/Physics/System/physContactListener.cpp +++ b/src/KingSystem/Physics/System/physContactListener.cpp @@ -1,14 +1,20 @@ #include "KingSystem/Physics/System/physContactListener.h" #include +#include #include #include +#include #include #include #include +#include #include "KingSystem/Physics/RigidBody/physRigidBody.h" #include "KingSystem/Physics/System/physContactLayerCollisionInfo.h" #include "KingSystem/Physics/System/physContactMgr.h" +#include "KingSystem/Physics/System/physGroupFilter.h" +#include "KingSystem/Physics/System/physLayerContactPointInfo.h" #include "KingSystem/Physics/System/physSystem.h" +#include "KingSystem/Physics/physConversions.h" namespace ksys::phys { @@ -25,9 +31,9 @@ ContactListener::~ContactListener() = default; void ContactListener::init(sead::Heap* heap) { // NOLINTBEGIN(cppcoreguidelines-narrowing-conversions) - _20.allocBufferAssert(mLayerCount, nullptr); + mTrackedContactPointLayers.allocBufferAssert(mLayerCount, nullptr); for (u32 i = 0; i < mLayerCount; ++i) { - _20[i].allocBufferAssert(mLayerCount, nullptr); + mTrackedContactPointLayers[i].allocBufferAssert(mLayerCount, nullptr); } mCollisionInfoPerLayerPair.allocBufferAssert(mLayerCount, nullptr); @@ -45,13 +51,13 @@ void ContactListener::init(sead::Heap* heap) { } // NOLINTEND(cppcoreguidelines-narrowing-conversions) - _48 = sead::Mathu::roundUpPow2(mLayerCount * mLayerCount, 0x20); - _40 = ::operator new[](_48, heap, 0x20); + mTrackedLayersBufferSize = sead::Mathu::roundUpPow2(mLayerCount * mLayerCount, 0x20); + mTrackedLayers = new (heap, 0x20) u8[mTrackedLayersBufferSize]; clearTable(); } void ContactListener::clearTable() { - sead::MemUtil::fillZero(_40, _48); + sead::MemUtil::fillZero(mTrackedLayers, mTrackedLayersBufferSize); } void ContactListener::collisionAddedCallback(const hkpCollisionEvent& event) { @@ -88,7 +94,98 @@ void ContactListener::contactPointCallback(const hkpContactPointEvent& event) { } else if (event.m_type == hkpContactPointEvent::TYPE_MANIFOLD) { manifoldContactPointCallback(event, body_a, body_b); } else { - regularContactPointCallback(event, body_a, body_b); + regularContactPointCallback(event, body_a, body_b, nullptr); + } +} + +bool ContactListener::manifoldContactPointCallback(const hkpContactPointEvent& event, + RigidBody* body_a, RigidBody* body_b) { + auto* filter = System::instance()->getGroupFilter(mLayerType); + + RigidBody::CollisionMasks masks_a, masks_b; + sead::Vector3f contact_point_pos, position, normal; + ContactPointInfo::Event my_event; + + storeToVec3(&contact_point_pos, event.m_contactPoint->getPosition()); + + body_a->getCollisionMasks(&masks_a, event.getShapeKeys(0), contact_point_pos); + body_b->getCollisionMasks(&masks_b, event.getShapeKeys(1), contact_point_pos); + + const auto layer_a = filter->getCollisionFilterInfoLayer(masks_a.collision_filter_info); + const auto layer_b = filter->getCollisionFilterInfoLayer(masks_b.collision_filter_info); + + if (!characterControlContactPointCallback(masks_a.ignored_layers, masks_b.ignored_layers, + body_a, body_b, layer_a, layer_b, event)) { + return false; + } + + if (auto* info = body_a->getContactPointInfo(); info && info->getContactCallback()) { + storeToVec3(&position, event.m_contactPoint->getPosition()); + storeToVec3(&normal, event.m_contactPoint->getSeparatingNormal()); + normal *= -1; + my_event.body = body_b; + my_event.position = &position; + my_event.separating_normal = &normal; + my_event.collision_masks = &masks_b; + + auto disable = ContactPointInfo::ShouldDisableContact::No; + + info->getContactCallback()->invoke(&disable, my_event); + + if (disable == ContactPointInfo::ShouldDisableContact::Yes) { + event.m_contactPointProperties->m_flags |= + hkpContactPointProperties::CONTACT_IS_DISABLED; + return false; + } + } + + if (auto* info = body_b->getContactPointInfo(); info && info->getContactCallback()) { + storeToVec3(&position, event.m_contactPoint->getPosition()); + storeToVec3(&normal, event.m_contactPoint->getSeparatingNormal()); + my_event.body = body_a; + my_event.position = &position; + my_event.separating_normal = &normal; + my_event.collision_masks = &masks_a; + + auto disable = ContactPointInfo::ShouldDisableContact::No; + + info->getContactCallback()->invoke(&disable, my_event); + + if (disable == ContactPointInfo::ShouldDisableContact::Yes) { + event.m_contactPointProperties->m_flags |= + hkpContactPointProperties::CONTACT_IS_DISABLED; + return false; + } + } + + return true; +} + +void ContactListener::handleCollisionAdded(const hkpCollisionEvent& event, RigidBody* body_a, + RigidBody* body_b) { + registerForEndOfStepContactPointCallbacks(event); + + const auto layer_a = body_a->getContactLayer(); + const auto layer_b = body_b->getContactLayer(); + + if (body_a->getCollisionInfo() && body_a->getCollisionInfo()->isLayerEnabled(layer_b)) + mMgr->x_17(body_a->getCollisionInfo(), body_a, body_b); + + if (body_b->getCollisionInfo() && body_b->getCollisionInfo()->isLayerEnabled(layer_a)) + mMgr->x_17(body_b->getCollisionInfo(), body_b, body_a); + + const auto i = int(layer_a - mLayerBase); + const auto j = int(layer_b - mLayerBase); + if (areContactsTrackedForLayerPair(i, j)) { + auto* info = getContactLayerCollisionInfo(i, j); + if (body_a->isFlag8Set() && body_b->isFlag8Set()) { + const auto layer_a_ = int(layer_a); + const auto tracked_layer = info->getLayer(); + const bool body_a_first = layer_a_ == tracked_layer; + auto* body1 = body_a_first ? body_a : body_b; + auto* body2 = body_a_first ? body_b : body_a; + mMgr->x_18(info, body1, body2); + } } } @@ -99,15 +196,15 @@ void ContactListener::handleCollisionRemoved(const hkpCollisionEvent& event, Rig const auto layer_a = body_a->getContactLayer(); const auto layer_b = body_b->getContactLayer(); - if (auto* unk = body_a->getCollisionInfo()) - mMgr->x_19(unk, body_a, body_b); + if (auto* info = body_a->getCollisionInfo()) + mMgr->x_19(info, body_a, body_b); - if (auto* unk = body_b->getCollisionInfo()) - mMgr->x_19(unk, body_b, body_a); + if (auto* info = body_b->getCollisionInfo()) + mMgr->x_19(info, body_b, body_a); const auto i = int(layer_a - mLayerBase); const auto j = int(layer_b - mLayerBase); - ContactLayerCollisionInfo* info = mCollisionInfoPerLayerPair[i][j]; + auto* info = getContactLayerCollisionInfo(i, j); if (!info->getList().isEmpty()) { const auto layer_a_ = int(layer_a); const auto tracked_layer = info->getLayer(); @@ -118,4 +215,91 @@ void ContactListener::handleCollisionRemoved(const hkpCollisionEvent& event, Rig } } +bool ContactListener::areContactsTrackedForLayerPair(u32 rlayer_a, u32 rlayer_b) const { + return mTrackedLayers[mLayerCount * rlayer_a + rlayer_b]; +} + +ContactLayerCollisionInfo* ContactListener::getContactLayerCollisionInfo(u32 rlayer_a, + u32 rlayer_b) { + return mCollisionInfoPerLayerPair[int(rlayer_a)][int(rlayer_b)]; +} + +ContactLayerCollisionInfo* ContactListener::trackLayerPair(ContactLayer layer_a, + ContactLayer layer_b) { + const auto [i, j] = convertToRelativeLayer(layer_a, layer_b); + (&mTrackedLayers[mLayerCount * i])[j] = true; + (&mTrackedLayers[mLayerCount * j])[i] = true; + return mCollisionInfoPerLayerPair[i][j]; +} + +void ContactListener::addLayerPairForContactPointInfo(LayerContactPointInfo* info, + ContactLayer layer1, ContactLayer layer2, + bool enabled) { + auto lock = sead::makeScopedLock(mCS); + const auto [i, j] = convertToRelativeLayer(layer1, layer2); + + const auto set = [&](TrackedContactPointLayer* entry) { + if (!entry) + return; + entry->info = info; + entry->layer = layer1; + entry->enabled = enabled; + }; + + auto& row_i = mTrackedContactPointLayers[i]; + auto& row_j = mTrackedContactPointLayers[j]; + set(row_i[j].emplaceBack()); + set(row_j[i].emplaceBack()); +} + +void ContactListener::removeLayerPairsForContactPointInfo(LayerContactPointInfo* info) { + auto lock = sead::makeScopedLock(mCS); + for (int i = 0; i < info->getLayerEntries().size(); ++i) { + auto* entry = info->getLayerEntries()[i]; + removeLayerPairForContactPointInfo(info, entry->layer1, entry->layer2); + } +} + +// NON_MATCHING: enum-to-int conversion (stp should be 2 str), reordering, branching +void ContactListener::removeLayerPairForContactPointInfo(LayerContactPointInfo* info, + ContactLayer layer1, ContactLayer layer2) { + const auto [i, j] = convertToRelativeLayer(layer1, layer2); + auto& row_i = mTrackedContactPointLayers[i]; + auto& row_j = mTrackedContactPointLayers[j]; + auto& ij = row_i[j]; + auto& ji = row_j[i]; + + for (int idx = 0; idx < ij.size(); ++idx) { + if (ij[idx]->info == info) { + ij.erase(idx); + break; + } + } + + for (int idx = 0; idx < ji.size(); ++idx) { + if (ji[idx]->info == info) { + ji.erase(idx); + break; + } + } +} + +void ContactListener::registerRigidBody(RigidBody* body) { + const u32 rlayer = body->getContactLayer() - mLayerBase; + auto& column = mCollisionInfoPerLayerPair[int(rlayer)]; + for (u32 i = 0; i < mLayerCount; ++i) { + ContactLayerCollisionInfo* info = column[int(i)]; + mMgr->x_21(info, body); + } +} + +bool ContactListener::characterControlContactPointCallback(u32 ignored_layers_a, + u32 ignored_layers_b, RigidBody* body_a, + RigidBody* body_b, ContactLayer layer_a, + ContactLayer layer_b, + const hkpContactPointEvent& event) { + event.m_contactPointProperties->m_flags |= hkpContactPointProperties::CONTACT_IS_DISABLED; + return false; +} + } // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physContactListener.h b/src/KingSystem/Physics/System/physContactListener.h index c64090fd..66c99616 100644 --- a/src/KingSystem/Physics/System/physContactListener.h +++ b/src/KingSystem/Physics/System/physContactListener.h @@ -6,12 +6,15 @@ #include #include #include +#include #include "KingSystem/Physics/physDefines.h" +#include "KingSystem/Physics/physMaterialMask.h" namespace ksys::phys { class ContactLayerCollisionInfo; class ContactMgr; +class LayerContactPointInfo; class RigidBody; class ContactListener : public hkpContactListener, public sead::hostio::Node { @@ -23,6 +26,18 @@ public: void init(sead::Heap* heap); void clearTable(); + bool areContactsTrackedForLayerPair(u32 rlayer_a, u32 rlayer_b) const; + ContactLayerCollisionInfo* trackLayerPair(ContactLayer layer_a, ContactLayer layer_b); + ContactLayerCollisionInfo* getContactLayerCollisionInfo(u32 rlayer_a, u32 rlayer_b); + + void addLayerPairForContactPointInfo(LayerContactPointInfo* info, ContactLayer layer1, + ContactLayer layer2, bool enabled); + void removeLayerPairsForContactPointInfo(LayerContactPointInfo* info); + void removeLayerPairForContactPointInfo(LayerContactPointInfo* info, ContactLayer layer1, + ContactLayer layer2); + + void registerRigidBody(RigidBody* body); + void contactPointCallback(const hkpContactPointEvent& event) override; void collisionAddedCallback(const hkpCollisionEvent& event) override; void collisionRemovedCallback(const hkpCollisionEvent& event) override; @@ -31,7 +46,7 @@ public: void contactProcessCallback(hkpContactProcessEvent& event) override {} protected: - virtual void characterControlContactPointCallback(u32 ignored_layers_a, u32 ignored_layers_b, + virtual bool characterControlContactPointCallback(u32 ignored_layers_a, u32 ignored_layers_b, RigidBody* body_a, RigidBody* body_b, ContactLayer layer_a, ContactLayer layer_b, const hkpContactPointEvent& event); @@ -44,27 +59,35 @@ protected: void handleCollisionRemoved(const hkpCollisionEvent& event, RigidBody* body_a, RigidBody* body_b); - virtual void manifoldContactPointCallback(const hkpContactPointEvent& event, RigidBody* body_a, + virtual bool 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); + /// @param out_material_masks [Optional] Pass this to get the materials of the rigid bodies. + virtual bool regularContactPointCallback(const hkpContactPointEvent& event, RigidBody* body_a, + RigidBody* body_b, + sead::SafeArray* out_material_masks); virtual u32 m15() { return 0; } + std::pair convertToRelativeLayer(ContactLayer layer1, ContactLayer layer2) const { + return {layer1 - int(mLayerBase), layer2 - int(mLayerBase)}; + } + private: - struct Unk1 { - void* _0; - void* _8; + struct TrackedContactPointLayer { + LayerContactPointInfo* info; + ContactLayer layer; + bool enabled; }; ContactMgr* mMgr{}; ContactLayerType mLayerType{}; u32 mLayerBase{}; - sead::Buffer>> _20; + sead::Buffer>> + mTrackedContactPointLayers; sead::Buffer> mCollisionInfoPerLayerPair; - void* _40{}; - u32 _48{}; + u8* mTrackedLayers{}; + u32 mTrackedLayersBufferSize{}; u32 mLayerCount{}; sead::CriticalSection mCS; u16 _90{}; diff --git a/src/KingSystem/Physics/System/physContactMgr.h b/src/KingSystem/Physics/System/physContactMgr.h index 02e0c88c..bd0ce4be 100644 --- a/src/KingSystem/Physics/System/physContactMgr.h +++ b/src/KingSystem/Physics/System/physContactMgr.h @@ -22,8 +22,10 @@ class Heap; namespace ksys::phys { -class ContactLayerCollisionInfo; enum class IsIndoorStage; + +class CollisionInfo; +class ContactLayerCollisionInfo; class ContactPointInfoBase; class RigidBody; class ContactPointInfo; @@ -89,13 +91,15 @@ public: void freeContactPointInfo(ContactPointInfoBase* info); // 0x0000007100fb3744 - void x_17(void* unk, RigidBody* body_a, RigidBody* body_b); + void x_17(CollisionInfo* info, RigidBody* body_a, RigidBody* body_b); // 0x0000007100fb37d4 void x_18(ContactLayerCollisionInfo* info, RigidBody* body_a, RigidBody* body_b); // 0x0000007100fb3854 - void x_19(void* unk, RigidBody* body_a, RigidBody* body_b); + void x_19(CollisionInfo* info, RigidBody* body_a, RigidBody* body_b); // 0x0000007100fb3938 void x_20(ContactLayerCollisionInfo* info, RigidBody* body_a, RigidBody* body_b); + // 0x0000007100fb3a2c + void x_21(ContactLayerCollisionInfo* info, RigidBody* body); private: void doLoadContactInfoTable(agl::utl::ResParameterArchive archive, ContactLayerType type, diff --git a/src/KingSystem/Physics/System/physContactPointInfo.h b/src/KingSystem/Physics/System/physContactPointInfo.h index 282eb90d..763fa92c 100644 --- a/src/KingSystem/Physics/System/physContactPointInfo.h +++ b/src/KingSystem/Physics/System/physContactPointInfo.h @@ -5,10 +5,13 @@ #include #include #include +#include #include +#include #include #include #include +#include "KingSystem/Physics/RigidBody/physRigidBody.h" #include "KingSystem/Utils/Types.h" namespace ksys::phys { @@ -40,6 +43,20 @@ protected: class ContactPointInfo : public ContactPointInfoBase { public: + enum class ShouldDisableContact : bool { + Yes = true, + No = false, + }; + + struct Event { + RigidBody* body; + const sead::Vector3f* position; + const sead::Vector3f* separating_normal; + const RigidBody::CollisionMasks* collision_masks; + }; + + using ContactCallback = sead::IDelegate2R; + static ContactPointInfo* make(sead::Heap* heap, int num, const sead::SafeString& name, int a, int b, int c); static void free(ContactPointInfo* instance); @@ -49,9 +66,12 @@ public: void freePoints() override; virtual void allocPoints(sead::Heap* heap, int num); + ContactCallback* getContactCallback() const { return mContactCallback; } + void setContactCallback(ContactCallback* cb) { mContactCallback = cb; } + private: sead::Buffer mPoints{}; - void* _58{}; + ContactCallback* mContactCallback{}; }; KSYS_CHECK_SIZE_NX150(ContactPointInfo, 0x60); diff --git a/src/KingSystem/Physics/System/physLayerContactPointInfo.h b/src/KingSystem/Physics/System/physLayerContactPointInfo.h index 953458f6..0b843de2 100644 --- a/src/KingSystem/Physics/System/physLayerContactPointInfo.h +++ b/src/KingSystem/Physics/System/physLayerContactPointInfo.h @@ -16,6 +16,12 @@ class LayerContactPointInfo : public ContactPointInfoBase { public: using Points = sead::Buffer; + struct LayerEntry { + ContactLayer layer1; + ContactLayer layer2; + bool enabled; + }; + class IteratorEnd; class Iterator { @@ -100,13 +106,10 @@ public: auto begin() const { return Iterator(mPoints, _18); } auto end() const { return IteratorEnd(mPoints, _18); } -private: - struct LayerEntry { - ContactLayer layer1; - ContactLayer layer2; - bool enabled; - }; + sead::ObjArray& getLayerEntries() { return mLayerEntries; } + const sead::ObjArray& getLayerEntries() const { return mLayerEntries; } +private: Points mPoints{}; sead::ObjArray mLayerEntries; ContactLayerType mLayerType = ContactLayerType::Invalid; diff --git a/src/KingSystem/Physics/System/physSystem.cpp b/src/KingSystem/Physics/System/physSystem.cpp index 2efa20ae..bfad9d89 100644 --- a/src/KingSystem/Physics/System/physSystem.cpp +++ b/src/KingSystem/Physics/System/physSystem.cpp @@ -58,8 +58,8 @@ void System::freeContactPointInfo(ContactPointInfo* info) const { } LayerContactPointInfo* System::allocLayerContactPointInfo(sead::Heap* heap, int num, int num2, - const sead::SafeString& name, int a, int b, - int c) const { + const sead::SafeString& name, int a, + int b, int c) const { return mContactMgr->allocContactPointsEx(heap, num, num2, name, a, b, c); }