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 Field {
9
11ObjectKCL::ObjectKCL(const System::MapdataGeoObj &params)
12 : ObjectDrivable(params), m_lastMtxUpdateFrame(-2000), m_lastScaleUpdateFrame(-2000) {}
13
15ObjectKCL::~ObjectKCL() {
16 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 = new ObjColMgr(resMgr->getFile(filepath, nullptr, System::ArchiveId::Course));
26}
27
29void ObjectKCL::calcCollisionTransform() {
30 update(0);
31}
32
34void ObjectKCL::initCollision() {
35 const EGG::Matrix34f &mat = getUpdatedMatrix(0);
36 EGG::Matrix34f matInv;
37 bool inverted = mat.ps_inverse(matInv);
38 ASSERT(inverted);
39
40 m_objColMgr->setMtx(mat);
41 m_objColMgr->setInvMtx(matInv);
42 m_objColMgr->setScale(getScaleY(0));
43
44 EGG::Vector3f high = m_objColMgr->kclHighWorld();
45 EGG::Vector3f low = m_objColMgr->kclLowWorld();
46
47 m_kclMidpoint = (high + low).multInv(2.0f);
48
49 EGG::Vector3f highLowDiffAbs = (high - low).abs();
50 f32 maxDiff = std::max(highLowDiffAbs.x, highLowDiffAbs.z);
51 m_bboxHalfSideLength = maxDiff * 0.5f;
52}
53
55bool ObjectKCL::checkPointPartial(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
56 KCLTypeMask mask, CollisionInfoPartial *info, KCLTypeMask *maskOut) {
57 if (!shouldCheckColNoPush()) {
58 return false;
59 }
60
61 return m_objColMgr->checkPointPartial(pos, prevPos, mask, info, maskOut);
62}
63
65bool ObjectKCL::checkPointPartialPush(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
66 KCLTypeMask mask, CollisionInfoPartial *info, KCLTypeMask *maskOut) {
67 if (!shouldCheckColPush()) {
68 return false;
69 }
70
71 return m_objColMgr->checkPointPartialPush(pos, prevPos, mask, info, maskOut);
72}
73
75bool ObjectKCL::checkPointFull(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
76 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
77 if (!shouldCheckColNoPush()) {
78 return false;
79 }
80
81 return m_objColMgr->checkPointFull(pos, prevPos, mask, info, maskOut);
82}
83
85bool ObjectKCL::checkPointFullPush(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
86 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
87 if (!shouldCheckColPush()) {
88 return false;
89 }
90
91 return m_objColMgr->checkPointFullPush(pos, prevPos, mask, info, maskOut);
92}
93
95bool ObjectKCL::checkSpherePartial(f32 radius, const EGG::Vector3f &pos,
96 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
97 KCLTypeMask *maskOut, u32 timeOffset) {
98 if (!shouldCheckColNoPush()) {
99 return false;
100 }
101
102 calcScale(timeOffset);
103 update(timeOffset);
104
105 return m_objColMgr->checkSpherePartial(radius, pos, prevPos, mask, info, maskOut);
106}
107
109bool ObjectKCL::checkSpherePartialPush(f32 radius, const EGG::Vector3f &pos,
110 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
111 KCLTypeMask *maskOut, u32 timeOffset) {
112 if (!shouldCheckColPush()) {
113 return false;
114 }
115
116 calcScale(timeOffset);
117 update(timeOffset);
118
119 return m_objColMgr->checkSpherePartialPush(radius, pos, prevPos, mask, info, maskOut);
120}
121
123bool ObjectKCL::checkSphereFull(f32 radius, const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
124 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut, u32 timeOffset) {
125 if (!shouldCheckColNoPush()) {
126 return false;
127 }
128
129 calcScale(timeOffset);
130 update(timeOffset);
131
132 return m_objColMgr->checkSphereFull(radius, pos, prevPos, mask, info, maskOut);
133}
134
136bool ObjectKCL::checkSphereFullPush(f32 radius, const EGG::Vector3f &pos,
137 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
138 u32 timeOffset) {
139 return checkCollision(radius, pos, prevPos, mask, info, maskOut, timeOffset);
140}
141
143void ObjectKCL::narrScLocal(f32 radius, const EGG::Vector3f &pos, KCLTypeMask mask,
144 u32 /*timeOffset*/) {
145 m_objColMgr->narrScLocal(radius, pos, mask);
146}
147
149bool ObjectKCL::checkPointCachedPartial(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
150 KCLTypeMask mask, CollisionInfoPartial *info, KCLTypeMask *maskOut) {
151 if (!shouldCheckColNoPush()) {
152 return false;
153 }
154
155 return m_objColMgr->checkPointCachedPartial(pos, prevPos, mask, info, maskOut);
156}
157
159bool ObjectKCL::checkPointCachedPartialPush(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
160 KCLTypeMask mask, CollisionInfoPartial *info, KCLTypeMask *maskOut) {
161 if (!shouldCheckColPush()) {
162 return false;
163 }
164
165 return m_objColMgr->checkPointCachedPartialPush(pos, prevPos, mask, info, maskOut);
166}
167
169bool ObjectKCL::checkPointCachedFull(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
170 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
171 if (!shouldCheckColNoPush()) {
172 return false;
173 }
174
175 return m_objColMgr->checkPointCachedFull(pos, prevPos, mask, info, maskOut);
176}
177
179bool ObjectKCL::checkPointCachedFullPush(const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
180 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut) {
181 if (!shouldCheckColPush()) {
182 return false;
183 }
184
185 return m_objColMgr->checkPointCachedFullPush(pos, prevPos, mask, info, maskOut);
186}
187
189bool ObjectKCL::checkSphereCachedPartial(f32 radius, const EGG::Vector3f &pos,
190 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
191 KCLTypeMask *maskOut, u32 timeOffset) {
192 if (!shouldCheckColNoPush()) {
193 return false;
194 }
195
196 update(timeOffset);
197 calcScale(timeOffset);
198
199 return m_objColMgr->checkSphereCachedPartial(radius, pos, prevPos, mask, info, maskOut);
200}
201
203bool ObjectKCL::checkSphereCachedPartialPush(f32 radius, const EGG::Vector3f &pos,
204 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfoPartial *info,
205 KCLTypeMask *maskOut, u32 timeOffset) {
206 if (!shouldCheckColPush()) {
207 return false;
208 }
209
210 update(timeOffset);
211 calcScale(timeOffset);
212
213 return m_objColMgr->checkSphereCachedPartialPush(radius, pos, prevPos, mask, info, maskOut);
214}
215
217bool ObjectKCL::checkSphereCachedFull(f32 radius, const EGG::Vector3f &pos,
218 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
219 u32 timeOffset) {
220 if (!shouldCheckColNoPush()) {
221 return false;
222 }
223
224 update(timeOffset);
225 calcScale(timeOffset);
226
227 return m_objColMgr->checkSphereCachedFull(radius, pos, prevPos, mask, info, maskOut);
228}
229
231bool ObjectKCL::checkSphereCachedFullPush(f32 radius, const EGG::Vector3f &pos,
232 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
233 u32 timeOffset) {
234 return checkCollisionCached(radius, pos, prevPos, mask, info, maskOut, timeOffset);
235}
236
238void ObjectKCL::update(u32 timeOffset) {
239 u32 time = System::RaceManager::Instance()->timer() - timeOffset;
240 if (m_lastMtxUpdateFrame == static_cast<s32>(time)) {
241 return;
242 }
243
244 EGG::Matrix34f mat;
245
246 if (timeOffset == 0) {
247 calcTransform();
248 mat = m_transform;
249 } else {
250 mat = getUpdatedMatrix(timeOffset);
251 }
252
253 EGG::Matrix34f matInv;
254 mat.ps_inverse(matInv);
255 m_objColMgr->setMtx(mat);
256 m_objColMgr->setInvMtx(matInv);
257
258 m_lastMtxUpdateFrame = time;
259}
260
262void ObjectKCL::calcScale(u32 timeOffset) {
263 u32 time = System::RaceManager::Instance()->timer() - timeOffset;
264 if (m_lastScaleUpdateFrame == static_cast<s32>(time)) {
265 return;
266 }
267
268 if (time == 0) {
269 m_objColMgr->setScale(m_scale.y);
270 } else {
271 m_objColMgr->setScale(getScaleY(timeOffset));
272 }
273
274 m_lastScaleUpdateFrame = time;
275}
276
278const EGG::Matrix34f &ObjectKCL::getUpdatedMatrix(u32 /*timeOffset*/) {
279 calcTransform();
280 return m_transform;
281}
282
284bool ObjectKCL::checkCollision(f32 radius, const EGG::Vector3f &pos, const EGG::Vector3f &prevPos,
285 KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut, u32 timeOffset) {
286 if (!shouldCheckColPush()) {
287 return false;
288 }
289
290 update(timeOffset);
291 calcScale(timeOffset);
292
293 return m_objColMgr->checkSphereFullPush(radius, pos, prevPos, mask, info, maskOut);
294}
295
297bool ObjectKCL::checkCollisionCached(f32 radius, const EGG::Vector3f &pos,
298 const EGG::Vector3f &prevPos, KCLTypeMask mask, CollisionInfo *info, KCLTypeMask *maskOut,
299 u32 timeOffset) {
300 if (!shouldCheckColPush()) {
301 return false;
302 }
303
304 update(timeOffset);
305 calcScale(timeOffset);
306
307 return m_objColMgr->checkSphereCachedFullPush(radius, pos, prevPos, mask, info, maskOut);
308}
309
310} // namespace Field
A 3 x 4 matrix.
Definition Matrix.hh:8
bool ps_inverse(Matrix34f &out) const
Definition Matrix.cc:298
Pertains to collision.
A 3D float vector.
Definition Vector.hh:83