mirror of
https://github.com/zeldaret/botw
synced 2026-08-28 16:12:18 -04:00
ksys/phys: Add RayCastRequestMgr
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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{};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user