diff options
| author | Léo Lam <leo@leolam.fr> | 2022-03-21 00:45:06 +0100 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2022-03-21 03:00:36 +0100 |
| commit | ec37bc00181e69a88a410e2807d5f560bae81529 (patch) | |
| tree | 1ba1830c665f547c1720ef296d94486fa4b5bb72 /src | |
| parent | 509d557731ce02136f79026ce1e1d5683c93876f (diff) | |
ksys/phys: Add RayCastRequestMgr
Diffstat (limited to 'src')
| -rw-r--r-- | src/KingSystem/Map/mapAutoPlacement.cpp | 17 | ||||
| -rw-r--r-- | src/KingSystem/Map/mapAutoPlacement.h | 5 | ||||
| -rw-r--r-- | src/KingSystem/Physics/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/KingSystem/Physics/System/physRayCastForRequest.cpp | 34 | ||||
| -rw-r--r-- | src/KingSystem/Physics/System/physRayCastForRequest.h | 36 | ||||
| -rw-r--r-- | src/KingSystem/Physics/System/physRayCastRequestMgr.cpp | 127 | ||||
| -rw-r--r-- | src/KingSystem/Physics/System/physRayCastRequestMgr.h | 42 | ||||
| -rw-r--r-- | src/KingSystem/Physics/System/physSystem.h | 9 | ||||
| -rw-r--r-- | src/KingSystem/ksys.h | 5 |
9 files changed, 261 insertions, 18 deletions
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 <container/seadTList.h> +#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<RayCastForRequest*> 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 <cmath> +#include <prim/seadScopedLock.h> +#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 <container/seadTList.h> +#include <hostio/seadHostIONode.h> +#include <thread/seadCriticalSection.h> +#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<RayCastForRequest*> mQueuedList; + sead::TList<RayCastForRequest*> mFreeList; + util::TaskDelegateT<RayCastRequestMgr> 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 |
