From ec37bc00181e69a88a410e2807d5f560bae81529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 21 Mar 2022 00:45:06 +0100 Subject: [PATCH] ksys/phys: Add RayCastRequestMgr --- data/uking_functions.csv | 48 +++---- lib/sead | 2 +- src/KingSystem/Map/mapAutoPlacement.cpp | 17 +-- src/KingSystem/Map/mapAutoPlacement.h | 5 +- src/KingSystem/Physics/CMakeLists.txt | 4 + .../Physics/System/physRayCastForRequest.cpp | 34 +++++ .../Physics/System/physRayCastForRequest.h | 36 +++++ .../Physics/System/physRayCastRequestMgr.cpp | 127 ++++++++++++++++++ .../Physics/System/physRayCastRequestMgr.h | 42 ++++++ src/KingSystem/Physics/System/physSystem.h | 9 +- src/KingSystem/ksys.h | 5 + 11 files changed, 286 insertions(+), 43 deletions(-) create mode 100644 src/KingSystem/Physics/System/physRayCastForRequest.cpp create mode 100644 src/KingSystem/Physics/System/physRayCastForRequest.h create mode 100644 src/KingSystem/Physics/System/physRayCastRequestMgr.cpp create mode 100644 src/KingSystem/Physics/System/physRayCastRequestMgr.h diff --git a/data/uking_functions.csv b/data/uking_functions.csv index abff23a2..7e241d30 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -84065,30 +84065,30 @@ Address,Quality,Size,Name 0x0000007100fc5368,O,000204,_ZNK4ksys4phys16RayCastBodyQuery27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE 0x0000007100fc5434,O,000092,_ZNK4ksys4phys16RayCastBodyQuery18getRuntimeTypeInfoEv 0x0000007100fc5490,O,000140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys4phys7RayCastEE9isDerivedEPKNS0_9InterfaceE -0x0000007100fc551c,U,000076,phys::RayCastDerived2::ctor -0x0000007100fc5568,U,000004,phys::RayCastDerived2::dtor -0x0000007100fc556c,U,000036,phys::RayCastDerived2::dtord -0x0000007100fc5590,U,000028,phys::RayCastDerived2::x_0 -0x0000007100fc55ac,U,000024,phys::RayCastDerived2::x_1 -0x0000007100fc55c4,U,000016,phys::RayCastDerived2::x_2 -0x0000007100fc55d4,U,000020,phys::RayCastDerived2::x_3 -0x0000007100fc55e8,U,000016,phys::RayCastDerived2::x_4 -0x0000007100fc55f8,U,000204,phys::RayCastDerived2::rtti1 -0x0000007100fc56c4,U,000092,phys::RayCastDerived2::rtti2 -0x0000007100fc5720,U,000104,RayCastRequestMgr::ctor -0x0000007100fc5788,U,000020,RayCastRequestMgr::dtor -0x0000007100fc579c,U,000052,RayCastRequestMgr::dtord -0x0000007100fc57d0,U,000256,RayCastRequestMgr::init -0x0000007100fc58d0,U,000148,RayCastRequestMgr::processRequests -0x0000007100fc5964,U,000204,RayCastRequestMgr::clearRequests -0x0000007100fc5a30,U,000136,RayCastRequestMgr::eraseRequest -0x0000007100fc5ab8,U,000184,RayCastRequestMgr::submitRequest -0x0000007100fc5b70,U,000352,RayCastRequestMgr::x_0 -0x0000007100fc5cd0,U,000020,RayCastRequestMgr::x_1 -0x0000007100fc5ce4,U,000020,RayCastRequestMgr::x_2 -0x0000007100fc5cf8,U,000068,RayCastRequestMgr::triggerRequestProcessingOnWorker -0x0000007100fc5d3c,U,000052,sead_delegate_fn -0x0000007100fc5d70,U,000092,sead_delegate_fn_0 +0x0000007100fc551c,O,000076,_ZN4ksys4phys17RayCastForRequestC1EPNS0_17RayCastRequestMgrE +0x0000007100fc5568,O,000004,_ZN4ksys4phys17RayCastForRequestD1Ev +0x0000007100fc556c,O,000036,_ZN4ksys4phys17RayCastForRequestD0Ev +0x0000007100fc5590,O,000028,_ZN4ksys4phys17RayCastForRequest12allocRequestEPNS0_18SystemGroupHandlerENS0_9GroundHitE +0x0000007100fc55ac,O,000024,_ZN4ksys4phys17RayCastForRequest13submitRequestENS0_16ContactLayerTypeE +0x0000007100fc55c4,O,000016,_ZNK4ksys4phys17RayCastForRequest15isRequestQueuedEv +0x0000007100fc55d4,O,000020,_ZN4ksys4phys17RayCastForRequest7releaseEv +0x0000007100fc55e8,O,000016,_ZNK4ksys4phys17RayCastForRequest17isRequestFinishedEv +0x0000007100fc55f8,O,000204,_ZNK4ksys4phys17RayCastForRequest27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE +0x0000007100fc56c4,O,000092,_ZNK4ksys4phys17RayCastForRequest18getRuntimeTypeInfoEv +0x0000007100fc5720,O,000104,_ZN4ksys4phys17RayCastRequestMgrC1Ev +0x0000007100fc5788,O,000020,_ZN4ksys4phys17RayCastRequestMgrD1Ev +0x0000007100fc579c,O,000052,_ZN4ksys4phys17RayCastRequestMgrD0Ev +0x0000007100fc57d0,O,000256,_ZN4ksys4phys17RayCastRequestMgr4initEPN4sead4HeapEi +0x0000007100fc58d0,O,000148,_ZN4ksys4phys17RayCastRequestMgr15processRequestsEPv +0x0000007100fc5964,O,000204,_ZN4ksys4phys17RayCastRequestMgr13clearRequestsEv +0x0000007100fc5a30,O,000136,_ZN4ksys4phys17RayCastRequestMgr14releaseRequestERNS0_17RayCastForRequestE +0x0000007100fc5ab8,O,000184,_ZN4ksys4phys17RayCastRequestMgr12allocRequestEPNS0_18SystemGroupHandlerENS0_9GroundHitE +0x0000007100fc5b70,O,000352,_ZN4ksys4phys17RayCastRequestMgr13submitRequestERNS0_17RayCastForRequestENS0_16ContactLayerTypeE +0x0000007100fc5cd0,O,000020,_ZNK4ksys4phys17RayCastRequestMgr15isRequestQueuedERKNS0_17RayCastForRequestE +0x0000007100fc5ce4,O,000020,_ZNK4ksys4phys17RayCastRequestMgr17isRequestFinishedERKNS0_17RayCastForRequestE +0x0000007100fc5cf8,O,000068,_ZN4ksys4phys17RayCastRequestMgr25scheduleRequestProcessingEv +0x0000007100fc5d3c,O,000052,_ZN4sead10Delegate1RIN4ksys4phys17RayCastRequestMgrEPvbE6invokeES4_ +0x0000007100fc5d70,O,000092,_ZNK4sead10Delegate1RIN4ksys4phys17RayCastRequestMgrEPvbE5cloneEPNS_4HeapE 0x0000007100fc5dcc,U,000032, 0x0000007100fc5dec,U,000092,phys::RigidBodyDividedMeshShapeMgr::makeInstance 0x0000007100fc5e48,U,000812,phys::RigidBodyDividedMeshShapeMgr::ctor diff --git a/lib/sead b/lib/sead index fa370e87..1b66e825 160000 --- a/lib/sead +++ b/lib/sead @@ -1 +1 @@ -Subproject commit fa370e87acb11df1805de89078b0bf9007b616e8 +Subproject commit 1b66e825d1927254c191028523645541b13c7eab diff --git a/src/KingSystem/Map/mapAutoPlacement.cpp b/src/KingSystem/Map/mapAutoPlacement.cpp index a49e6153..b47494c8 100644 --- a/src/KingSystem/Map/mapAutoPlacement.cpp +++ b/src/KingSystem/Map/mapAutoPlacement.cpp @@ -7,23 +7,12 @@ #include "KingSystem/Map/mapAutoPlacementFlowMgr.h" #include "KingSystem/Map/mapAutoPlacementMgr.h" #include "KingSystem/Physics/RigidBody/physRigidBody.h" -#include "KingSystem/Physics/System/physRayCast.h" +#include "KingSystem/Physics/System/physRayCastForRequest.h" #include "KingSystem/Utils/Byaml/Byaml.h" #include "KingSystem/World/worldWeatherMgr.h" namespace ksys::map { -// TODO: this phys::RayCast derived class should be moved to phys:: -struct Raycast : phys::RayCast { - Raycast(); - ~Raycast() override; - - static Raycast* create(void*, u32); - - void sub_7100FC55AC(u32); - void release(); -}; - AutoPlacement::AutoPlacement() = default; AutoPlacement::~AutoPlacement() = default; @@ -284,11 +273,11 @@ void PlacementThing::stepRaycast() { switch (mState) { case State::Uninitialized: - mRaycast = Raycast::create(nullptr, 1); + mRaycast = phys::RayCastForRequest::allocRequest(nullptr, phys::GroundHit::Animal); next = mRaycast != nullptr ? State::Initialized : State::Invalid; break; case State::LayersDone: - mRaycast->sub_7100FC55AC(0); + mRaycast->submitRequest(phys::ContactLayerType::Entity); next = State::RaycastDone; break; case State::PlacementDone: diff --git a/src/KingSystem/Map/mapAutoPlacement.h b/src/KingSystem/Map/mapAutoPlacement.h index 0ec68ba8..5624fddb 100644 --- a/src/KingSystem/Map/mapAutoPlacement.h +++ b/src/KingSystem/Map/mapAutoPlacement.h @@ -11,6 +11,7 @@ #include "KingSystem/Utils/Types.h" namespace ksys::phys { +class RayCastForRequest; class RigidBody; } // namespace ksys::phys @@ -20,8 +21,6 @@ class AutoPlacement; struct AutoPlacementFlowRes; class PlacementThing; -struct Raycast; - struct PlacementGroup { sead::SafeString a; u32 _10; @@ -75,7 +74,7 @@ public: private: friend class AutoPlacement; - Raycast* mRaycast{}; + phys::RayCastForRequest* mRaycast{}; u8 _8880{}; u8 mUnderwater{}; sead::Vector3f mVec1{}; diff --git a/src/KingSystem/Physics/CMakeLists.txt b/src/KingSystem/Physics/CMakeLists.txt index e0ff7ea0..c5ca57de 100644 --- a/src/KingSystem/Physics/CMakeLists.txt +++ b/src/KingSystem/Physics/CMakeLists.txt @@ -147,6 +147,10 @@ target_sources(uking PRIVATE System/physRayCast.h System/physRayCastBodyQuery.cpp System/physRayCastBodyQuery.h + System/physRayCastForRequest.cpp + System/physRayCastForRequest.h + System/physRayCastRequestMgr.cpp + System/physRayCastRequestMgr.h System/physSensorContactListener.cpp System/physSensorContactListener.h System/physSensorGroupFilter.cpp diff --git a/src/KingSystem/Physics/System/physRayCastForRequest.cpp b/src/KingSystem/Physics/System/physRayCastForRequest.cpp new file mode 100644 index 00000000..44cbfdaa --- /dev/null +++ b/src/KingSystem/Physics/System/physRayCastForRequest.cpp @@ -0,0 +1,34 @@ +#include "KingSystem/Physics/System/physRayCastForRequest.h" +#include "KingSystem/Physics/System/physRayCastRequestMgr.h" +#include "KingSystem/Physics/System/physSystem.h" + +namespace ksys::phys { + +RayCastForRequest::RayCastForRequest(RayCastRequestMgr* mgr) + : RayCast(nullptr, GroundHit::HitAll), mMgr(mgr) {} + +RayCastForRequest::~RayCastForRequest() = default; + +RayCastForRequest* RayCastForRequest::allocRequest(SystemGroupHandler* group_handler, + GroundHit ground_hit) { + return System::instance()->allocRayCastRequest(group_handler, ground_hit); +} + +bool RayCastForRequest::submitRequest(ContactLayerType layer_type) { + return mMgr->submitRequest(*this, layer_type); +} + +bool RayCastForRequest::isRequestQueued() const { + return mMgr->isRequestQueued(*this); +} + +void RayCastForRequest::release() { + mRigidBodyHitCallback = nullptr; + mMgr->releaseRequest(*this); +} + +bool RayCastForRequest::isRequestFinished() const { + return mMgr->isRequestFinished(*this); +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physRayCastForRequest.h b/src/KingSystem/Physics/System/physRayCastForRequest.h new file mode 100644 index 00000000..f5e68ad8 --- /dev/null +++ b/src/KingSystem/Physics/System/physRayCastForRequest.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include "KingSystem/Physics/System/physRayCast.h" +#include "KingSystem/Utils/Types.h" + +namespace ksys::phys { + +class RayCastRequestMgr; + +/// A RayCast that is used by RayCastRequestMgr to process raycast requests. +class RayCastForRequest : public RayCast { + SEAD_RTTI_OVERRIDE(RayCastForRequest, RayCast) +public: + static RayCastForRequest* allocRequest(SystemGroupHandler* group_handler = nullptr, + GroundHit ground_hit = GroundHit::HitAll); + + explicit RayCastForRequest(RayCastRequestMgr* mgr); + ~RayCastForRequest() override; + + bool submitRequest(ContactLayerType layer_type); + bool isRequestQueued() const; + bool isRequestFinished() const; + + /// This must be called after you're finished using this RayCast. + void release(); + +private: + friend class RayCastRequestMgr; + + RayCastRequestMgr* mMgr{}; + sead::TListNode mListNode{this}; + ContactLayerType mRequestContactLayerType = ContactLayerType::Entity; +}; + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physRayCastRequestMgr.cpp b/src/KingSystem/Physics/System/physRayCastRequestMgr.cpp new file mode 100644 index 00000000..cbae2dac --- /dev/null +++ b/src/KingSystem/Physics/System/physRayCastRequestMgr.cpp @@ -0,0 +1,127 @@ +#include "KingSystem/Physics/System/physRayCastRequestMgr.h" +#include +#include +#include "KingSystem/Framework/frmWorkerSupportThreadMgr.h" +#include "KingSystem/Physics/System/physRayCastForRequest.h" +#include "KingSystem/ksys.h" + +namespace ksys::phys { + +RayCastRequestMgr::RayCastRequestMgr() = default; + +RayCastRequestMgr::~RayCastRequestMgr() = default; + +void RayCastRequestMgr::init(sead::Heap* heap, int pool_size) { + mLargestRecordedQueueSize = 0; + for (auto it = mQueuedList.robustBegin(); it != mQueuedList.robustEnd(); it++) + mQueuedList.erase(&*it); + + for (int i = 0; i < pool_size; ++i) { + auto* ray_cast = new (heap, 0x10) RayCastForRequest(this); + mFreeList.pushBack(&ray_cast->mListNode); + } + + mWorkerFunction.bind(this, &RayCastRequestMgr::processRequests); +} + +bool RayCastRequestMgr::processRequests(void*) { + for (int i = 0; i < mBatchSize; ++i) { + mCS.lock(); + auto* request = mQueuedList.popFront(); + if (!request) { + mCS.unlock(); + return true; + } + request->mList = nullptr; + mCS.unlock(); + + request->mData->worldRayCast(request->mData->mRequestContactLayerType); + } + + return true; +} + +void RayCastRequestMgr::clearRequests() { + { + auto lock = sead::makeScopedLock(mCS); + while (!mQueuedList.isEmpty()) { + auto* request = mQueuedList.popFront(); + if (!request) + continue; + + auto* ray_cast = request->mData; + request->mList = nullptr; + releaseRequest(*ray_cast); + } + } + mLargestRecordedQueueSize = 0; +} + +void RayCastRequestMgr::releaseRequest(RayCastForRequest& ray_cast) { + auto lock = sead::makeScopedLock(mCS); + ray_cast.mRigidBodyHitCallback = nullptr; + mFreeList.pushBack(&ray_cast.mListNode); +} + +RayCastForRequest* RayCastRequestMgr::allocRequest(SystemGroupHandler* group_handler, + GroundHit ground_hit) { + auto lock = sead::makeScopedLock(mCS); + + auto* request = mFreeList.popFront(); + if (!request) + return nullptr; + + request->mList = nullptr; + + if (request->mData->_98) { + mFreeList.pushBack(request); + return nullptr; + } + + request->mData->reset(); + request->mData->mGroupHandler = group_handler; + request->mData->setGroundHit(ground_hit); + request->mData->mNormalCheckingMode = RayCast::NormalCheckingMode::_0; + return request->mData; +} + +static bool isVectorInvalid(const sead::Vector3f& vec) { + for (int i = 0; i < 3; ++i) { + if (std::isnan(vec.e[i])) + return true; + } + return false; +} + +bool RayCastRequestMgr::submitRequest(RayCastForRequest& ray_cast, ContactLayerType layer_type) { + if (isVectorInvalid(ray_cast.mFrom) || isVectorInvalid(ray_cast.mTo)) + return false; + + if (ray_cast.mListNode.isLinked()) + return false; + + auto lock = sead::makeScopedLock(mCS); + + ray_cast.mRequestContactLayerType = layer_type; + mQueuedList.pushBack(&ray_cast.mListNode); + + if (mQueuedList.size() > mLargestRecordedQueueSize) + mLargestRecordedQueueSize = mQueuedList.size(); + + return true; +} + +bool RayCastRequestMgr::isRequestQueued(const RayCastForRequest& ray_cast) const { + return ray_cast.mListNode.mList == &mQueuedList; +} + +bool RayCastRequestMgr::isRequestFinished(const RayCastForRequest& ray_cast) const { + return ray_cast.mListNode.mList == &mFreeList; +} + +void RayCastRequestMgr::scheduleRequestProcessing() { + if (!isGameOver()) + frm::WorkerSupportThreadMgr::instance()->submitRequest(5, &mWorkerFunction); +} + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physRayCastRequestMgr.h b/src/KingSystem/Physics/System/physRayCastRequestMgr.h new file mode 100644 index 00000000..4dde6bd6 --- /dev/null +++ b/src/KingSystem/Physics/System/physRayCastRequestMgr.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include +#include "KingSystem/Physics/physDefines.h" +#include "KingSystem/Utils/Thread/Task.h" + +namespace ksys::phys { + +class RayCastForRequest; +class SystemGroupHandler; + +class RayCastRequestMgr : public sead::hostio::Node { +public: + RayCastRequestMgr(); + virtual ~RayCastRequestMgr(); + + void init(sead::Heap* heap, int pool_size); + + void clearRequests(); + void releaseRequest(RayCastForRequest& ray_cast); + RayCastForRequest* allocRequest(SystemGroupHandler* group_handler, GroundHit ground_hit); + bool submitRequest(RayCastForRequest& ray_cast, ContactLayerType layer_type); + bool isRequestQueued(const RayCastForRequest& ray_cast) const; + bool isRequestFinished(const RayCastForRequest& ray_cast) const; + + void scheduleRequestProcessing(); + +private: + bool processRequests(void*); + + sead::CriticalSection mCS; + sead::TList mQueuedList; + sead::TList mFreeList; + util::TaskDelegateT mWorkerFunction; + /// The number of requests to process per batch. + int mBatchSize = 1; + int mLargestRecordedQueueSize = 0; +}; + +} // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physSystem.h b/src/KingSystem/Physics/System/physSystem.h index 1f9647c1..b9439b99 100644 --- a/src/KingSystem/Physics/System/physSystem.h +++ b/src/KingSystem/Physics/System/physSystem.h @@ -17,6 +17,7 @@ class ContactLayerCollisionInfoGroup; class ContactMgr; class GroupFilter; class MaterialTable; +class RayCastForRequest; class RigidBody; class RigidBodyRequestMgr; class ContactPointInfo; @@ -40,7 +41,6 @@ class System { public: float get64() const { return _64; } float getTimeFactor() const { return mTimeFactor; } - GroupFilter* getGroupFilter(ContactLayerType type) const; ContactMgr* getContactMgr() const { return mContactMgr; } RigidBodyRequestMgr* getRigidBodyRequestMgr() const { return mRigidBodyRequestMgr; } SystemData* getSystemData() const { return mSystemData; } @@ -94,6 +94,13 @@ public: void unlockWorld(ContactLayerType type, const char* description = nullptr, int b = 0, OnlyLockIfNeeded only_lock_if_needed = OnlyLockIfNeeded::No); + // 0x0000007101216ac8 + GroupFilter* getGroupFilter(ContactLayerType type) const; + + // 0x0000007101216ae8 + RayCastForRequest* allocRayCastRequest(SystemGroupHandler* group_handler = nullptr, + GroundHit ground_hit = GroundHit::HitAll); + // TODO: rename // 0x0000007101216c60 void setEntityContactListenerField90(bool value); diff --git a/src/KingSystem/ksys.h b/src/KingSystem/ksys.h index 535e0df5..4775ea4f 100644 --- a/src/KingSystem/ksys.h +++ b/src/KingSystem/ksys.h @@ -6,6 +6,11 @@ class Heap; namespace ksys { +// 0x0000007100f3a4e4 +bool isGameOver(); +// 0x0000007100f3a4f0 +void setIsGameOver(bool is_game_over); + void initBaseProcMgr(sead::Heap* heap); } // namespace ksys