A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectAurora.cc
1#include "ObjectAurora.hh"
2
3#include "game/field/CollisionDirector.hh"
4
5#include "game/system/RaceManager.hh"
6
7namespace Field {
8
10ObjectAurora::ObjectAurora(const System::MapdataGeoObj &params) : ObjectDrivable(params) {}
11
13ObjectAurora::~ObjectAurora() = default;
14
16void ObjectAurora::init() {}
17
19u32 ObjectAurora::loadFlags() const {
20 return 1;
21}
22
24void ObjectAurora::createCollision() {}
25
27void ObjectAurora::calcCollisionTransform() {}
28
30f32 ObjectAurora::getCollisionRadius() const {
31 return COLLISION_SIZE.z + 100.0f;
32}
33
35bool ObjectAurora::checkPointPartial(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
36 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut) {
37 return checkSpherePartialImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
38}
39
41bool ObjectAurora::checkPointPartialPush(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
42 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut) {
43 return checkSpherePartialPushImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
44}
45
47bool ObjectAurora::checkPointFull(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
48 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut) {
49 return checkSphereFullImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
50}
51
53bool ObjectAurora::checkPointFullPush(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
54 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut) {
55 return checkSphereFullPushImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
56}
57
59bool ObjectAurora::checkSpherePartial(f32 radius, const EGG::Vector3f &v0, const EGG::Vector3f &v1,
60 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut, u32 timeOffset) {
61 return checkSpherePartialImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
62}
63
65bool ObjectAurora::checkSpherePartialPush(f32 radius, const EGG::Vector3f &v0,
66 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
67 KCLTypeMask *pFlagsOut, u32 timeOffset) {
68 return checkSpherePartialPushImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
69}
70
72bool ObjectAurora::checkSphereFull(f32 radius, const EGG::Vector3f &v0, const EGG::Vector3f &v1,
73 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut, u32 timeOffset) {
74 return checkSphereFullImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
75}
76
78bool ObjectAurora::checkSphereFullPush(f32 radius, const EGG::Vector3f &v0, const EGG::Vector3f &v1,
79 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut, u32 timeOffset) {
80 return checkSphereFullPushImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
81}
82
84bool ObjectAurora::checkPointCachedPartial(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
85 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut) {
86 return checkSpherePartialImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
87}
88
90bool ObjectAurora::checkPointCachedPartialPush(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
91 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut) {
92 return checkSpherePartialPushImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
93}
94
96bool ObjectAurora::checkPointCachedFull(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
97 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut) {
98 return checkSphereFullImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
99}
100
102bool ObjectAurora::checkPointCachedFullPush(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
103 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut) {
104 return checkSphereFullPushImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
105}
106
108bool ObjectAurora::checkSphereCachedPartial(f32 radius, const EGG::Vector3f &v0,
109 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
110 KCLTypeMask *pFlagsOut, u32 timeOffset) {
111 return checkSpherePartialImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
112}
113
115bool ObjectAurora::checkSphereCachedPartialPush(f32 radius, const EGG::Vector3f &v0,
116 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
117 KCLTypeMask *pFlagsOut, u32 timeOffset) {
118 return checkSpherePartialPushImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
119}
120
122bool ObjectAurora::checkSphereCachedFull(f32 radius, const EGG::Vector3f &v0,
123 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
124 u32 timeOffset) {
125 return checkSphereFullImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
126}
127
129bool ObjectAurora::checkSphereCachedFullPush(f32 radius, const EGG::Vector3f &v0,
130 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
131 u32 timeOffset) {
132 return checkSphereFullPushImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
133}
134
136bool ObjectAurora::checkSpherePartialImpl(f32 radius, const EGG::Vector3f &v0,
137 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
138 KCLTypeMask *pFlagsOut, u32 timeOffset) {
139 return checkSpherePartialImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset, false);
140}
141
143bool ObjectAurora::checkSpherePartialPushImpl(f32 radius, const EGG::Vector3f &v0,
144 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
145 KCLTypeMask *pFlagsOut, u32 timeOffset) {
146 return checkSpherePartialImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset, true);
147}
148
150bool ObjectAurora::checkSphereFullImpl(f32 radius, const EGG::Vector3f &v0, const EGG::Vector3f &v1,
151 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut, u32 timeOffset) {
152 return checkSphereFullImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset, false);
153}
154
156bool ObjectAurora::checkSphereFullPushImpl(f32 radius, const EGG::Vector3f &v0,
157 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
158 u32 timeOffset) {
159 return checkSphereFullImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset, true);
160}
161
165bool ObjectAurora::checkSpherePartialImpl(f32 radius, const EGG::Vector3f &v0,
166 const EGG::Vector3f & /*v1*/, KCLTypeMask flags, CollisionInfoPartial *pInfo,
167 KCLTypeMask *pFlagsOut, u32 timeOffset, bool push) {
168 EGG::Vector3f vel = v0 - m_pos;
169
170 if (vel.z < 0.0f || vel.z > COLLISION_SIZE.z || EGG::Mathf::abs(vel.x) > COLLISION_SIZE.x) {
171 return false;
172 }
173
174 if (!(flags & KCL_TYPE_FLOOR)) {
175 return false;
176 }
177
178 u32 t = timeOffset + System::RaceManager::Instance()->timer();
179 EGG::Vector3f bbox;
180 EGG::Vector3f fnrm;
181 f32 dist;
182
183 if (!calcCollision(radius, vel, t, bbox, fnrm, dist)) {
184 return false;
185 }
186
187 if (pInfo) {
188 pInfo->bbox.min = pInfo->bbox.min.minimize(bbox);
189 pInfo->bbox.max = pInfo->bbox.max.maximize(bbox);
190 }
191
192 if (pFlagsOut) {
193 auto *colDirector = CollisionDirector::Instance();
194
195 if (push) {
196 colDirector->pushCollisionEntry(dist, pFlagsOut, KCL_TYPE_BIT(COL_TYPE_ROAD2),
198 colDirector->setCurrentCollisionVariant(7);
199 colDirector->setCurrentCollisionTrickable(true);
200 } else {
202 }
203
204 if (vel.z > COLLISION_SIZE.z - 600.0f * 4.0f) {
205 if (push) {
206 colDirector->pushCollisionEntry(dist, pFlagsOut, KCL_TYPE_BIT(COL_TYPE_BOOST_RAMP),
208 } else {
210 }
211 }
212 }
213
214 return true;
215}
216
220bool ObjectAurora::checkSphereFullImpl(f32 radius, const EGG::Vector3f &v0,
221 const EGG::Vector3f & /*v1*/, KCLTypeMask flags, CollisionInfo *pInfo,
222 KCLTypeMask *pFlagsOut, u32 timeOffset, bool push) {
223 EGG::Vector3f vel = v0 - m_pos;
224
225 if (vel.z < 0.0f || vel.z > COLLISION_SIZE.z || EGG::Mathf::abs(vel.x) > COLLISION_SIZE.x) {
226 return false;
227 }
228
229 if (!(flags & KCL_TYPE_FLOOR)) {
230 return false;
231 }
232
233 u32 t = timeOffset + System::RaceManager::Instance()->timer();
234 EGG::Vector3f bbox;
235 EGG::Vector3f fnrm;
236 f32 dist;
237
238 if (!calcCollision(radius, vel, t, bbox, fnrm, dist)) {
239 return false;
240 }
241
242 if (pInfo) {
243 pInfo->bbox.min = pInfo->bbox.min.minimize(bbox);
244 pInfo->bbox.max = pInfo->bbox.max.maximize(bbox);
245
246 pInfo->updateFloor(dist, fnrm);
247 }
248
249 if (pFlagsOut) {
250 auto *colDirector = CollisionDirector::Instance();
251
252 if (push) {
253 colDirector->pushCollisionEntry(dist, pFlagsOut, KCL_TYPE_BIT(COL_TYPE_ROAD2),
255 colDirector->setCurrentCollisionVariant(7);
256 colDirector->setCurrentCollisionTrickable(true);
257 } else {
259 }
260
261 if (vel.z > COLLISION_SIZE.z - 600.0f * 4.0f) {
262 if (push) {
263 colDirector->pushCollisionEntry(dist, pFlagsOut, KCL_TYPE_BIT(COL_TYPE_BOOST_RAMP),
265 } else {
267 }
268 }
269 }
270
271 return true;
272}
273
280bool ObjectAurora::calcCollision(f32 radius, const EGG::Vector3f &vel, u32 time, EGG::Vector3f &v0,
281 EGG::Vector3f &fnrm, f32 &dist) {
282 constexpr f32 INITIAL_FREQUENCY = 1.0f;
283 constexpr f32 MAX_FREQUENCY = 4.0f;
284 constexpr f32 PHASE_SHIFT_SECONDS = 30.0f;
285 constexpr f32 COLLISION_DISTANCE_THRESHOLD = 600.0f;
286 constexpr f32 UPWARP_THRESHOLD = 300.0f;
287 constexpr f32 UPWARP_DIST_SCALAR = 0.2f;
288
289 f32 minsNormalized = (static_cast<f32>(time) / 60.0f - PHASE_SHIFT_SECONDS) / 60.0f;
290 f32 frequency = std::min(INITIAL_FREQUENCY + minsNormalized * minsNormalized, MAX_FREQUENCY);
291 f32 velPeriod = (F_PI * (2.0f * vel.z)) / COLLISION_SIZE.z;
292
293 f32 result = EGG::Mathf::SinFIdx(
294 RAD2FIDX * (velPeriod * frequency + (F_PI * static_cast<f32>(time) / 50.0f)));
295 result = radius - (vel.y - velPeriod * 80.0f * result);
296
297 // We're not colliding if we're 600 units away or if the road is now behind us.
298 if (result <= 0.0f || result >= COLLISION_DISTANCE_THRESHOLD) {
299 return false;
300 }
301
302 // Responsible for the sudden upwards snap that can occur when falling off.
303 if (result > UPWARP_THRESHOLD) {
304 result *= UPWARP_DIST_SCALAR;
305 }
306
307 fnrm = EGG::Vector3f::ey;
308 v0 = fnrm * result;
309 dist = result;
310
311 return true;
312}
313
314} // namespace Field
@ COL_TYPE_BOOST_RAMP
Trickable. Variant affects boost duration.
@ COL_TYPE_ROAD2
COL_TYPE_ROAD but with more variants.
@ COL_TYPE_ROTATING_ROAD
Chain Chomp Roulette.
#define KCL_TYPE_BIT(x)
#define KCL_TYPE_FLOOR
0x20E80FFF - Any KCL that the player or items can drive/land on.
Pertains to collision.
A 3D float vector.
Definition Vector.hh:83
Vector3f maximize(const Vector3f &rhs) const
Returns a vector whose elements are the max of the elements of both vectors.
Definition Vector.cc:65
Vector3f minimize(const Vector3f &rhs) const
Returns a vector whose elements are the min of the elements of both vectors.
Definition Vector.cc:77