blob: cbae2dac2ebf062958417ca043f3bd7662b6d530 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
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
|