summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLéo Lam <leo@leolam.fr>2022-03-21 00:45:06 +0100
committerLéo Lam <leo@leolam.fr>2022-03-21 03:00:36 +0100
commitec37bc00181e69a88a410e2807d5f560bae81529 (patch)
tree1ba1830c665f547c1720ef296d94486fa4b5bb72 /src
parent509d557731ce02136f79026ce1e1d5683c93876f (diff)
ksys/phys: Add RayCastRequestMgr
Diffstat (limited to 'src')
-rw-r--r--src/KingSystem/Map/mapAutoPlacement.cpp17
-rw-r--r--src/KingSystem/Map/mapAutoPlacement.h5
-rw-r--r--src/KingSystem/Physics/CMakeLists.txt4
-rw-r--r--src/KingSystem/Physics/System/physRayCastForRequest.cpp34
-rw-r--r--src/KingSystem/Physics/System/physRayCastForRequest.h36
-rw-r--r--src/KingSystem/Physics/System/physRayCastRequestMgr.cpp127
-rw-r--r--src/KingSystem/Physics/System/physRayCastRequestMgr.h42
-rw-r--r--src/KingSystem/Physics/System/physSystem.h9
-rw-r--r--src/KingSystem/ksys.h5
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