Skip to content

Commit

Permalink
Wall collision infrastructure
Browse files Browse the repository at this point in the history
  • Loading branch information
malleoz committed May 30, 2024
1 parent 86701d5 commit 8fefcb0
Show file tree
Hide file tree
Showing 15 changed files with 245 additions and 47 deletions.
2 changes: 2 additions & 0 deletions source/game/kart/CollisionGroup.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Kart {
void CollisionData::reset() {
tangentOff.setZero();
floorNrm.setZero();
wallNrm.setZero();
vel.setZero();
relPos.setZero();
movement.setZero();
Expand All @@ -16,6 +17,7 @@ void CollisionData::reset() {
intensity = 0.0f;

bFloor = false;
bWall = false;
bSoftWall = false;
bTrickable = false;
}
Expand Down
2 changes: 2 additions & 0 deletions source/game/kart/CollisionGroup.hh
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct CollisionData {

EGG::Vector3f tangentOff;
EGG::Vector3f floorNrm;
EGG::Vector3f wallNrm;
EGG::Vector3f noBounceWallNrm;
EGG::Vector3f vel;
EGG::Vector3f relPos;
Expand All @@ -30,6 +31,7 @@ struct CollisionData {
s32 intensity; ///< The KCL flag's "wheel depth"

bool bFloor; ///< Set if colliding with KCL which satisfies #KCL_TYPE_FLOOR
bool bWall; ///< Set if colliding with KCL which satisfies #KCL_TYPE_WALL
bool bSoftWall;
bool bTrickable;
};
Expand Down
22 changes: 16 additions & 6 deletions source/game/kart/KartCollide.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ void KartCollide::calcHitboxes() {
void KartCollide::findCollision() {
calcBodyCollision(move()->totalScale(), fullRot(), scale());

auto &colData = collisionData();
if (colData.bWall) {
colData.wallNrm.normalise();
}

f32 fVar1;
if (state()->isBoost()) {
fVar1 = 0.0f;
Expand Down Expand Up @@ -99,11 +104,11 @@ void KartCollide::FUN_80572F4C() {
void KartCollide::FUN_805B72B8(f32 param_1, f32 param_2, bool lockXZ, bool addExtVelY) {
const auto &colData = collisionData();

if (!colData.bFloor) {
if (!colData.bFloor && !colData.bWall) {
return;
}

EGG::Vector3f collisionDir = colData.floorNrm;
EGG::Vector3f collisionDir = colData.floorNrm + colData.wallNrm;
collisionDir.normalise();

f32 directionalVelocity = colData.vel.dot(collisionDir);
Expand Down Expand Up @@ -544,9 +549,14 @@ void KartCollide::applySomeFloorMoment(f32 down, f32 rate, CollisionGroup *hitbo
/// @addr{0x805B6A9C}
/// @rename
bool KartCollide::FUN_805B6A9C(CollisionData &collisionData, const Hitbox &hitbox,
EGG::BoundBox3f &minMax, EGG::Vector3f &relPos, s32 &count, Field::KCLTypeMask &maskOut,
const Field::CourseColMgr::CollisionInfo &colInfo) {
if (!!(maskOut & KCL_TYPE_FLOOR)) {
EGG::BoundBox3f &minMax, EGG::Vector3f &relPos, s32 &count,
const Field::KCLTypeMask &maskOut, const Field::CourseColMgr::CollisionInfo &colInfo) {
if (maskOut & KCL_TYPE_WALL) {
collisionData.wallNrm += colInfo.wallNrm;
collisionData.bWall = true;
}

if (maskOut & KCL_TYPE_FLOOR) {
collisionData.floorNrm += colInfo.floorNrm;
collisionData.bFloor = true;
}
Expand All @@ -571,7 +581,7 @@ void KartCollide::applyBodyCollision(CollisionData &collisionData, const EGG::Ve
const EGG::Vector3f &posRel, s32 count) {
setPos(pos() + movement);

if (!collisionData.bFloor) {
if (!collisionData.bFloor && collisionData.bWall) {
collisionData.movement = movement;
}

Expand Down
2 changes: 1 addition & 1 deletion source/game/kart/KartCollide.hh
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public:
bool b1, bool b2, bool b3);

bool FUN_805B6A9C(CollisionData &collisionData, const Hitbox &hitbox, EGG::BoundBox3f &minMax,
EGG::Vector3f &relPos, s32 &count, Field::KCLTypeMask &maskOut,
EGG::Vector3f &relPos, s32 &count, const Field::KCLTypeMask &maskOut,
const Field::CourseColMgr::CollisionInfo &colInfo);
void applyBodyCollision(CollisionData &collisionData, const EGG::Vector3f &movement,
const EGG::Vector3f &posRel, s32 count);
Expand Down
13 changes: 13 additions & 0 deletions source/game/kart/KartDynamics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,19 @@ void KartDynamics::applySuspensionWrench(const EGG::Vector3f &p, const EGG::Vect
m_totalTorque += torque;
}

/// @addr{0x805B5CE8}
/// @stage 2
/// @brief Applies a force linearly and rotationally to the kart.
void KartDynamics::applyWrenchScaled(const EGG::Vector3f &p, const EGG::Vector3f &f, f32 scale) {
m_totalForce += f;

EGG::Vector3f invForceRot = m_fullRot.rotateVectorInv(f);
EGG::Vector3f relPos = p - m_pos;
EGG::Vector3f invPosRot = m_fullRot.rotateVectorInv(relPos);

m_totalTorque += invPosRot.cross(invForceRot) * scale;
}

void KartDynamics::setPos(const EGG::Vector3f &pos) {
m_pos = pos;
}
Expand Down
1 change: 1 addition & 0 deletions source/game/kart/KartDynamics.hh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public:

void applySuspensionWrench(const EGG::Vector3f &p, const EGG::Vector3f &Flinear,
const EGG::Vector3f &Frot, bool ignoreX);
void applyWrenchScaled(const EGG::Vector3f &p, const EGG::Vector3f &f, f32 scale);

/// @beginSetters
void setPos(const EGG::Vector3f &pos);
Expand Down
133 changes: 119 additions & 14 deletions source/game/kart/KartMove.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ KartMove::KartMove() : m_smoothedUp(EGG::Vector3f::ey), m_scale(1.0f, 1.0f, 1.0f
m_bPadJump = false;
m_bSsmtCharged = false;
m_bSsmtLeeway = false;
m_bWallBounce = false;
m_jump = nullptr;
}

Expand Down Expand Up @@ -83,6 +84,7 @@ void KartMove::calcTurn() {
void KartMove::setTurnParams() {
init(false, false);
m_dir = bodyFront();
m_lastDir = m_dir;
m_vel1Dir = m_dir;
m_landingDir = m_dir;
}
Expand All @@ -99,6 +101,7 @@ void KartMove::init(bool b1, bool b2) {
m_up = EGG::Vector3f::ey;
m_smoothedUp = EGG::Vector3f::ey;
m_vel1Dir = EGG::Vector3f::ez;
m_lastDir = EGG::Vector3f::ez;
m_dir = EGG::Vector3f::ez;
m_landingDir = EGG::Vector3f::ez;
m_dirDiff = EGG::Vector3f::zero;
Expand Down Expand Up @@ -147,6 +150,9 @@ void KartMove::init(bool b1, bool b2) {
m_bPadBoost = false;
m_bRampBoost = false;
m_bPadJump = false;
m_bSsmtCharged = false;
m_bSsmtLeeway = false;
m_bWallBounce = false;
m_jump->reset();
m_rawTurn = 0.0f;
}
Expand Down Expand Up @@ -724,7 +730,7 @@ void KartMove::calcRotation() {

if (!drifting) {
bool noTurn = false;
if (EGG::Mathf::abs(m_speed) < 1.0f) {
if (!state()->isWallCollision() && EGG::Mathf::abs(m_speed) < 1.0f) {
if (!(state()->isHop() && m_hopPosY > 0.0f)) {
turn = 0.0f;
noTurn = true;
Expand Down Expand Up @@ -769,8 +775,11 @@ void KartMove::calcRotation() {
void KartMove::calcVehicleSpeed() {
const auto *raceMgr = System::RaceManager::Instance();
if (raceMgr->isStageReached(System::RaceManager::Stage::Race)) {
if (!state()->isDriftManual()) {
m_speed += dynamics()->speedFix();
f32 speedFix = dynamics()->speedFix();
if ((state()->isWallCollisionStart() || state()->wallBonkTimer() == 0 ||
EGG::Mathf::abs(speedFix) >= 3.0f) &&
!state()->isDriftManual()) {
m_speed += speedFix;
}
}

Expand Down Expand Up @@ -905,8 +914,12 @@ void KartMove::calcAcceleration() {
dVar17 = std::max(dVar17, 100.0f);
}

if (m_softSpeedLimit > dVar17) {
// If not colliding with a wall
m_lastDir = (m_speed > 0.0f) ? 1.0f * m_dir : -1.0f * m_dir;

f32 local_c8 = 1.0f;
dVar17 *= calcWallCollisionSpeedFactor(local_c8);

if (!state()->isWallCollision()) {
m_softSpeedLimit = std::max(m_softSpeedLimit - 3.0f, dVar17);
} else {
m_softSpeedLimit = dVar17;
Expand All @@ -920,6 +933,8 @@ void KartMove::calcAcceleration() {
m_speed = std::max(m_speed, m_jumpPadMinSpeed);
}

calcWallCollisionStart(local_c8);

m_speedRatioCapped = std::min(1.0f, EGG::Mathf::abs(m_speed / m_baseSpeed));

EGG::Vector3f crossVec = m_smoothedUp.cross(m_dir);
Expand Down Expand Up @@ -957,6 +972,83 @@ void KartMove::calcAcceleration() {
}
}

/// @addr{0x8057B108}
/// @stage 2
/// @brief Every frame, computes a speed scalar if we are colliding with a wall.
f32 KartMove::calcWallCollisionSpeedFactor(f32 &f1) {
if (!state()->isWallCollision()) {
return 1.0f;
}

cancelWheelie();

EGG::Vector3f wallNrm = collisionData().wallNrm;
if (wallNrm.y > 0.0f) {
wallNrm.y = 0.0f;
wallNrm.normalise();
}

f32 dot = m_lastDir.dot(wallNrm);

if (dot < 0.0f) {
f1 = std::max(0.0f, dot + 1.0f);
return std::min(1.0f, f1 * 0.4f);
}

return 1.0f;
}

/// @addr{0x8057B2A0}
/// @stage 2
/// @brief If we started to collide with a wall this frame, applies rotation.
void KartMove::calcWallCollisionStart(f32 param_2) {
m_bWallBounce = false;

if (!state()->isWallCollisionStart()) {
return;
}

m_dir = bodyFront();
m_vel1Dir = m_dir;
m_landingDir = m_dir;

if (param_2 < 0.9f) {
f32 speedDiff = m_lastSpeed - m_speed;

if (speedDiff > 30.0f) {
m_bWallBounce = true;
const CollisionData &colData = collisionData();
EGG::Vector3f newPos = colData.relPos + pos();
f32 dot = -bodyUp().dot(colData.relPos) * 0.5f;
EGG::Vector3f scaledUp = dot * bodyUp();
newPos -= scaledUp;

speedDiff = std::min(60.0f, speedDiff);
EGG::Vector3f scaledWallNrm = speedDiff * colData.wallNrm;

auto projAndRej = scaledWallNrm.projAndRej(m_vel1Dir);
projAndRej.first *= 0.3f;
projAndRej.second *= 0.9f;

if (state()->isBoost()) {
projAndRej.first = EGG::Vector3f::zero;
projAndRej.second = EGG::Vector3f::zero;
}

if (bodyFront().dot(colData.wallNrm) > 0.0f) {
projAndRej.first = EGG::Vector3f::zero;
}
projAndRej.second *= 0.9f;

EGG::Vector3f projRejSum = projAndRej.first + projAndRej.second;
f32 bumpDeviation =
state()->isTouchingGround() ? param()->stats().bumpDeviationLevel : 0.0f;

dynamics()->applyWrenchScaled(newPos, projRejSum, bumpDeviation);
}
}
}

/// @stage 1+
/// @brief STAGE Computes the x-component of angular velocity based on the kart's speed.
/// @addr{0x8057D1D4}
Expand Down Expand Up @@ -988,7 +1080,11 @@ void KartMove::calcStandstillBoostRot() {
}
}

m_standStillBoostRot += scalar * (next - m_standStillBoostRot);
if (m_bWallBounce) {
m_standStillBoostRot = isBike() ? next * 3.0f : next * 10.0f;
} else {
m_standStillBoostRot += scalar * (next - m_standStillBoostRot);
}
}

/// @stage 2
Expand Down Expand Up @@ -1589,13 +1685,24 @@ void KartMoveBike::calcWheelie() {
EGG::Vector3f angVel2 = dynamics()->angVel2();
angVel2.x -= m_wheelieRot * (1.0f - EGG::Mathf::abs(vel1DirUp));
dynamics()->setAngVel2(angVel2);
} else {
cancelWheelie();
}

state()->setWheelieRot(true);
} else {
state()->setWheelieRot(false);
}
}

/// @addr{0x805883C4}
/// @stage 1+
/// @brief Clears the wheelie bit flag and resets the rotation decrement.
void KartMoveBike::cancelWheelie() {
state()->setWheelie(false);
m_wheelieRotDec = 0.0f;
}

/// @stage 2
/// @brief Virtual function that just cancels wheelies when you hop.
/// @addr{0x80588B30}
Expand Down Expand Up @@ -1654,7 +1761,12 @@ void KartMoveBike::tryStartWheelie() {

if (!state()->isWheelie()) {
if (dpadUp && state()->isTouchingGround()) {
if (state()->isDriftManual() || state()->isHop() || state()->isDriftAuto()) {
if (state()->isDriftManual() || state()->isWallCollision() || state()->isHop() ||
state()->isDriftAuto()) {
return;
}

if (m_wheelieCooldown > 0) {
return;
}

Expand All @@ -1666,13 +1778,6 @@ void KartMoveBike::tryStartWheelie() {
}
}

/// @brief STAGE 1+ - Clears the wheelie bit flag and resets the rotation decrement.
/// @addr{0x805883C4}
void KartMoveBike::cancelWheelie() {
state()->setWheelie(false);
m_wheelieRotDec = 0.0f;
}

/// @addr{0x805896BC}
f32 KartMoveBike::leanRot() const {
return m_leanRot;
Expand Down
Loading

0 comments on commit 8fefcb0

Please sign in to comment.