A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectTuribashi.cc
1#include "ObjectTuribashi.hh"
2
3#include "game/field/CollisionDirector.hh"
4
5#include "game/system/RaceManager.hh"
6
7namespace Field {
8
10ObjectTuribashi::ObjectTuribashi(const System::MapdataGeoObj &params) : ObjectDrivable(params) {}
11
13ObjectTuribashi::~ObjectTuribashi() = default;
14
16bool ObjectTuribashi::checkPointPartial(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
17 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut) {
18 return checkSpherePartialImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
19}
20
22bool ObjectTuribashi::checkPointPartialPush(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
23 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut) {
24 return checkSpherePartialPushImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
25}
26
28bool ObjectTuribashi::checkPointFull(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
29 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut) {
30 return checkSphereFullImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
31}
32
34bool ObjectTuribashi::checkPointFullPush(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
35 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut) {
36 return checkSphereFullPushImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
37}
38
40bool ObjectTuribashi::checkSpherePartial(f32 radius, const EGG::Vector3f &v0,
41 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
42 KCLTypeMask *pFlagsOut, u32 timeOffset) {
43 return checkSpherePartialImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
44}
45
47bool ObjectTuribashi::checkSpherePartialPush(f32 radius, const EGG::Vector3f &v0,
48 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
49 KCLTypeMask *pFlagsOut, u32 timeOffset) {
50 return checkSpherePartialPushImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
51}
52
54bool ObjectTuribashi::checkSphereFull(f32 radius, const EGG::Vector3f &v0, const EGG::Vector3f &v1,
55 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut, u32 timeOffset) {
56 return checkSphereFullImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
57}
58
60bool ObjectTuribashi::checkSphereFullPush(f32 radius, const EGG::Vector3f &v0,
61 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
62 u32 timeOffset) {
63 return checkSphereFullPushImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
64}
65
67bool ObjectTuribashi::checkPointCachedPartial(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
68 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut) {
69 return checkSpherePartialImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
70}
71
73bool ObjectTuribashi::checkPointCachedPartialPush(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
74 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut) {
75 return checkSpherePartialPushImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
76}
77
79bool ObjectTuribashi::checkPointCachedFull(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
80 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut) {
81 return checkSphereFullImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
82}
83
85bool ObjectTuribashi::checkPointCachedFullPush(const EGG::Vector3f &v0, const EGG::Vector3f &v1,
86 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut) {
87 return checkSphereFullPushImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
88}
89
91bool ObjectTuribashi::checkSphereCachedPartial(f32 radius, const EGG::Vector3f &v0,
92 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
93 KCLTypeMask *pFlagsOut, u32 timeOffset) {
94 return checkSpherePartialImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
95}
96
98bool ObjectTuribashi::checkSphereCachedPartialPush(f32 radius, const EGG::Vector3f &v0,
99 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
100 KCLTypeMask *pFlagsOut, u32 timeOffset) {
101 return checkSpherePartialPushImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
102}
103
105bool ObjectTuribashi::checkSphereCachedFull(f32 radius, const EGG::Vector3f &v0,
106 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
107 u32 timeOffset) {
108 return checkSphereFullImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
109}
110
112bool ObjectTuribashi::checkSphereCachedFullPush(f32 radius, const EGG::Vector3f &v0,
113 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
114 u32 timeOffset) {
115 return checkSphereFullPushImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
116}
117
119bool ObjectTuribashi::checkSpherePartialImpl(f32 radius, const EGG::Vector3f &v0,
120 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
121 KCLTypeMask *pFlagsOut, u32 timeOffset) {
122 return checkSphereImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset, false);
123}
124
126bool ObjectTuribashi::checkSpherePartialPushImpl(f32 radius, const EGG::Vector3f &v0,
127 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
128 KCLTypeMask *pFlagsOut, u32 timeOffset) {
129 return checkSphereImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset, true);
130}
131
133bool ObjectTuribashi::checkSphereFullImpl(f32 radius, const EGG::Vector3f &v0,
134 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
135 u32 timeOffset) {
136 return checkSphereImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset, false);
137}
138
140bool ObjectTuribashi::checkSphereFullPushImpl(f32 radius, const EGG::Vector3f &v0,
141 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
142 u32 timeOffset) {
143 return checkSphereImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset, true);
144}
145
153template <typename T>
154 requires std::is_same_v<T, CollisionInfo> || std::is_same_v<T, CollisionInfoPartial>
155bool ObjectTuribashi::checkSphereImpl(f32 radius, const EGG::Vector3f &v0,
156 const EGG::Vector3f & /*v1*/, KCLTypeMask flags, T *pInfo, KCLTypeMask *pFlagsOut,
157 u32 timeOffset, bool push) {
158 constexpr u16 PERIOD = 160; // Framecount of a full bridge swing.
159 constexpr f32 HEIGHT = 2000.0f; // Distance between min/max positions along the angled bridge.
160
161 // This check normally happens after the stage check,
162 // but there's no difference in behavior if we check earlier.
163 if ((flags & 1) == 0) {
164 return false;
165 }
166
167 EGG::Vector3f deltaPos = v0 - m_pos;
168
169 if (EGG::Mathf::abs(deltaPos.z) > RADIUS) {
170 return false;
171 }
172
173 const auto *raceMgr = System::RaceManager::Instance();
174 f32 angle = 0.0f;
175
176 if (raceMgr->isStageReached(System::RaceManager::Stage::Race)) {
177 f32 phase = -deltaPos.z / RADIUS;
178 f32 lower = phase - 1.0f;
179 f32 higher = phase + 1.0f;
180 u32 t = (timeOffset + raceMgr->timer()) % PERIOD;
181 f32 sin = EGG::Mathf::SinFIdx(
182 (t * 2.0f * F_PI / static_cast<f32>(PERIOD) + 0.7f * phase) * RAD2FIDX);
183 angle = 0.12f * (higher * (higher * (lower * (lower * sin))));
184 }
185
186 auto [sinfidx, cosfidx] = EGG::Mathf::SinCosFIdx(RAD2FIDX * angle);
187
188 f32 phase = deltaPos.z / RADIUS;
189 f32 cos = EGG::Mathf::CosFIdx(RAD2FIDX * (0.5f * (F_PI * (37.0f * phase))));
190 f32 base = HEIGHT * -0.5f;
191 f32 dist = base +
192 (cosfidx * (-deltaPos.y - base) +
193 (-deltaPos.x * sinfidx +
194 (radius + (EGG::Mathf::abs(30.0f * cos) + 25.0f) +
195 0.156f * deltaPos.z)));
196
197 if (0.0f >= dist || dist >= 600.0f) {
198 return false;
199 }
200
201 if (300.0f < dist) {
202 dist *= 0.2f;
203 }
204
205 if (pInfo) {
206 EGG::Vector3f scaledY = EGG::Vector3f::ey * dist;
207 pInfo->bbox.min = pInfo->bbox.min.minimize(scaledY);
208 pInfo->bbox.max = pInfo->bbox.max.maximize(scaledY);
209
210 if constexpr (std::is_same_v<T, CollisionInfo>) {
211 pInfo->updateFloor(dist, EGG::Vector3f(sinfidx, cosfidx, 0.0f));
212 }
213 }
214
215 if (pFlagsOut) {
216 if (push) {
217 auto *colDirector = CollisionDirector::Instance();
218 colDirector->pushCollisionEntry(dist, pFlagsOut, KCL_TYPE_BIT(COL_TYPE_ROAD), 0);
219 colDirector->setCurrentCollisionVariant(4);
220 colDirector->setCurrentCollisionTrickable(false);
221 } else {
222 *pFlagsOut |= KCL_TYPE_BIT(COL_TYPE_ROAD);
223 }
224 }
225
226 return true;
227}
228
229} // namespace Field
@ COL_TYPE_ROAD
Default road.
#define KCL_TYPE_BIT(x)
Pertains to collision.
A 3D float vector.
Definition Vector.hh:87