From 0c3df3ed97101d91df6bfa7522e268f35885e58b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 14 Mar 2022 01:41:28 +0100 Subject: [PATCH] ksys/phys: Add ShapeCast --- data/uking_functions.csv | 76 +++--- lib/hkStubs/CMakeLists.txt | 6 + .../Collide/Agent/Collidable/hkpCdPoint.h | 48 ++++ .../Collide/Agent/hkpProcessCollisionInput.h | 21 ++ .../Query/CastUtil/hkpLinearCastInput.h | 11 + .../PointCollector/hkpAllCdPointCollector.h | 54 ++++ .../hkpClosestCdPointCollector.h | 54 ++++ .../Collector/PointCollector/hkpRootCdPoint.h | 35 +++ .../Physics2012/Dynamics/World/hkpWorld.h | 5 + src/KingSystem/Physics/CMakeLists.txt | 4 + .../Shape/Sphere/physSphereRigidBody.h | 2 + .../Physics/RigidBody/physRigidBody.h | 2 +- .../Physics/System/physClosestPointQuery.cpp | 6 +- .../Physics/System/physContactListener.cpp | 10 +- .../Physics/System/physContactPointInfo.h | 14 + .../Physics/System/physShapeCast.cpp | 256 ++++++++++++++++++ src/KingSystem/Physics/System/physShapeCast.h | 100 +++++++ .../Physics/System/physShapeCastWithInfo.cpp | 94 +++++++ .../Physics/System/physShapeCastWithInfo.h | 52 ++++ src/KingSystem/Physics/System/physSystem.h | 20 +- 20 files changed, 815 insertions(+), 55 deletions(-) create mode 100644 lib/hkStubs/Havok/Physics2012/Collide/Agent/Collidable/hkpCdPoint.h create mode 100644 lib/hkStubs/Havok/Physics2012/Collide/Agent/hkpProcessCollisionInput.h create mode 100644 lib/hkStubs/Havok/Physics2012/Collide/Query/CastUtil/hkpLinearCastInput.h create mode 100644 lib/hkStubs/Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpAllCdPointCollector.h create mode 100644 lib/hkStubs/Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpClosestCdPointCollector.h create mode 100644 lib/hkStubs/Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpRootCdPoint.h create mode 100644 src/KingSystem/Physics/System/physShapeCast.cpp create mode 100644 src/KingSystem/Physics/System/physShapeCast.h create mode 100644 src/KingSystem/Physics/System/physShapeCastWithInfo.cpp create mode 100644 src/KingSystem/Physics/System/physShapeCastWithInfo.h diff --git a/data/uking_functions.csv b/data/uking_functions.csv index 17e520b9..219485fb 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -48306,7 +48306,7 @@ Address,Quality,Size,Name 0x000000710079482c,U,000400, 0x00000071007949bc,U,001556, 0x0000007100794fd0,U,000016, -0x0000007100794fe0,U,000004,nullsub_2388 +0x0000007100794fe0,U,000004,_ZN4ksys4phys16LayerMaskBuilderD2Ev 0x0000007100794fe4,U,000992,CameraPhysCollisionCheck 0x00000071007953c4,U,000004,nullsub_2389 0x00000071007953c8,U,000076, @@ -48376,7 +48376,7 @@ Address,Quality,Size,Name 0x0000007100799d10,U,000008, 0x0000007100799d18,U,000008, 0x0000007100799d20,U,000008, -0x0000007100799d28,U,000004,j__ZdlPv_323 +0x0000007100799d28,U,000004,_ZN4ksys4phys16LayerMaskBuilderD0Ev 0x0000007100799d2c,U,000052, 0x0000007100799d60,U,000092, 0x0000007100799dbc,O,000008,_ZNK4sead11IDelegate1RIPvbE9isNoDummyEv @@ -84161,42 +84161,42 @@ Address,Quality,Size,Name 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 -0x0000007100fc87e0,U,000028, -0x0000007100fc87fc,U,000068, -0x0000007100fc8840,U,000068, -0x0000007100fc8884,U,000052, -0x0000007100fc88b8,U,000064, -0x0000007100fc88f8,U,000076, -0x0000007100fc8944,U,000040, -0x0000007100fc896c,U,000004,nullsub_4251 -0x0000007100fc8970,U,000588, -0x0000007100fc8bbc,U,000560, -0x0000007100fc8dec,U,000100, -0x0000007100fc8e50,U,000004,nullsub_4252 -0x0000007100fc8e54,U,000080, -0x0000007100fc8ea4,U,000040, -0x0000007100fc8ecc,U,000476, -0x0000007100fc90a8,U,000112, -0x0000007100fc9118,U,000092, -0x0000007100fc9174,U,000124, -0x0000007100fc91f0,U,000052, -0x0000007100fc9224,U,000072, -0x0000007100fc926c,U,000080, -0x0000007100fc92bc,U,000456, -0x0000007100fc9484,U,000316, -0x0000007100fc95c0,U,000536, -0x0000007100fc97d8,U,000124, -0x0000007100fc9854,U,000132, -0x0000007100fc98d8,U,000040, -0x0000007100fc9900,U,000204, -0x0000007100fc99cc,U,000092, -0x0000007100fc9a28,U,000288, -0x0000007100fc9b48,U,000092, -0x0000007100fc9ba4,U,000140, -0x0000007100fc9c30,U,000140, +0x0000007100fc872c,O,000172,_ZN4ksys4phys9ShapeCastC2EPNS0_9RigidBodyEPNS0_21QueryContactPointInfoENS1_4ModeE +0x0000007100fc87d8,O,000004,_ZN4ksys4phys9ShapeCastD1Ev +0x0000007100fc87dc,O,000004,_ZN4ksys4phys9ShapeCastD0Ev +0x0000007100fc87e0,O,000028,_ZN4ksys4phys9ShapeCast5resetEv +0x0000007100fc87fc,O,000068,_ZN4ksys4phys9ShapeCast11setRotationERKN4sead8Matrix33IfEE +0x0000007100fc8840,O,000068,_ZN4ksys4phys9ShapeCast11setRotationERKN4sead8Matrix34IfEE +0x0000007100fc8884,O,000052,_ZN4ksys4phys9ShapeCast14setStartAndEndERKN4sead7Vector3IfEES6_ +0x0000007100fc88b8,O,000064,_ZN4ksys4phys9ShapeCast23setStartAndDisplacementERKN4sead7Vector3IfEES6_ +0x0000007100fc88f8,O,000076,_ZN4ksys4phys9ShapeCast29setStartAndDisplacementScaledERKN4sead7Vector3IfEES6_f +0x0000007100fc8944,O,000040,_ZN4ksys4phys9ShapeCast13setLayerMasksERKNS0_16LayerMaskBuilderE +0x0000007100fc896c,O,000004,_ZN4ksys4phys9ShapeCast9setColorsERKN4sead7Color4fES5_S5_b +0x0000007100fc8970,M,000588,_ZN4ksys4phys9ShapeCast14doExecuteQueryER19hkpCdPointCollectorP22hkpAllCdPointCollectorNS1_17WeldClosestPointsENS0_16OnlyLockIfNeededE +0x0000007100fc8bbc,O,000560,_ZN4ksys4phys9ShapeCast20registerContactPointERK14hkpRootCdPointPNS0_9RigidBodyENS1_13ClampDistanceE +0x0000007100fc8dec,O,000100,_ZN4ksys4phys31FilteredClosestCdPointCollectorC1EPNS0_9RigidBodyEPNS0_21QueryContactPointInfoE +0x0000007100fc8e50,O,000004,_ZN4ksys4phys31FilteredClosestCdPointCollectorD1Ev +0x0000007100fc8e54,m,000080,_ZN4ksys4phys31FilteredClosestCdPointCollectorD0Ev +0x0000007100fc8ea4,O,000040,_ZN4ksys4phys31FilteredClosestCdPointCollector5resetEv +0x0000007100fc8ecc,O,000476,_ZN4ksys4phys31FilteredClosestCdPointCollector10addCdPointERK10hkpCdPoint +0x0000007100fc90a8,O,000112,_ZNK4ksys4phys9ShapeCast27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100fc9118,O,000092,_ZNK4ksys4phys9ShapeCast18getRuntimeTypeInfoEv +0x0000007100fc9174,O,000124,_ZN4ksys4phys17ShapeCastWithInfoC1EPNS0_9RigidBodyEiNS0_9ShapeCast4ModeERKN4sead14SafeStringBaseIcEENS0_11LowPriorityE +0x0000007100fc91f0,O,000052,_ZN4ksys4phys17ShapeCastWithInfoC1EPNS0_9RigidBodyEPNS0_21QueryContactPointInfoENS0_9ShapeCast4ModeE +0x0000007100fc9224,O,000072,_ZN4ksys4phys17ShapeCastWithInfoD1Ev +0x0000007100fc926c,O,000080,_ZN4ksys4phys17ShapeCastWithInfoD0Ev +0x0000007100fc92bc,m,000456,_ZN4ksys4phys17ShapeCastWithInfo12executeQueryENS0_9ShapeCast17WeldClosestPointsE +0x0000007100fc9484,O,000316,_ZN4ksys4phys17ShapeCastWithInfo6doCastERK18hkpLinearCastInputR19hkpCdPointCollectorPS5_ +0x0000007100fc95c0,O,000536,_ZN4ksys4phys10SphereCastC1ENS0_12ContactLayerENS0_9GroundHitEPNS0_18SystemGroupHandlerEiNS0_9ShapeCast4ModeERKN4sead7Vector3IfEEfRKNS8_14SafeStringBaseIcEENS0_11LowPriorityE +0x0000007100fc97d8,O,000124,_ZN4ksys4phys10SphereCastD1Ev +0x0000007100fc9854,O,000132,_ZN4ksys4phys10SphereCastD0Ev +0x0000007100fc98d8,O,000040,_ZN4ksys4phys10SphereCast9setRadiusEf +0x0000007100fc9900,O,000204,_ZNK4ksys4phys17ShapeCastWithInfo27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100fc99cc,O,000092,_ZNK4ksys4phys17ShapeCastWithInfo18getRuntimeTypeInfoEv +0x0000007100fc9a28,O,000288,_ZNK4ksys4phys10SphereCast27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100fc9b48,O,000092,_ZNK4ksys4phys10SphereCast18getRuntimeTypeInfoEv +0x0000007100fc9ba4,O,000140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys4phys9ShapeCastEE9isDerivedEPKNS0_9InterfaceE +0x0000007100fc9c30,O,000140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys4phys17ShapeCastWithInfoEE9isDerivedEPKNS0_9InterfaceE 0x0000007100fc9cbc,O,000208,_ZN4ksys4phys14StaticCompoundC1Ev 0x0000007100fc9d8c,U,000352,ResourceHksc::dtor 0x0000007100fc9eec,U,000008, diff --git a/lib/hkStubs/CMakeLists.txt b/lib/hkStubs/CMakeLists.txt index a1e9d62a..6bcca644 100644 --- a/lib/hkStubs/CMakeLists.txt +++ b/lib/hkStubs/CMakeLists.txt @@ -89,7 +89,9 @@ add_library(hkStubs OBJECT Havok/Physics2012/Collide/Agent/hkpCollisionInput.h Havok/Physics2012/Collide/Agent/hkpCollisionQualityInfo.h + Havok/Physics2012/Collide/Agent/hkpProcessCollisionInput.h Havok/Physics2012/Collide/Agent/Collidable/hkpCdBody.h + Havok/Physics2012/Collide/Agent/Collidable/hkpCdPoint.h Havok/Physics2012/Collide/Agent/Collidable/hkpCollidable.h Havok/Physics2012/Collide/Agent/Collidable/hkpCollidableQualityType.h Havok/Physics2012/Collide/Agent/ContactMgr/hkpContactMgr.h @@ -110,7 +112,11 @@ add_library(hkStubs OBJECT Havok/Physics2012/Collide/Filter/Group/hkpGroupFilter.cpp Havok/Physics2012/Collide/Filter/Group/hkpGroupFilter.h Havok/Physics2012/Collide/Query/hkpRayHitCollector.h + Havok/Physics2012/Collide/Query/CastUtil/hkpLinearCastInput.h Havok/Physics2012/Collide/Query/CastUtil/hkpWorldRayCastInput.h + Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpAllCdPointCollector.h + Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpClosestCdPointCollector.h + Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpRootCdPoint.h Havok/Physics2012/Collide/Shape/hkpShape.h Havok/Physics2012/Collide/Shape/hkpShapeBase.h Havok/Physics2012/Collide/Shape/hkpShapeBuffer.h diff --git a/lib/hkStubs/Havok/Physics2012/Collide/Agent/Collidable/hkpCdPoint.h b/lib/hkStubs/Havok/Physics2012/Collide/Agent/Collidable/hkpCdPoint.h new file mode 100644 index 00000000..0d4be33b --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Collide/Agent/Collidable/hkpCdPoint.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include + +class hkpCdBody; + +struct hkpCdPoint { + HK_DECLARE_CLASS_ALLOCATOR(hkpCdPoint) + + hkpCdPoint(const hkpCdBody& a, const hkpCdBody& b) : m_cdBodyA(a), m_cdBodyB(b) {} + hkpCdPoint(const hkpCdBody& a, const hkpCdBody& b, const hkContactPoint& cp) + : m_contact(cp), m_cdBodyA(a), m_cdBodyB(b) { + m_unweldedNormal = cp.getNormal(); + } + + const hkContactPoint& getContact() const { return m_contact; } + + void setContact(const hkContactPoint& cp) { + m_contact = cp; + m_unweldedNormal = cp.getNormal(); + } + + void setContact(hkVector4Parameter pos, hkVector4Parameter norm, hkReal d) { + m_contact.set(pos, norm, d); + m_unweldedNormal = norm; + } + + void setContact(hkVector4Parameter pos, hkVector4Parameter norm, + hkVector4Parameter unweldedNorm, hkReal d) { + m_contact.set(pos, norm, d); + m_unweldedNormal = unweldedNorm; + } + + void setContactDistance(hkReal d) { m_contact.setDistance(d); } + void setContactNormal(hkVector4Parameter norm) { m_contact.setNormalOnly(norm); } + void setContactDistance(hkSimdRealParameter d) { m_contact.setDistanceSimdReal(d); } + void setUnweldedNormal(hkVector4Parameter norm) { m_unweldedNormal = norm; } + const hkVector4& getUnweldedNormal() const { return m_unweldedNormal; } + +protected: + hkContactPoint m_contact; + hkVector4 m_unweldedNormal; + +public: + const hkpCdBody& m_cdBodyA; + const hkpCdBody& m_cdBodyB; +}; diff --git a/lib/hkStubs/Havok/Physics2012/Collide/Agent/hkpProcessCollisionInput.h b/lib/hkStubs/Havok/Physics2012/Collide/Agent/hkpProcessCollisionInput.h new file mode 100644 index 00000000..e4851c25 --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Collide/Agent/hkpProcessCollisionInput.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include +#include + +struct hkpAgent1nSector; +struct hkpCollisionAgentConfig; +struct hkpCollisionQualityInfo; + +struct hkpProcessCollisionInput : hkpCollisionInput { + HK_DECLARE_CLASS_ALLOCATOR(hkpProcessCollisionInput) + + hkStepInfo m_stepInfo; + mutable hkpCollisionQualityInfo* m_collisionQualityInfo; + mutable hkpAgent1nSector* m_spareAgentSector; + void* m_dynamicsInfo; + hkBool m_enableDeprecatedWelding; + hkBool m_allowToSkipConfirmedCallbacks; + hkpCollisionAgentConfig* m_config; +}; diff --git a/lib/hkStubs/Havok/Physics2012/Collide/Query/CastUtil/hkpLinearCastInput.h b/lib/hkStubs/Havok/Physics2012/Collide/Query/CastUtil/hkpLinearCastInput.h new file mode 100644 index 00000000..9047ca78 --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Collide/Query/CastUtil/hkpLinearCastInput.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +struct hkpLinearCastInput { + HK_DECLARE_CLASS_ALLOCATOR(hkpLinearCastInput) + + hkVector4 m_to; + hkReal m_maxExtraPenetration = HK_REAL_EPSILON; + hkReal m_startPointTolerance = HK_REAL_EPSILON; +}; diff --git a/lib/hkStubs/Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpAllCdPointCollector.h b/lib/hkStubs/Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpAllCdPointCollector.h new file mode 100644 index 00000000..61762eed --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpAllCdPointCollector.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include +#include + +class hkpAllCdPointCollector : public hkpCdPointCollector { +public: + HK_DECLARE_CLASS_ALLOCATOR(hkpAllCdPointCollector) + + inline hkpAllCdPointCollector(); + inline ~hkpAllCdPointCollector() override; + inline void reset() override; + + inline const hkArray& getHits() const; + inline hkArray& getHits(); + + inline int getNumHits() const; + inline hkBool hasHit() const; + + void sortHits(); + + void addCdPoint(const hkpCdPoint& event) override; + +protected: + hkInplaceArray m_hits; +}; + +inline hkpAllCdPointCollector::hkpAllCdPointCollector() { + reset(); +} + +inline hkpAllCdPointCollector::~hkpAllCdPointCollector() = default; + +inline void hkpAllCdPointCollector::reset() { + m_hits.clear(); + hkpCdPointCollector::reset(); +} + +inline const hkArray& hkpAllCdPointCollector::getHits() const { + return m_hits; +} + +inline hkArray& hkpAllCdPointCollector::getHits() { + return m_hits; +} + +inline int hkpAllCdPointCollector::getNumHits() const { + return m_hits.getSize(); +} + +inline hkBool hkpAllCdPointCollector::hasHit() const { + return getNumHits() > 0; +} diff --git a/lib/hkStubs/Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpClosestCdPointCollector.h b/lib/hkStubs/Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpClosestCdPointCollector.h new file mode 100644 index 00000000..4be96c07 --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpClosestCdPointCollector.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include + +class hkpClosestCdPointCollector : public hkpCdPointCollector { +public: + HK_DECLARE_CLASS_ALLOCATOR(hkpClosestCdPointCollector) + + inline hkpClosestCdPointCollector(); + inline ~hkpClosestCdPointCollector() override; + + inline void reset() override; + + inline hkBool hasHit() const; + inline const hkpRootCdPoint& getHit() const; + inline const hkContactPoint& getHitContact() const; + + inline const hkVector4& getUnweldedNormal() const; + +protected: + void addCdPoint(const hkpCdPoint& pointInfo) override; + + hkpRootCdPoint m_hitPoint; + hkVector4 m_unweldedNormal; +}; + +inline hkpClosestCdPointCollector::hkpClosestCdPointCollector() { + reset(); +} + +inline hkpClosestCdPointCollector::~hkpClosestCdPointCollector() = default; + +inline void hkpClosestCdPointCollector::reset() { + m_hitPoint.m_rootCollidableA = nullptr; + m_hitPoint.m_contact.setDistanceSimdReal(hkSimdReal::getConstant()); + hkpCdPointCollector::reset(); +} + +inline hkBool hkpClosestCdPointCollector::hasHit() const { + return m_hitPoint.m_rootCollidableA != nullptr; +} + +inline const hkpRootCdPoint& hkpClosestCdPointCollector::getHit() const { + return m_hitPoint; +} + +inline const hkContactPoint& hkpClosestCdPointCollector::getHitContact() const { + return m_hitPoint.getContact(); +} + +inline const hkVector4& hkpClosestCdPointCollector::getUnweldedNormal() const { + return m_unweldedNormal; +} diff --git a/lib/hkStubs/Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpRootCdPoint.h b/lib/hkStubs/Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpRootCdPoint.h new file mode 100644 index 00000000..787efc70 --- /dev/null +++ b/lib/hkStubs/Havok/Physics2012/Collide/Query/Collector/PointCollector/hkpRootCdPoint.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include + +class hkpCollidable; + +struct hkpRootCdPoint { + HK_DECLARE_CLASS_ALLOCATOR(hkpRootCdPoint) + + hkBool32 operator<(const hkpRootCdPoint& b) const { + return m_contact.getDistanceSimdReal().isLess(b.m_contact.getDistanceSimdReal()); + } + + const hkContactPoint& getContact() const { return m_contact; } + + void setContact(const hkContactPoint& cp) { m_contact = cp; } + + void setContact(hkVector4Parameter pos, hkVector4Parameter norm, hkReal d) { + m_contact.set(pos, norm, d); + } + void setContact(hkVector4Parameter pos, hkVector4Parameter norm, hkSimdRealParameter d) { + m_contact.setPositionNormalAndDistance(pos, norm, d); + } + + void setContactDistance(hkReal d) { m_contact.setDistance(d); } + void setContactDistance(hkSimdRealParameter d) { m_contact.setDistanceSimdReal(d); } + + hkContactPoint m_contact; + const hkpCollidable* m_rootCollidableA; + hkpShapeKey m_shapeKeyA; + const hkpCollidable* m_rootCollidableB; + hkpShapeKey m_shapeKeyB; +}; diff --git a/lib/hkStubs/Havok/Physics2012/Dynamics/World/hkpWorld.h b/lib/hkStubs/Havok/Physics2012/Dynamics/World/hkpWorld.h index 79673476..34a1296d 100644 --- a/lib/hkStubs/Havok/Physics2012/Dynamics/World/hkpWorld.h +++ b/lib/hkStubs/Havok/Physics2012/Dynamics/World/hkpWorld.h @@ -311,6 +311,11 @@ public: hkThreadPool* threadPool, hkSemaphoreBusyWait* semaphore, int numCommandsPerJob = 32) const; + /// Cast a shape. + /// + /// @param collA The collidable for the shape to cast. + /// @param castCollector Collects all potential hits. + /// @param startCollector [Optional] Collects points that are closest to the start point. void linearCast(const hkpCollidable* collA, const hkpLinearCastInput& input, hkpCdPointCollector& castCollector, hkpCdPointCollector* startCollector = nullptr) const; diff --git a/src/KingSystem/Physics/CMakeLists.txt b/src/KingSystem/Physics/CMakeLists.txt index e6cbf839..6593112a 100644 --- a/src/KingSystem/Physics/CMakeLists.txt +++ b/src/KingSystem/Physics/CMakeLists.txt @@ -143,6 +143,10 @@ target_sources(uking PRIVATE System/physSensorContactListener.h System/physSensorGroupFilter.cpp System/physSensorGroupFilter.h + System/physShapeCast.cpp + System/physShapeCast.h + System/physShapeCastWithInfo.cpp + System/physShapeCastWithInfo.h System/physSystem.cpp System/physSystem.h System/physSystemData.cpp diff --git a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h index addaa3b9..dfc29094 100644 --- a/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h @@ -19,6 +19,8 @@ public: float getVolume() override; + void setRadius(float radius); + protected: Shape* getShape_() override; const Shape* getShape_() const override; diff --git a/src/KingSystem/Physics/RigidBody/physRigidBody.h b/src/KingSystem/Physics/RigidBody/physRigidBody.h index 42aad7ea..304c3129 100644 --- a/src/KingSystem/Physics/RigidBody/physRigidBody.h +++ b/src/KingSystem/Physics/RigidBody/physRigidBody.h @@ -527,7 +527,7 @@ public: bool isEntityMotionFlag200On() const; // FIXME: return type - virtual u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* unk, + virtual u32 getCollisionMasks(RigidBody::CollisionMasks* masks, const u32* shape_key, const sead::Vector3f& contact_point) = 0; protected: diff --git a/src/KingSystem/Physics/System/physClosestPointQuery.cpp b/src/KingSystem/Physics/System/physClosestPointQuery.cpp index c27220a0..ab4b8ffd 100644 --- a/src/KingSystem/Physics/System/physClosestPointQuery.cpp +++ b/src/KingSystem/Physics/System/physClosestPointQuery.cpp @@ -19,11 +19,7 @@ void ClosestPointQuery::reset() { } void ClosestPointQuery::setLayerMasks(const LayerMaskBuilder& builder) { - auto* info = mContactPointInfo; - for (int i = 0; i < NumContactLayerTypes; ++i) { - info->mSubscribedLayers[i] = builder.getMasks()[i].layers; - info->mLayerMask2[i] = builder.getMasks()[i].layers2; - } + mContactPointInfo->setLayerMasks(builder); } bool ClosestPointQuery::isSuccess() const { diff --git a/src/KingSystem/Physics/System/physContactListener.cpp b/src/KingSystem/Physics/System/physContactListener.cpp index 23564f3f..8236d74f 100644 --- a/src/KingSystem/Physics/System/physContactListener.cpp +++ b/src/KingSystem/Physics/System/physContactListener.cpp @@ -226,8 +226,8 @@ int ContactListener::notifyContactPointInfo(RigidBody* body_a, RigidBody* body_b int result = 1; - if (info_b && info_b->isLayerSubscribed(layer_a) && (info_b->get30() == 0 || distance <= 0.0) && - (info_b->get34() == 0 || !contact_disabled)) { + if (info_b && info_b->isLayerSubscribed(layer_a) && + info_b->testContactPointDistance(distance) && (info_b->get34() == 0 || !contact_disabled)) { if (should_notify) { point.body_a = body_b; point.body_b = body_a; @@ -250,8 +250,8 @@ int ContactListener::notifyContactPointInfo(RigidBody* body_a, RigidBody* body_b clearCallbackDelay(event); } - if (info_a && info_a->isLayerSubscribed(layer_b) && (info_a->get30() == 0 || distance <= 0.0) && - (info_a->get34() == 0 || !contact_disabled)) { + if (info_a && info_a->isLayerSubscribed(layer_b) && + info_a->testContactPointDistance(distance) && (info_a->get34() == 0 || !contact_disabled)) { if (should_notify) { point.body_a = body_a; point.body_b = body_b; @@ -293,7 +293,7 @@ void ContactListener::notifyLayerContactPointInfo(const TrackedContactPointLayer return; const hkReal distance = event.m_contactPoint->getDistance(); - if (!(tracked_layer.info->get30() == 0 || distance <= 0.0)) + if (!tracked_layer.info->testContactPointDistance(distance)) return; if (tracked_layer.info->get34() != 0 && isContactDisabled(event)) diff --git a/src/KingSystem/Physics/System/physContactPointInfo.h b/src/KingSystem/Physics/System/physContactPointInfo.h index f8861e40..2d6a2445 100644 --- a/src/KingSystem/Physics/System/physContactPointInfo.h +++ b/src/KingSystem/Physics/System/physContactPointInfo.h @@ -12,6 +12,8 @@ #include #include #include "KingSystem/Physics/RigidBody/physRigidBody.h" +#include "KingSystem/Physics/physDefines.h" +#include "KingSystem/Physics/physLayerMaskBuilder.h" #include "KingSystem/Utils/Types.h" namespace ksys::phys { @@ -31,6 +33,9 @@ public: u32 get30() const { return _30; } void set30(u32 value) { _30 = value; } + // TODO: rename + bool testContactPointDistance(float distance) const { return get30() == 0 || distance <= 0; } + u32 get34() const { return _34; } void set34(u32 value) { _34 = value; } @@ -45,9 +50,18 @@ public: return mLayerMask2[int(type)].isOnBit(int(getContactLayerBaseRelativeValue(layer))); } + void setLayerMasks(const LayerMaskBuilder& builder) { + for (int i = 0; i < NumContactLayerTypes; ++i) { + mSubscribedLayers[i] = builder.getMasks()[i].layers; + mLayerMask2[i] = builder.getMasks()[i].layers2; + } + } + public: // For internal use by the physics system. + sead::Atomic& getNumContactPoints() { return mNumContactPoints; } + bool isLinked() const { return mListNode.isLinked(); } static constexpr size_t getListNodeOffset() { diff --git a/src/KingSystem/Physics/System/physShapeCast.cpp b/src/KingSystem/Physics/System/physShapeCast.cpp new file mode 100644 index 00000000..cefed97b --- /dev/null +++ b/src/KingSystem/Physics/System/physShapeCast.cpp @@ -0,0 +1,256 @@ +#include "KingSystem/Physics/System/physShapeCast.h" +#include +#include +#include +#include +#include "KingSystem/Physics/System/physContactMgr.h" +#include "KingSystem/Physics/System/physEntityContactListener.h" +#include "KingSystem/Physics/System/physGroupFilter.h" +#include "KingSystem/Physics/System/physQueryContactPointInfo.h" +#include "KingSystem/Physics/System/physSystem.h" +#include "KingSystem/Physics/physConversions.h" +#include "KingSystem/Physics/physLayerMaskBuilder.h" + +namespace ksys::phys { + +ShapeCast::ShapeCast(RigidBody* body, QueryContactPointInfo* contact_point_info, Mode mode) + : mContactPointInfo(contact_point_info), mMode(mode) { + if (body) + mBody = body; + + mTo = sead::Vector3f::zero; + mFrom = sead::Vector3f::zero; + mRotation.set(1, 0, 0, 0); + reset(); +} + +ShapeCast::~ShapeCast() = default; + +void ShapeCast::reset() { + _40 = {}; + _41 = {}; + _42 = {}; + _44 = {}; + + if (mContactPointInfo) + mContactPointInfo->getNumContactPoints() = 0; +} + +void ShapeCast::setRotation(sead::Quatf rotation) { + mRotation = rotation; +} + +void ShapeCast::setRotation(const sead::Matrix33f& rotation_matrix) { + auto quat = sead::Quatf::unit; + rotation_matrix.toQuat(quat); + setRotation(quat); +} + +void ShapeCast::setRotation(const sead::Matrix34f& transform_matrix) { + auto quat = sead::Quatf::unit; + transform_matrix.toQuat(quat); + setRotation(quat); +} + +void ShapeCast::setStartAndEnd(const sead::Vector3f& start, const sead::Vector3f& end) { + mFrom = start; + mTo = end; +} + +void ShapeCast::setStartAndDisplacement(const sead::Vector3f& start, + const sead::Vector3f& displacement) { + mFrom = start; + mTo = start + displacement; +} + +void ShapeCast::setStartAndDisplacementScaled(const sead::Vector3f& start, + const sead::Vector3f& displacement, + float displacement_scale) { + mFrom = start; + mTo = start + displacement * displacement_scale; +} + +void ShapeCast::setLayerMasks(const LayerMaskBuilder& mask_builder) { + mContactPointInfo->setLayerMasks(mask_builder); +} + +void ShapeCast::setColors(const sead::Color4f& color1, const sead::Color4f& color2, + const sead::Color4f& color3, bool enabled) { + // Stubbed in release builds. +} + +// NON_MATCHING: the last if block is a complete mess. Should be equivalent, though. +bool ShapeCast::doExecuteQuery(hkpCdPointCollector& cast_collector, + hkpAllCdPointCollector* start_collector, + ShapeCast::WeldClosestPoints weld_closest_points, + OnlyLockIfNeeded only_lock_if_needed) { + const auto layer_type = mBody->getLayerType(); + + System::instance()->lockWorld(layer_type, "shape_cast", 0, only_lock_if_needed); + + hkpLinearCastInput input; + loadFromVec3(&input.m_to, mTo); + + // Reset internal state. + cast_collector.reset(); + if (_44 == 1) + reset(); + + System::instance()->getHavokWorld(layer_type)->m_collisionInput->m_weldClosestPoints = + bool(weld_closest_points); + + doCast(input, cast_collector, start_collector); + + System::instance()->unlockWorld(layer_type, "shape_cast", 0, only_lock_if_needed); + + // Register every point that is in start_collector. + auto* body = mBody; + for (int i = 0, n = start_collector->getNumHits(); i < n; ++i) { + if (registerContactPoint(start_collector->getHits()[i], body, ClampDistance::Yes)) { + _40 = true; + if (mMode == Mode::_0) + break; + } + } + + _41 = _40; + + if (mMode == Mode::_2 || !_40) { + int num_hits = 0; + FilteredClosestCdPointCollector* filtered_collector = nullptr; + hkpAllCdPointCollector* all_point_collector = nullptr; + bool ok = false; + + if (mMode == Mode::_1 || mMode == Mode::_0) { + filtered_collector = static_cast(&cast_collector); + num_hits = 1; + ok = filtered_collector->hasHit(); + } else { + all_point_collector = static_cast(&cast_collector); + num_hits = all_point_collector->getNumHits(); + ok = num_hits >= 0; + } + + if (ok) { + for (int i = 0; i < num_hits; ++i) { + const auto& point = mMode == Mode::_2 ? all_point_collector->getHits()[i] : + filtered_collector->getHit(); + if (registerContactPoint(point, body, ClampDistance::No)) + _40 = true; + } + } + + _42 = _40; + } + + _44 = 1; + return _40; +} + +bool ShapeCast::registerContactPoint(const hkpRootCdPoint& point, RigidBody* body, + ClampDistance clamp_distance) { + auto* hit_entity = getHkpEntity(*point.m_rootCollidableB); + if (!hit_entity) + return false; + + if (!mContactPointInfo->testContactPointDistance(point.getContact().getDistance())) + return false; + + auto* hit_body = getRigidBody(hit_entity); + + if (System::instance()->getEntityContactListenerField91() && hit_body->isEntity() && + EntityContactListener::isObjectOrGroundOrNPCOrTree(*hit_body)) { + return false; + } + + RigidBodyCollisionMasks masks_a, masks_b; + sead::Vector3f contact_position; + storeToVec3(&contact_position, point.getContact().getPosition()); + + body->getCollisionMasks(&masks_a, &point.m_shapeKeyA, contact_position); + hit_body->getCollisionMasks(&masks_b, &point.m_shapeKeyB, contact_position); + + auto* filter = System::instance()->getGroupFilter(hit_body->getLayerType()); + auto layer_b = filter->getCollisionFilterInfoLayer(masks_b.collision_filter_info); + + if (!mContactPointInfo->isLayerSubscribed(layer_b)) + return false; + + ContactPoint contact_point; + contact_point.flags.makeAllZero(); + contact_point.body_a = body; + contact_point.body_b = hit_body; + contact_point.material_mask_a = MaterialMaskData(masks_a.material_mask); + contact_point.material_mask_b = MaterialMaskData(masks_b.material_mask); + storeToVec3(&contact_point.position, point.getContact().getPosition()); + storeToVec3(&contact_point.separating_normal, point.getContact().getSeparatingNormal()); + + float distance = point.getContact().getDistance(); + if (distance < 0 && bool(clamp_distance)) + distance = 0; + + contact_point.separating_distance = distance; + contact_point.shape_key_a = point.m_shapeKeyA; + contact_point.shape_key_b = point.m_shapeKeyB; + contact_point.separating_normal *= -1; + + return System::instance()->getContactMgr()->registerContactPoint(mContactPointInfo, + contact_point, true); +} + +FilteredClosestCdPointCollector::FilteredClosestCdPointCollector( + RigidBody* body, QueryContactPointInfo* contact_point_info) + : mBody(body), mContactPointInfo(contact_point_info) {} + +// NON_MATCHING: the original code has a useless `if (this == nullptr)` check for some reason +FilteredClosestCdPointCollector::~FilteredClosestCdPointCollector() = default; + +void FilteredClosestCdPointCollector::addCdPoint(const hkpCdPoint& point) { + auto* body = mBody; + const auto point_distance = point.getContact().getDistanceSimdReal(); + + if (hasHit() && !point_distance.isLess(getHitContact().getDistanceSimdReal())) + return; + + auto* hit_entity = getHkpEntity(*point.m_cdBodyB.getRootCollidable()); + if (!hit_entity) + return; + + auto* hit_body = getRigidBody(hit_entity); + + if (System::instance()->getEntityContactListenerField91() && hit_body->isEntity() && + EntityContactListener::isObjectOrGroundOrNPCOrTree(*hit_body)) { + return; + } + + RigidBodyCollisionMasks masks_a, masks_b; + sead::Vector3f contact_position; + storeToVec3(&contact_position, point.getContact().getPosition()); + auto shape_key_a = point.m_cdBodyA.getShapeKey(); + auto shape_key_b = point.m_cdBodyB.getShapeKey(); + + body->getCollisionMasks(&masks_a, &shape_key_a, contact_position); + hit_body->getCollisionMasks(&masks_b, &shape_key_b, contact_position); + + auto* filter = System::instance()->getGroupFilter(hit_body->getLayerType()); + auto layer_b = filter->getCollisionFilterInfoLayer(masks_b.collision_filter_info); + + if (!mContactPointInfo->isLayerSubscribed(layer_b)) + return; + + m_hitPoint.setContact(point.getContact()); + m_hitPoint.m_rootCollidableA = point.m_cdBodyA.getRootCollidable(); + m_hitPoint.m_shapeKeyA = point.m_cdBodyA.getShapeKey(); + m_hitPoint.m_rootCollidableB = point.m_cdBodyB.getRootCollidable(); + m_hitPoint.m_shapeKeyB = point.m_cdBodyB.getShapeKey(); + // Set m_earlyOutDistance to the current distance as an optimisation. + m_earlyOutDistance = point_distance; + m_unweldedNormal = point.getUnweldedNormal(); +} + +void FilteredClosestCdPointCollector::reset() { + hkpClosestCdPointCollector::reset(); + m_earlyOutDistance = 1.0f; +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physShapeCast.h b/src/KingSystem/Physics/System/physShapeCast.h new file mode 100644 index 00000000..85927677 --- /dev/null +++ b/src/KingSystem/Physics/System/physShapeCast.h @@ -0,0 +1,100 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +class hkpAllCdPointCollector; +class hkpCdPointCollector; +struct hkpLinearCastInput; +struct hkpRootCdPoint; + +namespace ksys::phys { + +enum class OnlyLockIfNeeded : bool; + +class LayerMaskBuilder; +class RigidBody; +class QueryContactPointInfo; + +class ShapeCast { + SEAD_RTTI_BASE(ShapeCast) +public: + enum class WeldClosestPoints : bool { Yes = true, No = false }; + + virtual bool executeQuery(WeldClosestPoints weld_closest_points) = 0; + +protected: + virtual void doCast(const hkpLinearCastInput& input, hkpCdPointCollector& cast_collector, + hkpCdPointCollector* start_collector) = 0; + +public: + enum class Mode { + _0 = 0, + _1 = 1, + _2 = 2, + }; + + ShapeCast(RigidBody* body, QueryContactPointInfo* contact_point_info, Mode mode); + virtual ~ShapeCast(); + + void reset(); + + void setRotation(sead::Quatf rotation); + void setRotation(const sead::Matrix33f& rotation_matrix); + void setRotation(const sead::Matrix34f& transform_matrix); + + void setStartAndEnd(const sead::Vector3f& start, const sead::Vector3f& end); + void setStartAndDisplacement(const sead::Vector3f& start, const sead::Vector3f& displacement); + void setStartAndDisplacementScaled(const sead::Vector3f& start, + const sead::Vector3f& displacement, + float displacement_scale); + + void setLayerMasks(const LayerMaskBuilder& mask_builder); + + void setColors(const sead::Color4f& color1, const sead::Color4f& color2, + const sead::Color4f& color3, bool enabled = true); + +protected: + bool doExecuteQuery(hkpCdPointCollector& cast_collector, + hkpAllCdPointCollector* start_collector, + WeldClosestPoints weld_closest_points, + OnlyLockIfNeeded only_lock_if_needed); + + enum class ClampDistance : bool { Yes = true, No = false }; + bool registerContactPoint(const hkpRootCdPoint& point, RigidBody* body, + ClampDistance clamp_distance); + + RigidBody* mBody{}; + QueryContactPointInfo* mContactPointInfo{}; + /// The start position of the ray in world space. + sead::Vector3f mFrom = sead::Vector3f::zero; + /// The end position of the ray in world space. + sead::Vector3f mTo = sead::Vector3f::zero; + sead::Quatf mRotation = sead::Quatf::unit; + bool _40{}; + bool _41{}; + bool _42{}; + int _44{}; + Mode mMode{}; +}; + +class FilteredClosestCdPointCollector : public hkpClosestCdPointCollector { +public: + HK_DECLARE_CLASS_ALLOCATOR(FilteredClosestCdPointCollector) + + FilteredClosestCdPointCollector(RigidBody* body, QueryContactPointInfo* contact_point_info); + ~FilteredClosestCdPointCollector() override; + + void addCdPoint(const hkpCdPoint& point) override; + void reset() override; + +protected: + RigidBody* mBody{}; + QueryContactPointInfo* mContactPointInfo{}; +}; + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physShapeCastWithInfo.cpp b/src/KingSystem/Physics/System/physShapeCastWithInfo.cpp new file mode 100644 index 00000000..cf0a8ac0 --- /dev/null +++ b/src/KingSystem/Physics/System/physShapeCastWithInfo.cpp @@ -0,0 +1,94 @@ +#include "KingSystem/Physics/System/physShapeCastWithInfo.h" +#include +#include +#include +#include +#include "KingSystem/Physics/RigidBody/Shape/Sphere/physSphereRigidBody.h" +#include "KingSystem/Physics/RigidBody/Shape/Sphere/physSphereShape.h" +#include "KingSystem/Physics/RigidBody/physRigidBody.h" +#include "KingSystem/Physics/System/physQueryContactPointInfo.h" +#include "KingSystem/Physics/System/physSystem.h" +#include "KingSystem/Physics/physConversions.h" + +namespace ksys::phys { + +ShapeCastWithInfo::ShapeCastWithInfo(RigidBody* body, int num_contact_points, Mode mode, + const sead::SafeString& name, LowPriority low_priority) + : ShapeCast(body, nullptr, mode) { + mStatus = Status::_1; + auto* heap = System::instance()->getPhysicsTempHeap(low_priority); + mContactPointInfo = QueryContactPointInfo::make(heap, num_contact_points, name, 0, 0); +} + +ShapeCastWithInfo::ShapeCastWithInfo(RigidBody* body, QueryContactPointInfo* contact_point_info, + Mode mode) + : ShapeCast(body, contact_point_info, mode) {} + +ShapeCastWithInfo::~ShapeCastWithInfo() { + if (mStatus == Status::_1 || mStatus == Status::_3) + QueryContactPointInfo::free(mContactPointInfo); +} + +// NON_MATCHING: mMode test + regalloc +bool ShapeCastWithInfo::executeQuery(WeldClosestPoints weld_closest_points) { + if (mMode == Mode::_1 || mMode == Mode::_0) { + FilteredClosestCdPointCollector cast_collector{mBody, mContactPointInfo}; + hkpAllCdPointCollector start_collector; + return doExecuteQuery(cast_collector, &start_collector, weld_closest_points, + OnlyLockIfNeeded::Yes); + } else { + hkpAllCdPointCollector cast_collector; + hkpAllCdPointCollector start_collector; + return doExecuteQuery(cast_collector, &start_collector, weld_closest_points, + OnlyLockIfNeeded::Yes); + } +} + +void ShapeCastWithInfo::doCast(const hkpLinearCastInput& input, hkpCdPointCollector& cast_collector, + hkpCdPointCollector* start_collector) { + hkTransformf transform; + const auto translate = mFrom; + transform.set(toHkQuat(mRotation), toHkVec4(translate)); + + hkpRigidBody* hk_body = mBody->getHkBody(); + hkpCollidable collidable{hk_body->getCollidable()->getShape(), + hk_body->getMotion()->getMotionState()}; + collidable.setTransform(&transform); + collidable.setCollisionFilterInfo(hk_body->getCollisionFilterInfo()); + + auto* world = System::instance()->getHavokWorld(mBody->getLayerType()); + world->linearCast(&collidable, input, cast_collector, start_collector); +} + +SphereCast::SphereCast(ContactLayer layer, GroundHit ground_hit, SystemGroupHandler* group_handler, + int num_contact_points, ShapeCast::Mode mode, const sead::Vector3f& from, + float sphere_radius, const sead::SafeString& name, LowPriority low_priority) + : ShapeCastWithInfo(nullptr, num_contact_points, mode, name, low_priority) { + auto* heap = System::instance()->getPhysicsTempHeap(low_priority); + + SphereParam sphere_param; + sphere_param.name = sead::SafeString::cEmptyString.cstr(); + sphere_param.radius = sphere_radius; + sphere_param.translate = from; + sphere_param.contact_layer = layer; + sphere_param.groundhit = ground_hit; + sphere_param.motion_type = MotionType::Fixed; + sphere_param.system_group_handler = group_handler; + sphere_param._90 = true; + + mSphere = SphereRigidBody::make(&sphere_param, heap); + mBody = mSphere; + mStatus = Status::_3; +} + +SphereCast::~SphereCast() { + if (mStatus == Status::_2 || mStatus == Status::_3) + delete mSphere; +} + +void SphereCast::setRadius(float radius) { + mSphere->setRadius(radius); + mSphere->x_40(); +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physShapeCastWithInfo.h b/src/KingSystem/Physics/System/physShapeCastWithInfo.h new file mode 100644 index 00000000..42dadd9e --- /dev/null +++ b/src/KingSystem/Physics/System/physShapeCastWithInfo.h @@ -0,0 +1,52 @@ +#pragma once + +#include "KingSystem/Physics/System/physShapeCast.h" +#include "KingSystem/Physics/System/physSystem.h" +#include "KingSystem/Physics/physDefines.h" + +namespace ksys::phys { + +class SphereRigidBody; +class SystemGroupHandler; + +class ShapeCastWithInfo : public ShapeCast { + SEAD_RTTI_OVERRIDE(ShapeCastWithInfo, ShapeCast) +public: + ShapeCastWithInfo(RigidBody* body, int num_contact_points, Mode mode, + const sead::SafeString& name, LowPriority low_priority); + ShapeCastWithInfo(RigidBody* body, QueryContactPointInfo* contact_point_info, Mode mode); + + ~ShapeCastWithInfo() override; + + bool executeQuery(WeldClosestPoints weld_closest_points) override; + +protected: + enum class Status { + _0 = 0, + _1 = 1, + _2 = 2, + _3 = 3, + }; + + void doCast(const hkpLinearCastInput& input, hkpCdPointCollector& cast_collector, + hkpCdPointCollector* start_collector) override; + + Status mStatus = Status::_0; +}; + +class SphereCast : public ShapeCastWithInfo { + SEAD_RTTI_OVERRIDE(SphereCast, ShapeCastWithInfo) +public: + SphereCast(ContactLayer layer, GroundHit ground_hit, SystemGroupHandler* group_handler, + int num_contact_points, Mode mode, const sead::Vector3f& from, float sphere_radius, + const sead::SafeString& name, LowPriority low_priority); + + ~SphereCast() override; + + void setRadius(float radius); + +private: + SphereRigidBody* mSphere; +}; + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physSystem.h b/src/KingSystem/Physics/System/physSystem.h index 68fd7bac..8c61d82d 100644 --- a/src/KingSystem/Physics/System/physSystem.h +++ b/src/KingSystem/Physics/System/physSystem.h @@ -7,6 +7,8 @@ #include "KingSystem/Physics/physDefines.h" #include "KingSystem/Utils/Types.h" +class hkpWorld; + namespace ksys::phys { class CollisionInfo; @@ -27,10 +29,8 @@ enum class IsIndoorStage { Yes, }; -enum class LowPriority : bool { - Yes = true, - No = false, -}; +enum class LowPriority : bool { Yes = true, No = false }; +enum class OnlyLockIfNeeded : bool { Yes = true, No = false }; class System { SEAD_SINGLETON_DISPOSER(System) @@ -85,8 +85,11 @@ public: void removeSystemGroupHandler(SystemGroupHandler* handler); - void lockWorld(ContactLayerType type, void* a = nullptr, int b = 0, bool c = false); - void unlockWorld(ContactLayerType type, void* a = nullptr, int b = 0, bool c = false); + hkpWorld* getHavokWorld(ContactLayerType type) const; + void lockWorld(ContactLayerType type, const char* description = nullptr, int b = 0, + OnlyLockIfNeeded only_lock_if_needed = OnlyLockIfNeeded::No); + void unlockWorld(ContactLayerType type, const char* description = nullptr, int b = 0, + OnlyLockIfNeeded only_lock_if_needed = OnlyLockIfNeeded::No); // TODO: rename // 0x0000007101216c60 @@ -94,6 +97,11 @@ public: // 0x0000007101216c74 bool getEntityContactListenerField90() const; + // 0x0000007101216800 + void setEntityContactListenerField91(bool value); + // 0x0000007101216814 + bool getEntityContactListenerField91() const; + // 0x0000007101216cec sead::Heap* getPhysicsTempHeap(LowPriority low_priority) const;