Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wall collision infrastructure #96

Merged
merged 1 commit into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
139 changes: 125 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;
}

onWallCollision();

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 @@ -1407,6 +1503,14 @@ void KartMoveBike::startWheelie() {
m_wheelieRotDec = 0.0f;
}

/// @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;
}

/// @addr{0x80587BB8}
void KartMoveBike::createSubsystems() {
m_jump = new KartJumpBike(this);
Expand Down Expand Up @@ -1589,7 +1693,10 @@ 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);
Expand All @@ -1609,6 +1716,12 @@ void KartMoveBike::onHop() {
cancelWheelie();
}

/// @stage 2
/// @brief Called when you collide with a wall. All it does for bikes is cancel wheelies.
void KartMoveBike::onWallCollision() {
cancelWheelie();
}

/// @stage 2
/// @brief Every frame during a drift, calculates MT charge based on player input.
/// @addr{0x80588888}
Expand Down Expand Up @@ -1654,7 +1767,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 +1784,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
Loading