A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectKCL.cc
1#include "ObjectKCL.hh"
2
3#include "game/system/RaceManager.hh"
4#include "game/system/ResourceManager.hh"
5
6#include <egg/math/Math.hh>
7
8namespace Kinoko::Field {
9
11ObjectKCL::ObjectKCL(const System::MapdataGeoObj &params)
12 : ObjectDrivable(params), m_lastMtxUpdateFrame(-2000), m_lastScaleUpdateFrame(-2000) {}
13
15ObjectKCL::~ObjectKCL() {
16 EGG::egg_delete(m_objColMgr);
17}
18
20void ObjectKCL::createCollision() {
21 char filepath[128];
22 snprintf(filepath, sizeof(filepath), "%s.kcl", getKclName());
23
24 auto *resMgr = System::ResourceManager::Instance();
25 m_objColMgr =
26 EGG::egg_new<ObjColMgr>(resMgr->getFile(filepath, nullptr, System::ArchiveId::Course));
27}
28
30void ObjectKCL::calcCollisionTransform() {
31 update(0);
32}
33
35void ObjectKCL::initCollision() {
36 const EGG::Matrix34f &mat = getUpdatedMatrix(0);
37 EGG::Matrix34f matInv;
38 bool inverted = mat.ps_inverse(matInv);
39 ASSERT(inverted);
40
41 m_objColMgr->setMtx(mat);
42 m_objColMgr->setInvMtx(matInv);
43 m_objColMgr->setScale(getScaleY(0));
44
45 EGG::Vector3f high = m_objColMgr->kclHighWorld();
46 EGG::Vector3f low = m_objColMgr->kclLowWorld();
47
48 m_kclMidpoint = (high + low).multInv(2.0f);
49
50 EGG::Vector3f highLowDiffAbs = (high - low).abs();
51 f32 maxDiff = std::max(highLowDiffAbs.x, highLowDiffAbs.z);
52 m_bboxHalfSideLength = maxDiff * 0.5f;
53}
54
56bool ObjectKCL::checkPointPartial(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
57 KCLTypeMask mask, CollisionInfoPartial *info, KCLTypeMask *maskOut) {
58 if (!shouldCheckColNoPush()) {
59 return false;
60 }
61
62 return m_objColMgr->checkPointPartial(pos, prevPos, mask, info, maskOut);
63}
64
66bool ObjectKCL::checkPointPartialPush(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
67 KCLTypeMask mask, CollisionInfoPartial *info, KCLTypeMask *maskOut) {
68 if (!shouldCheckColPush()) {
69 return false;
70 }
71
72 return m_objColMgr->checkPointPartialPush(pos, prevPos, mask, info, maskOut);
73}
74
76bool ObjectKCL::checkPointFull(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
77 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
78 if (!shouldCheckColNoPush()) {
79 return false;
80 }
81
82 return m_objColMgr->checkPointFull(pos, prevPos, mask, info, maskOut);
83}
84
86bool ObjectKCL::checkPointFullPush(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
87 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
88 if (!shouldCheckColPush()) {
89 return false;
90 }
91
92 return m_objColMgr->checkPointFullPush(pos, prevPos, mask, info, maskOut);
93}
94
96bool ObjectKCL::checkSpherePartial(f32 radius, const EGG::Vector3f &pos,
97 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
98 KCLTypeMask *maskOut, u32 timeOffset) {
99 if (!shouldCheckColNoPush()) {
100 return false;
101 }
102
103 calcScale(timeOffset);
104 update(timeOffset);
105
106 return m_objColMgr->checkSpherePartial(radius, pos, prevPos, mask, info, maskOut);
107}
108
110bool ObjectKCL::checkSpherePartialPush(f32 radius, const EGG::Vector3f &pos,
111 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
112 KCLTypeMask *maskOut, u32 timeOffset) {
113 if (!shouldCheckColPush()) {
114 return false;
115 }
116
117 calcScale(timeOffset);
118 update(timeOffset);
119
120 return m_objColMgr->checkSpherePartialPush(radius, pos, prevPos, mask, info, maskOut);
121}
122
124bool ObjectKCL::checkSphereFull(f32 radius, const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
125 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut, u32 timeOffset) {
126 if (!shouldCheckColNoPush()) {
127 return false;
128 }
129
130 calcScale(timeOffset);
131 update(timeOffset);
132
133 return m_objColMgr->checkSphereFull(radius, pos, prevPos, mask, info, maskOut);
134}
135
137bool ObjectKCL::checkSphereFullPush(f32 radius, const EGG::Vector3f &pos,
138 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
139 u32 timeOffset) {
140 return checkCollision(radius, pos, prevPos, mask, info, maskOut, timeOffset);
141}
142
144void ObjectKCL::narrScLocal(f32 radius, const EGG::Vector3f &pos, KCLTypeMask mask,
145 u32 /*timeOffset*/) {
146 m_objColMgr->narrScLocal(radius, pos, mask);
147}
148
150bool ObjectKCL::checkPointCachedPartial(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
151 KCLTypeMask mask, CollisionInfoPartial *info, KCLTypeMask *maskOut) {
152 if (!shouldCheckColNoPush()) {
153 return false;
154 }
155
156 return m_objColMgr->checkPointCachedPartial(pos, prevPos, mask, info, maskOut);
157}
158
160bool ObjectKCL::checkPointCachedPartialPush(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
161 KCLTypeMask mask, CollisionInfoPartial *info, KCLTypeMask *maskOut) {
162 if (!shouldCheckColPush()) {
163 return false;
164 }
165
166 return m_objColMgr->checkPointCachedPartialPush(pos, prevPos, mask, info, maskOut);
167}
168
170bool ObjectKCL::checkPointCachedFull(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
171 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
172 if (!shouldCheckColNoPush()) {
173 return false;
174 }
175
176 return m_objColMgr->checkPointCachedFull(pos, prevPos, mask, info, maskOut);
177}
178
180bool ObjectKCL::checkPointCachedFullPush(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
181 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
182 if (!shouldCheckColPush()) {
183 return false;
184 }
185
186 return m_objColMgr->checkPointCachedFullPush(pos, prevPos, mask, info, maskOut);
187}
188
190bool ObjectKCL::checkSphereCachedPartial(f32 radius, const EGG::Vector3f &pos,
191 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
192 KCLTypeMask *maskOut, u32 timeOffset) {
193 if (!shouldCheckColNoPush()) {
194 return false;
195 }
196
197 update(timeOffset);
198 calcScale(timeOffset);
199
200 return m_objColMgr->checkSphereCachedPartial(radius, pos, prevPos, mask, info, maskOut);
201}
202
204bool ObjectKCL::checkSphereCachedPartialPush(f32 radius, const EGG::Vector3f &pos,
205 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
206 KCLTypeMask *maskOut, u32 timeOffset) {
207 if (!shouldCheckColPush()) {
208 return false;
209 }
210
211 update(timeOffset);
212 calcScale(timeOffset);
213
214 return m_objColMgr->checkSphereCachedPartialPush(radius, pos, prevPos, mask, info, maskOut);
215}
216
218bool ObjectKCL::checkSphereCachedFull(f32 radius, const EGG::Vector3f &pos,
219 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
220 u32 timeOffset) {
221 if (!shouldCheckColNoPush()) {
222 return false;
223 }
224
225 update(timeOffset);
226 calcScale(timeOffset);
227
228 return m_objColMgr->checkSphereCachedFull(radius, pos, prevPos, mask, info, maskOut);
229}
230
232bool ObjectKCL::checkSphereCachedFullPush(f32 radius, const EGG::Vector3f &pos,
233 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
234 u32 timeOffset) {
235 return checkCollisionCached(radius, pos, prevPos, mask, info, maskOut, timeOffset);
236}
237
239void ObjectKCL::update(u32 timeOffset) {
240 u32 time = System::RaceManager::Instance()->timer() - timeOffset;
241 if (m_lastMtxUpdateFrame == static_cast<s32>(time)) {
242 return;
243 }
244
245 EGG::Matrix34f mat;
246
247 if (timeOffset == 0) {
248 calcTransform();
249 mat = transform();
250 } else {
251 mat = getUpdatedMatrix(timeOffset);
252 }
253
254 EGG::Matrix34f matInv;
255 mat.ps_inverse(matInv);
256 m_objColMgr->setMtx(mat);
257 m_objColMgr->setInvMtx(matInv);
258
259 m_lastMtxUpdateFrame = time;
260}
261
263void ObjectKCL::calcScale(u32 timeOffset) {
264 u32 time = System::RaceManager::Instance()->timer() - timeOffset;
265 if (m_lastScaleUpdateFrame == static_cast<s32>(time)) {
266 return;
267 }
268
269 if (time == 0) {
270 m_objColMgr->setScale(scale().y);
271 } else {
272 m_objColMgr->setScale(getScaleY(timeOffset));
273 }
274
275 m_lastScaleUpdateFrame = time;
276}
277
279bool ObjectKCL::checkCollision(f32 radius, const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
280 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut, u32 timeOffset) {
281 if (!shouldCheckColPush()) {
282 return false;
283 }
284
285 update(timeOffset);
286 calcScale(timeOffset);
287
288 return m_objColMgr->checkSphereFullPush(radius, pos, prevPos, mask, info, maskOut);
289}
290
292bool ObjectKCL::checkCollisionCached(f32 radius, const EGG::Vector3f &pos,
293 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
294 u32 timeOffset) {
295 if (!shouldCheckColPush()) {
296 return false;
297 }
298
299 update(timeOffset);
300 calcScale(timeOffset);
301
302 return m_objColMgr->checkSphereCachedFullPush(radius, pos, prevPos, mask, info, maskOut);
303}
304
305} // namespace Kinoko::Field
Pertains to collision.