1#include "ObjectTwistedWay.hh"
3#include "game/field/CollisionDirector.hh"
5#include "game/system/RaceManager.hh"
7#include <egg/math/Math.hh>
15ObjectTwistedWay::~ObjectTwistedWay() =
default;
18void ObjectTwistedWay::calc() {
19 if (!System::RaceManager::Instance()->isStageReached(System::RaceManager::Stage::Race)) {
26 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut) {
27 return checkSpherePartialImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
32 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut) {
33 return checkSpherePartialPushImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
38 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut) {
39 return checkSphereFullImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
44 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut) {
45 return checkSphereFullPushImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
49bool ObjectTwistedWay::checkSpherePartial(f32 radius,
const EGG::Vector3f &v0,
50 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
51 KCLTypeMask *pFlagsOut,
u32 timeOffset) {
52 return checkSpherePartialImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
56bool ObjectTwistedWay::checkSpherePartialPush(f32 radius,
const EGG::Vector3f &v0,
57 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
58 KCLTypeMask *pFlagsOut,
u32 timeOffset) {
59 return checkSpherePartialPushImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
64 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
u32 timeOffset) {
65 return checkSphereFullImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
69bool ObjectTwistedWay::checkSphereFullPush(f32 radius,
const EGG::Vector3f &v0,
70 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
72 return checkSphereFullPushImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
77 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut) {
78 return checkSpherePartialImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
83 KCLTypeMask flags, CollisionInfoPartial *pInfo, KCLTypeMask *pFlagsOut) {
84 return checkSpherePartialPushImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
89 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut) {
90 return checkSphereFullImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
95 KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut) {
96 return checkSphereFullPushImpl(0.0f, v0, v1, flags, pInfo, pFlagsOut, 0);
100bool ObjectTwistedWay::checkSphereCachedPartial(f32 radius,
const EGG::Vector3f &v0,
101 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
102 KCLTypeMask *pFlagsOut,
u32 timeOffset) {
103 return checkSpherePartialImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
107bool ObjectTwistedWay::checkSphereCachedPartialPush(f32 radius,
const EGG::Vector3f &v0,
108 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
109 KCLTypeMask *pFlagsOut,
u32 timeOffset) {
110 return checkSpherePartialPushImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
114bool ObjectTwistedWay::checkSphereCachedFull(f32 radius,
const EGG::Vector3f &v0,
115 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
117 return checkSphereFullImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
121bool ObjectTwistedWay::checkSphereCachedFullPush(f32 radius,
const EGG::Vector3f &v0,
122 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
124 return checkSphereFullPushImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset);
128bool ObjectTwistedWay::checkSpherePartialImpl(f32 radius,
const EGG::Vector3f &v0,
129 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
130 KCLTypeMask *pFlagsOut,
u32 timeOffset) {
131 return checkSphereImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset,
false);
135bool ObjectTwistedWay::checkSpherePartialPushImpl(f32 radius,
const EGG::Vector3f &v0,
136 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfoPartial *pInfo,
137 KCLTypeMask *pFlagsOut,
u32 timeOffset) {
138 return checkSphereImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset,
true);
142bool ObjectTwistedWay::checkSphereFullImpl(f32 radius,
const EGG::Vector3f &v0,
143 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
145 return checkSphereImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset,
false);
149bool ObjectTwistedWay::checkSphereFullPushImpl(f32 radius,
const EGG::Vector3f &v0,
150 const EGG::Vector3f &v1, KCLTypeMask flags, CollisionInfo *pInfo, KCLTypeMask *pFlagsOut,
152 return checkSphereImpl(radius, v0, v1, flags, pInfo, pFlagsOut, timeOffset,
true);
159 requires std::is_same_v<T, CollisionInfo> || std::is_same_v<T, CollisionInfoPartial>
162 u32 timeOffset,
bool push) {
165 if (EGG::Mathf::abs(relPos.z) > HALF_DEPTH || EGG::Mathf::abs(relPos.x) > WIDTH * 2.0f) {
169 auto *raceMgr = System::RaceManager::Instance();
170 bool isInRace = raceMgr->isStageReached(System::RaceManager::Stage::Race);
172 u32 frameCount = timeOffset + (isInRace ? raceMgr->timer() : m_introTimer);
173 u32 t = (frameCount % PERIOD_LENGTH) * 2;
175 f32 angle = isInRace ? calcWave(-relPos.z / HALF_DEPTH, t) : 0.0f;
179 hasCol |= checkWallCollision(angle, radius, t, relPos, pInfo, pFlagsOut, push);
183 hasCol |= checkFloorCollision(angle, radius, relPos, pInfo, pFlagsOut, push);
190 requires std::is_same_v<T, CollisionInfo> || std::is_same_v<T, CollisionInfoPartial>
191bool ObjectTwistedWay::checkWallCollision(f32 angle, f32 radius, u32 t,
const EGG::Vector3f &relPos,
193 auto [sin, cos] = EGG::Mathf::SinCosFIdx(RAD2FIDX * angle);
194 f32 yProj = sin * (relPos.y - WIDTH * 0.5f);
195 f32 dist = radius + (yProj - cos * (relPos.x + WIDTH));
201 dist = radius - (yProj - cos * (relPos.x - WIDTH));
214 pInfo->bbox.min = pInfo->bbox.min.minimize(bbox);
215 pInfo->bbox.max = pInfo->bbox.max.maximize(bbox);
217 if constexpr (std::is_same_v<T, CollisionInfo>) {
218 pInfo->updateWall(dist, fnrm);
224 CollisionDirector::Instance()->pushCollisionEntry(dist, pFlagsOut,
234 angle = calcWave(0.0f, t);
238 if (!checkPoleCollision(radius, angle, relPos, bbox, wnrm, dist)) {
243 pInfo->bbox.min = pInfo->bbox.min.minimize(bbox);
244 pInfo->bbox.max = pInfo->bbox.max.maximize(bbox);
246 if constexpr (std::is_same_v<T, CollisionInfo>) {
247 pInfo->updateWall(dist, wnrm);
253 CollisionDirector::Instance()->pushCollisionEntry(dist, pFlagsOut,
264 requires std::is_same_v<T, CollisionInfo> || std::is_same_v<T, CollisionInfoPartial>
265bool ObjectTwistedWay::checkFloorCollision(f32 angle, f32 radius,
const EGG::Vector3f &relPos,
266 T *pInfo, KCLTypeMask *pFlagsOut,
bool push) {
267 constexpr f32 HALF_WIDTH = WIDTH * -0.5f;
268 constexpr f32 TRICKABLE_RADIUS_FACTOR = 0.6f;
270 auto [sin, cos] = EGG::Mathf::SinCosFIdx(RAD2FIDX * angle);
271 f32 dist = HALF_WIDTH + ((radius + -relPos.x * sin) + cos * (-relPos.y - HALF_WIDTH));
281 pInfo->bbox.min = pInfo->bbox.min.minimize(bbox);
282 pInfo->bbox.max = pInfo->bbox.max.maximize(bbox);
284 if constexpr (std::is_same_v<T, CollisionInfo>) {
285 pInfo->updateFloor(dist, fnrm);
291 auto *colDir = CollisionDirector::Instance();
293 colDir->setCurrentCollisionVariant(2);
295 if (EGG::Mathf::abs(relPos.z) < HALF_DEPTH * TRICKABLE_RADIUS_FACTOR) {
296 colDir->setCurrentCollisionTrickable(
true);
307bool ObjectTwistedWay::checkPoleCollision(f32 radius, f32 angle,
const EGG::Vector3f &relPos,
310 constexpr f32 POLE_RADIUS = 227.0f;
312 auto [sin, cos] = EGG::Mathf::SinCosFIdx(angle * RAD2FIDX);
315 wnrm = relPos - (sinCos * (relPos - HEIGHT).
dot(sinCos) + HEIGHT);
316 f32 diff = POLE_RADIUS + radius - wnrm.
length();
329f32 ObjectTwistedWay::calcWave(f32 zPercent,
u32 t) {
330 constexpr f32 WAVINESS = 4.0f;
331 constexpr f32 AMPLITUDE = 0.2f;
333 f32 angle = EGG::Mathf::SinFIdx(
334 (
static_cast<f32
>(t) * F_PI / PERIOD_LENGTH + WAVINESS * zPercent) * RAD2FIDX);
336 f32 low = zPercent - 1.0f;
337 f32 high = zPercent + 1.0f;
339 return AMPLITUDE * (high * (high * (low * (low * angle))));
@ COL_TYPE_WALL
Default wall.
@ COL_TYPE_ROAD
Default road.
f32 dot(const Vector3f &rhs) const
The dot product between two vectors.
f32 length() const
The square root of the vector's dot product.