From 23b187946335769e72a2cc061ee109f562e4db64 Mon Sep 17 00:00:00 2001 From: Anthony Rossi Date: Fri, 11 Jul 2025 22:58:58 +0200 Subject: [PATCH 1/6] Work on KartObjectProxy (and related) --- src/kart/KartObjectProxy.cpp | 103 ++++++++++++++++++++ src/kart/KartObjectProxy.hpp | 31 ++++++ src/kart/KartPart.hpp | 10 +- src/kart/KartState.hpp | 1 + src/kart/KartSus.hpp | 9 +- src/kart/KartSusPhysics.cpp | 178 ++++++++++++++++++++++++++++++++++ src/kart/KartSusPhysics.hpp | 49 ++++++++++ src/kart/KartWheelPhysics.cpp | 175 --------------------------------- src/kart/KartWheelPhysics.hpp | 36 ------- 9 files changed, 379 insertions(+), 213 deletions(-) create mode 100644 src/kart/KartSusPhysics.cpp create mode 100644 src/kart/KartSusPhysics.hpp diff --git a/src/kart/KartObjectProxy.cpp b/src/kart/KartObjectProxy.cpp index 08fd97957..08ae1e5be 100644 --- a/src/kart/KartObjectProxy.cpp +++ b/src/kart/KartObjectProxy.cpp @@ -1,4 +1,11 @@ #include "KartObjectProxy.hpp" +#include "egg/math/eggMatrix.hpp" +#include "host_system/SystemManager.hpp" +#include "kart/KartPart.hpp" +#include "kart/KartPhysics.hpp" +#include "kart/KartState.hpp" +#include "system/KPadController.hpp" +#include "system/RaceManager.hpp" #include #include @@ -30,6 +37,73 @@ KartObjectProxy::KartObjectProxy() : mAccessor(nullptr) { const EGG::Vector3f& KartObjectProxy::getPos() const { return kartDynamics()->pos; } +const EGG::Vector3f& KartObjectProxy::getPrevPos() const { return kartPhysics()->pos; } + +void KartObjectProxy::setPos(EGG::Vector3f *pos) { + float z,y,x; + KartDynamics* dynamics; + x = pos->x; + y = pos->y; + z = pos->z; + dynamics = kartDynamics(); + dynamics->pos.x = x; + dynamics->pos.y = y; + dynamics->pos.z = z; + + return; +} + +const EGG::Matrix34f& KartObjectProxy::getPose() const { return kartPhysics()->pose; } + +const EGG::Matrix34f& KartObjectProxy::getBodyRot() const { return kartBody()->pose; } + +void KartObjectProxy::setRot(EGG::Quatf rot) { + KartDynamics* dynamics; + float w, x, y, z; + x = rot.x; + y = rot.y; + z = rot.z; + w = rot.w; + dynamics = kartDynamics(); + dynamics->fullRot.x = x; + dynamics->fullRot.y = y; + dynamics->fullRot.z = z; + dynamics->fullRot.w = w; + dynamics->mainRot.x = x; + dynamics->mainRot.y = y; + dynamics->mainRot.z = z; + dynamics->mainRot.w = w; +} + +u16 KartObjectProxy::getSuspCount() { return kartSettings()->susCount; } +u16 KartObjectProxy::getWheelCount() { return kartSettings()->wheelCount; } +float KartObjectProxy::getWheelCountRecip() { return kartSettings()->wheelCountRecip; } +float KartObjectProxy::getWheelCountPlusOneRecip() { return kartSettings()->wheelCountPlusOneRecip; } + +const EGG::Vector3f& KartObjectProxy::getWheelPos(u32 wheelIdx) { + return kartWheel(wheelIdx)->getPhysics()->wheelPos; +} + +bool KartObjectProxy::wheelIdxHasFloorCollision(u32 wheelIdx) { + return kartWheel(wheelIdx)->getPhysics()->hasFloorCollision(); +} + +void KartObjectProxy::setBodyAngle(f32 angle) { + // TODO + //kartBody()->setAngle(angle); +} + +void KartObjectProxy::setStartBoostIdx(s32 idx) { + kartState()->setStartBoostIdx(idx); +} + +const EGG::Vector3f& KartObjectProxy::getWheelEdgePos(u32 wheelIdx) { + return kartWheel(wheelIdx)->getPhysics()->wheelEdgePos; +} + +KartSettings* KartObjectProxy::kartSettings() { return mAccessor->kartSettings; } + +const KartSettings* KartObjectProxy::kartSettings() const { return mAccessor->kartSettings; } KartPhysics* KartObjectProxy::kartPhysics() { return mAccessor->mBody->getPhysics(); } const KartPhysics* KartObjectProxy::kartPhysics() const { return mAccessor->mBody->getPhysics(); } @@ -38,6 +112,22 @@ KartDynamics* KartObjectProxy::kartDynamics() { return mAccessor->mBody->getPhys const KartDynamics* KartObjectProxy::kartDynamics() const { return mAccessor->mBody->getPhysics()->mpDynamics; } +System::KPad* KartObjectProxy::getInput() { + return System::RaceManager::spInstance->players[kartSettings()->playerIdx]->kpadPlayer; +} + +bool KartObjectProxy::isLocal() { + return kartState()->on(KART_FLAG_LOCAL); +} + +bool KartObjectProxy::isCpu() { + return kartState()->on(KART_FLAG_CPU); +} + +bool KartObjectProxy::isGhost() { + return kartState()->on(KART_FLAG_GHOST); +} + KartBody* KartObjectProxy::kartBody() { return mAccessor->mBody; } const KartBody* KartObjectProxy::kartBody() const { return mAccessor->mBody; } @@ -54,6 +144,19 @@ const KartWheel* KartObjectProxy::kartWheel(s32 idx) const { return mAccessor->mWheels[idx]; } +KartSusPhysics* KartObjectProxy::kartSusPhysics(s32 idx) { return kartSus(idx)->getPhysics(); } + +const KartSusPhysics* KartObjectProxy::kartSusPhysics(s32 idx) const { + return kartSus(idx)->getPhysics(); +} + +KartWheelPhysics* KartObjectProxy::kartWheelPhysics(s32 idx) { return mAccessor->mWheels[idx]->getPhysics(); } + +const KartWheelPhysics* KartObjectProxy::kartWheelPhysics(s32 idx) const { + return mAccessor->mWheels[idx]->getPhysics(); +} + + KartPhysicsEngine* KartObjectProxy::kartPhysicsEngine() { return mAccessor->mPhysicsEngine; } const KartPhysicsEngine* KartObjectProxy::kartPhysicsEngine() const { return mAccessor->mPhysicsEngine; } diff --git a/src/kart/KartObjectProxy.hpp b/src/kart/KartObjectProxy.hpp index eb3123d28..8e6a2dea3 100644 --- a/src/kart/KartObjectProxy.hpp +++ b/src/kart/KartObjectProxy.hpp @@ -10,6 +10,11 @@ #include "KartSettings.hpp" #include "KartHitbox.hpp" +#include "egg/math/eggMatrix.hpp" +#include "egg/math/eggQuat.hpp" +#include "kart/KartWheel.hpp" +#include "kart/KartSus.hpp" +#include "system/KPadController.hpp" namespace Kart { @@ -18,6 +23,8 @@ class KartPhysics; class KartDynamics; class KartSus; class KartWheel; +class KartSusPhysics; +class KartWheelPhysics; class KartPhysicsEngine; class KartMove; class KartSnd; @@ -77,6 +84,8 @@ class KartObjectProxy { public: KartObjectProxy(); + KartSettings* kartSettings(); + const KartSettings* kartSettings() const; KartPhysics* kartPhysics(); const KartPhysics* kartPhysics() const; KartDynamics* kartDynamics(); @@ -87,6 +96,10 @@ class KartObjectProxy { const KartSus* kartSus(s32 idx) const; KartWheel* kartWheel(s32 idx); const KartWheel* kartWheel(s32 idx) const; + KartSusPhysics* kartSusPhysics(s32 idx); + const KartSusPhysics* kartSusPhysics(s32 idx) const; + KartWheelPhysics* kartWheelPhysics(s32 idx); + const KartWheelPhysics* kartWheelPhysics(s32 idx) const; KartPhysicsEngine* kartPhysicsEngine(); const KartPhysicsEngine* kartPhysicsEngine() const; KartMove* kartMove(); @@ -135,6 +148,24 @@ class KartObjectProxy { const KartJump* kartJump(); const EGG::Vector3f& getPos() const; + const EGG::Vector3f& getPrevPos() const; + void setPos(EGG::Vector3f* pos); + const EGG::Matrix34f& getPose() const; + const EGG::Matrix34f& getBodyRot() const; + void setRot(EGG::Quatf rot); + u16 getSuspCount(); + u16 getWheelCount(); + float getWheelCountRecip(); + float getWheelCountPlusOneRecip(); + const EGG::Vector3f& getWheelPos(u32 wheelIdx); + bool wheelIdxHasFloorCollision(u32 wheelIdx); + void setBodyAngle(f32 angle); + void setStartBoostIdx(s32 idx); + const EGG::Vector3f& getWheelEdgePos(u32 wheelIdx); + System::KPad* getInput(); + bool isLocal(); + bool isCpu(); + bool isGhost(); void getBodyForward(EGG::Vector3f& out); s32 getHopStickX(); s32 getAppliedHopStickX(); diff --git a/src/kart/KartPart.hpp b/src/kart/KartPart.hpp index 80ac949f1..13f59c18e 100644 --- a/src/kart/KartPart.hpp +++ b/src/kart/KartPart.hpp @@ -2,12 +2,20 @@ #pragma once #include "KartSettings.hpp" +#include "egg/math/eggMatrix.hpp" +#include "egg/math/eggVector.hpp" namespace Kart { class KartPart { - u8 todo[0x90]; + public: KartPart(const KartSettings& kartSettings, u32 thing); + const EGG::Matrix34f getPose() const { return pose; }; + + // TODO : structure is still very wrong + EGG::Vector3f pos; + EGG::Matrix34f pose; + u8 todo[0x90-0x3c]; }; } diff --git a/src/kart/KartState.hpp b/src/kart/KartState.hpp index 3cc7ce732..a3d750018 100644 --- a/src/kart/KartState.hpp +++ b/src/kart/KartState.hpp @@ -71,6 +71,7 @@ class KartState { void setBoostRampType(s32 type) { mBoostRampType = type; } void setJumpPadType(s32 type) { mJumpPadType = type; } void setHalfpipeInvisibilityTimer(s32 timer) { mHalfpipeInvisibilityTimer = timer; } + void setStartBoostIdx(s32 idx) { mStartBoostIdx = idx; } private: RKBitField<160> mFlags; diff --git a/src/kart/KartSus.hpp b/src/kart/KartSus.hpp index b1c2259ee..973f745d3 100644 --- a/src/kart/KartSus.hpp +++ b/src/kart/KartSus.hpp @@ -5,9 +5,16 @@ #include #include "KartPart.hpp" +#include "kart/KartObjectProxy.hpp" namespace Kart { -class KartSus { + class KartSusPhysics; +class KartSus: KartPart { +public: + inline const KartSusPhysics* getPhysics() const { return susPhysics; } + inline KartSusPhysics* getPhysics() { return susPhysics; } +private: + KartSusPhysics* susPhysics; }; } diff --git a/src/kart/KartSusPhysics.cpp b/src/kart/KartSusPhysics.cpp new file mode 100644 index 000000000..e2d98772a --- /dev/null +++ b/src/kart/KartSusPhysics.cpp @@ -0,0 +1,178 @@ +#include "KartSusPhysics.hpp" + +namespace Kart { + +KartSusPhysics::KartSusPhysics(u32 wheelIdx, KartWheelType wheelType, s32 bspWheelIdx) : KartObjectProxy() { + this->wheelPhysics = nullptr; + this->wheelType = wheelType; + this->bspWheelIdx = bspWheelIdx; + this->wheelIdx = wheelIdx; + this->_38 = 1.0f; + } + + void KartSusPhysics::reset() { + this->_38 = 1.0f / this->bspWheel->maxTravel; + this->suspTop.setZero(); + this->maxTravelScaled = 0.0f; + this->hasFloorCol = false; + this->_36 = 0; + this->downDir.setZero(); + } + + void KartSusPhysics::init() { + this->wheelPhysics = this->KartObjectProxy::kartWheel(this->wheelIdx)->getPhysics(); + this->bspWheel = this->KartObjectProxy::bspWheel(this->bspWheelIdx); + this->reset(); + } + + void KartSusPhysics::setInitialState() { + EGG::Vector3f suspTop; + #ifdef __CWCC__ + __memcpy(&suspTop, &this->bspWheel->centerPos, sizeof(suspTop)); // why (assignment copy uses lfs/stfs) + #else + suspTop = this->bspWheel->centerPos; + #endif + + EGG::Vector3f bottom(0.0f, -1.0f, 0.0f); + if (wheelType == KART_WHEEL_KART_RIGHT) { + suspTop.x = -suspTop.x; + } + EGG::Vector3f suspTopWorld; + kartDynamics()->fullRot.rotateVector(suspTop, suspTopWorld); + suspTopWorld += kartDynamics()->pos; + EGG::Vector3f kartBottom; + kartDynamics()->fullRot.rotateVector(bottom, kartBottom); + + f32 travel = this->bspWheel->maxTravel; + EGG::Vector3f scaledBottom = travel * kartBottom; + EGG::Vector3f wheelPos; + wheelPos.x = suspTopWorld.x + scaledBottom.x; + wheelPos.y = suspTopWorld.y + scaledBottom.y; + wheelPos.z = suspTopWorld.z + scaledBottom.z; + wheelPhysics->wheelPos = wheelPos; + wheelPhysics->prevWheelPos = wheelPos; + + KartWheelPhysics* physics = wheelPhysics; + physics->prevWheelOffset.x = wheelPos.x - suspTopWorld.x; + physics->prevWheelOffset.y = wheelPos.y - suspTopWorld.y; + physics->prevWheelOffset.z = wheelPos.z - suspTopWorld.z; + + f32 scale = kartMove()->totalScale(); + f32 radius = wheelPhysics->effectiveRadius; + f32 currentRadius = radius * scale; + + KartWheelPhysics* physics2 = wheelPhysics; + physics2->wheelEdgePos.x = currentRadius * kartBottom.x + wheelPos.x; + physics2->wheelEdgePos.y = currentRadius * kartBottom.y + wheelPos.y; + physics2->wheelEdgePos.z = currentRadius * kartBottom.z + wheelPos.z; + + EGG::Vector3f& hitboxPos = wheelPhysics->getHitbox()->getHitbox(0).pos; + Hitbox& wheelHitbox = wheelPhysics->getHitbox()->getHitbox(0); + hitboxPos.x = wheelPos.x; + hitboxPos.y = wheelPos.y; + hitboxPos.z = wheelPos.z; + EGG::Vector3f dynamicsPos = kartDynamics()->pos; + dynamicsPos.y += wheelHitboxHeight; + wheelHitbox.lastPos = dynamicsPos; + this->suspTop = suspTopWorld; + } + + void KartSusPhysics::calcCollision(const EGG::Vector3f& gravity, const EGG::Matrix34f& mtx, f32 dt) { + this->maxTravelScaled = this->bspWheel->maxTravel * kartPhysicsEngine()->getYScale(); + const EGG::Vector3f& scale = getScale(); + EGG::Vector3f scaledRelPos; + scaledRelPos.x = this->bspWheel->centerPos.x * scale.x; + scaledRelPos.y = this->bspWheel->centerPos.y * scale.y; + scaledRelPos.z = this->bspWheel->centerPos.z * scale.z; + + EGG::Vector3f bottom(0.0f, -1.0f, 0.0f); + if (wheelType == KART_WHEEL_KART_RIGHT) { + scaledRelPos.x = -scaledRelPos.x; + } + EGG::Vector3f suspTopWorld = mtx.multVector(scaledRelPos); + EGG::Vector3f wheelPos; + EGG::Vector3f rotEuler(DEG2RAD(this->bspWheel->xRot), 0.0f, 0.0f); + EGG::Matrix34f_aligned8 rotMtx; + rotMtx.makeR(rotEuler); + bottom = rotMtx.multVector33(bottom); + this->downDir = mtx.multVector33(bottom); + + this->wheelPhysics->setColState(dt, this->maxTravelScaled, gravity); + + EGG::Vector3f& down = this->downDir; + f32 susTravel = this->wheelPhysics->getSusTravel(); + wheelPos.x = susTravel * down.x + suspTopWorld.x; + wheelPos.y = susTravel * down.y + suspTopWorld.y; + wheelPos.z = susTravel * down.z + suspTopWorld.z; + this->wheelPhysics->setWheelPos(wheelPos); + + if (!kartState()->on(KART_FLAG_SKIP_WHEEL_CALC)) { + this->wheelPhysics->calcCollision(down, suspTopWorld); + this->suspTop = suspTopWorld; + } + } + + void KartSusPhysics::calc(const EGG::Vector3f& forward, const EGG::Vector3f& movement) { + EGG::Vector3f prevWhlOff = this->wheelPhysics->prevWheelOffset; + this->wheelPhysics->calc(this->downDir, movement); + + HitboxGroup* hitboxGroup = wheelPhysics->hitboxGroup; + if ((hitboxGroup->getKartCollisionInfo().flags & COL_FLAG_FLOOR) != 0) { + EGG::Vector3f travelVector = wheelPhysics->wheelPos - suspTop; + f32 travel = EGG::Vector3f::dot(downDir, travelVector); + if (travel < 0.0f) travel = 0.0f; + + EGG::Vector3f wheelMovement = prevWhlOff - travelVector; + f32 suspMax = this->maxTravelScaled; + f32 travelSpeed = EGG::Vector3f::dot(downDir, wheelMovement); + if (_36 > 0 && kartPhysics()->speed.dot(hitboxGroup->getKartCollisionInfo().floorNrm) < -15.0f) { + f32 targetSuspSpeed = 0.0f; + if (maxTravelScaled > 0.0f) { + f32 travelPerc = travel / maxTravelScaled; + if (travelPerc > 0.0f) { + targetSuspSpeed = travelPerc <= 1.0f ? travelPerc : 1.0f; + } + travelSpeed *= unk_suspSpeedRate + (1.0f - unk_suspSpeedRate) * targetSuspSpeed; + } + + } + _36--; + if (_36 < 0) _36 = 0; + + EGG::Vector3f rawSuspForce; + rawSuspForce.z = -bspWheel->springStiffness * (suspMax - travel) + bspWheel->dampingFactor * travelSpeed; + rawSuspForce.x = downDir.x * rawSuspForce.z; + rawSuspForce.y = downDir.y * rawSuspForce.z; + rawSuspForce.z = downDir.z * rawSuspForce.z; + + bool isRespawning = inRespawn(); + if (isRespawning) { + if (rawSuspForce.y < -respawnSuspLimit) { + rawSuspForce.y = -respawnSuspLimit; + } else if (rawSuspForce.y > respawnSuspLimit) { + rawSuspForce.y = respawnSuspLimit; + } + } + + EGG::Vector3f suspForce = rawSuspForce; + EGG::Vector3f suspForcePlanar = rawSuspForce; + suspForcePlanar.y = 0.0f; + RKGeom::projUnit(suspForcePlanar, suspForcePlanar, hitboxGroup->getKartCollisionInfo().floorNrm); + suspForce.y += suspForcePlanar.y; + if (suspForce.y > kartStats()->maxVerticalAcc) { + suspForce.y = kartStats()->maxVerticalAcc; + } + if (kartDynamics()->externalVel.y > disableSuspForceVerticalXV) { + suspForce.y = 0.0f; + } + if (kartState()->on(KART_FLAG_DISABLE_Y_SUS_FORCE)) { + suspForce.y = 0.0f; + } + kartDynamics()->applySuspensionWrench(suspTop, suspForce, rawSuspForce, kartState()->on(KART_FLAG_WHEELIE_ROT)); + if (!kartState()->on(KART_FLAG_IN_A_BULLET)) { + wheelPhysics->unk80599dc0(forward); + } + } + hasFloorCol = (hitboxGroup->getKartCollisionInfo().flags & COL_FLAG_FLOOR) != 0; + } +} diff --git a/src/kart/KartSusPhysics.hpp b/src/kart/KartSusPhysics.hpp new file mode 100644 index 000000000..bb8d4c8b1 --- /dev/null +++ b/src/kart/KartSusPhysics.hpp @@ -0,0 +1,49 @@ +#pragma once +#include "KartObjectProxy.hpp" +#include "KartWheelPhysics.hpp" + +namespace Kart { + f32 rateForward = 0.1f; + f32 wheelColForceFactor = 10.0f; + f32 wheelHitboxHeight = 100.0f; + f32 forwardFactor = 0.3f; + f32 respawnSuspLimit = 1.0f; + f32 disableSuspForceVerticalXV = 5.0f; + f32 unk_suspSpeedRate = 0.3f; +enum KartWheelType { + KART_WHEEL_KART_LEFT, + KART_WHEEL_KART_RIGHT, + KART_WHEEL_BIKE, + }; + +class KartSusPhysics : public KartObjectProxy { + public: + virtual ~KartSusPhysics() {} + + KartSusPhysics(u32 wheelIdx, KartWheelType wheelType, s32 bspWheelIdx); + void reset(); + void init(); + void setInitialState(); + void calc(const EGG::Vector3f& forward, const EGG::Vector3f& vehicleMovement); + void calcCollision(const EGG::Vector3f& gravity, const EGG::Matrix34f& mtx, f32 dt); + + private: + public: + BspWheel* bspWheel; + KartWheelPhysics* wheelPhysics; + private: + KartWheelType wheelType; + u32 bspWheelIdx; + u32 wheelIdx; + // topmost point of the suspension the wheel can reach + EGG::Vector3f suspTop; + // bsp max suspension travel after vehicle scale is applied + f32 maxTravelScaled; + bool hasFloorCol; + s16 _36; + f32 _38; + EGG::Vector3f downDir; + }; + static_assert(sizeof(KartSusPhysics) == 0x48); + +} diff --git a/src/kart/KartWheelPhysics.cpp b/src/kart/KartWheelPhysics.cpp index 9754be4b4..5fdef3091 100644 --- a/src/kart/KartWheelPhysics.cpp +++ b/src/kart/KartWheelPhysics.cpp @@ -195,115 +195,7 @@ const KartCollisionInfo& KartWheelPhysics::getKartCollisionInfo() const { return this->hitboxGroup->getKartCollisionInfo(); } -KartSusPhysics::KartSusPhysics(u32 wheelIdx, KartWheelType wheelType, s32 bspWheelIdx) : KartObjectProxy() { - this->wheelPhysics = nullptr; - this->wheelType = wheelType; - this->bspWheelIdx = bspWheelIdx; - this->wheelIdx = wheelIdx; - this->_38 = 1.0f; -} - -void KartSusPhysics::reset() { - this->_38 = 1.0f / this->bspWheel->maxTravel; - this->suspTop.setZero(); - this->maxTravelScaled = 0.0f; - this->hasFloorCol = false; - this->_36 = 0; - this->downDir.setZero(); -} - -void KartSusPhysics::init() { - this->wheelPhysics = this->KartObjectProxy::kartWheel(this->wheelIdx)->getPhysics(); - this->bspWheel = this->KartObjectProxy::bspWheel(this->bspWheelIdx); - this->reset(); -} -void KartSusPhysics::setInitialState() { - EGG::Vector3f suspTop; -#ifdef __CWCC__ - __memcpy(&suspTop, &this->bspWheel->centerPos, sizeof(suspTop)); // why (assignment copy uses lfs/stfs) -#else - suspTop = this->bspWheel->centerPos; -#endif - - EGG::Vector3f bottom(0.0f, -1.0f, 0.0f); - if (wheelType == KART_WHEEL_KART_RIGHT) { - suspTop.x = -suspTop.x; - } - EGG::Vector3f suspTopWorld; - kartDynamics()->fullRot.rotateVector(suspTop, suspTopWorld); - suspTopWorld += kartDynamics()->pos; - EGG::Vector3f kartBottom; - kartDynamics()->fullRot.rotateVector(bottom, kartBottom); - - f32 travel = this->bspWheel->maxTravel; - EGG::Vector3f scaledBottom = travel * kartBottom; - EGG::Vector3f wheelPos; - wheelPos.x = suspTopWorld.x + scaledBottom.x; - wheelPos.y = suspTopWorld.y + scaledBottom.y; - wheelPos.z = suspTopWorld.z + scaledBottom.z; - wheelPhysics->wheelPos = wheelPos; - wheelPhysics->prevWheelPos = wheelPos; - - KartWheelPhysics* physics = wheelPhysics; - physics->prevWheelOffset.x = wheelPos.x - suspTopWorld.x; - physics->prevWheelOffset.y = wheelPos.y - suspTopWorld.y; - physics->prevWheelOffset.z = wheelPos.z - suspTopWorld.z; - - f32 scale = kartMove()->totalScale(); - f32 radius = wheelPhysics->effectiveRadius; - f32 currentRadius = radius * scale; - - KartWheelPhysics* physics2 = wheelPhysics; - physics2->wheelEdgePos.x = currentRadius * kartBottom.x + wheelPos.x; - physics2->wheelEdgePos.y = currentRadius * kartBottom.y + wheelPos.y; - physics2->wheelEdgePos.z = currentRadius * kartBottom.z + wheelPos.z; - - EGG::Vector3f& hitboxPos = wheelPhysics->getHitbox()->getHitbox(0).pos; - Hitbox& wheelHitbox = wheelPhysics->getHitbox()->getHitbox(0); - hitboxPos.x = wheelPos.x; - hitboxPos.y = wheelPos.y; - hitboxPos.z = wheelPos.z; - EGG::Vector3f dynamicsPos = kartDynamics()->pos; - dynamicsPos.y += wheelHitboxHeight; - wheelHitbox.lastPos = dynamicsPos; - this->suspTop = suspTopWorld; -} - -void KartSusPhysics::calcCollision(const EGG::Vector3f& gravity, const EGG::Matrix34f& mtx, f32 dt) { - this->maxTravelScaled = this->bspWheel->maxTravel * kartPhysicsEngine()->getYScale(); - const EGG::Vector3f& scale = getScale(); - EGG::Vector3f scaledRelPos; - scaledRelPos.x = this->bspWheel->centerPos.x * scale.x; - scaledRelPos.y = this->bspWheel->centerPos.y * scale.y; - scaledRelPos.z = this->bspWheel->centerPos.z * scale.z; - - EGG::Vector3f bottom(0.0f, -1.0f, 0.0f); - if (wheelType == KART_WHEEL_KART_RIGHT) { - scaledRelPos.x = -scaledRelPos.x; - } - EGG::Vector3f suspTopWorld = mtx.multVector(scaledRelPos); - EGG::Vector3f wheelPos; - EGG::Vector3f rotEuler(DEG2RAD(this->bspWheel->xRot), 0.0f, 0.0f); - EGG::Matrix34f_aligned8 rotMtx; - rotMtx.makeR(rotEuler); - bottom = rotMtx.multVector33(bottom); - this->downDir = mtx.multVector33(bottom); - - this->wheelPhysics->setColState(dt, this->maxTravelScaled, gravity); - - EGG::Vector3f& down = this->downDir; - f32 susTravel = this->wheelPhysics->getSusTravel(); - wheelPos.x = susTravel * down.x + suspTopWorld.x; - wheelPos.y = susTravel * down.y + suspTopWorld.y; - wheelPos.z = susTravel * down.z + suspTopWorld.z; - this->wheelPhysics->setWheelPos(wheelPos); - - if (!kartState()->on(KART_FLAG_SKIP_WHEEL_CALC)) { - this->wheelPhysics->calcCollision(down, suspTopWorld); - this->suspTop = suspTopWorld; - } -} } EGG::Vector3f EGG::Matrix34f::multVector33(const EGG::Vector3f& v) const { @@ -313,70 +205,3 @@ EGG::Vector3f EGG::Matrix34f::multVector33(const EGG::Vector3f& v) const { ret.x = mtx[0][0] * v.x + mtx[0][1] * v.y + mtx[0][2] * v.z; return ret; } - -namespace Kart { -// https://decomp.me/scratch/H62Zm -void KartSusPhysics::calc(const EGG::Vector3f& forward, const EGG::Vector3f& movement) { - EGG::Vector3f prevWhlOff = this->wheelPhysics->prevWheelOffset; - this->wheelPhysics->calc(this->downDir, movement); - - HitboxGroup* hitboxGroup = wheelPhysics->hitboxGroup; - if ((hitboxGroup->getKartCollisionInfo().flags & COL_FLAG_FLOOR) != 0) { - EGG::Vector3f travelVector = wheelPhysics->wheelPos - suspTop; - f32 travel = EGG::Vector3f::dot(downDir, travelVector); - if (travel < 0.0f) travel = 0.0f; - - EGG::Vector3f wheelMovement = prevWhlOff - travelVector; - f32 suspMax = this->maxTravelScaled; - f32 travelSpeed = EGG::Vector3f::dot(downDir, wheelMovement); - if (_36 > 0 && kartPhysics()->speed.dot(hitboxGroup->getKartCollisionInfo().floorNrm) < -15.0f) { - f32 targetSuspSpeed = 0.0f; - if (maxTravelScaled > 0.0f) { - f32 travelPerc = travel / maxTravelScaled; - if (travelPerc > 0.0f) { - targetSuspSpeed = travelPerc <= 1.0f ? travelPerc : 1.0f; - } - travelSpeed *= unk_suspSpeedRate + (1.0f - unk_suspSpeedRate) * targetSuspSpeed; - } - - } - _36--; - if (_36 < 0) _36 = 0; - - EGG::Vector3f rawSuspForce; - rawSuspForce.z = -bspWheel->springStiffness * (suspMax - travel) + bspWheel->dampingFactor * travelSpeed; - rawSuspForce.x = downDir.x * rawSuspForce.z; - rawSuspForce.y = downDir.y * rawSuspForce.z; - rawSuspForce.z = downDir.z * rawSuspForce.z; - - bool isRespawning = inRespawn(); - if (isRespawning) { - if (rawSuspForce.y < -respawnSuspLimit) { - rawSuspForce.y = -respawnSuspLimit; - } else if (rawSuspForce.y > respawnSuspLimit) { - rawSuspForce.y = respawnSuspLimit; - } - } - - EGG::Vector3f suspForce = rawSuspForce; - EGG::Vector3f suspForcePlanar = rawSuspForce; - suspForcePlanar.y = 0.0f; - RKGeom::projUnit(suspForcePlanar, suspForcePlanar, hitboxGroup->getKartCollisionInfo().floorNrm); - suspForce.y += suspForcePlanar.y; - if (suspForce.y > kartStats()->maxVerticalAcc) { - suspForce.y = kartStats()->maxVerticalAcc; - } - if (kartDynamics()->externalVel.y > disableSuspForceVerticalXV) { - suspForce.y = 0.0f; - } - if (kartState()->on(KART_FLAG_DISABLE_Y_SUS_FORCE)) { - suspForce.y = 0.0f; - } - kartDynamics()->applySuspensionWrench(suspTop, suspForce, rawSuspForce, kartState()->on(KART_FLAG_WHEELIE_ROT)); - if (!kartState()->on(KART_FLAG_IN_A_BULLET)) { - wheelPhysics->unk80599dc0(forward); - } - } - hasFloorCol = (hitboxGroup->getKartCollisionInfo().flags & COL_FLAG_FLOOR) != 0; -} -} diff --git a/src/kart/KartWheelPhysics.hpp b/src/kart/KartWheelPhysics.hpp index 664e2026c..b78d72aae 100644 --- a/src/kart/KartWheelPhysics.hpp +++ b/src/kart/KartWheelPhysics.hpp @@ -17,42 +17,6 @@ #include "egg/math/eggMatrix.hpp" namespace Kart { -enum KartWheelType { - KART_WHEEL_KART_LEFT, - KART_WHEEL_KART_RIGHT, - KART_WHEEL_BIKE, -}; - -class KartWheelPhysics; -class KartSusPhysics : public KartObjectProxy { -public: - virtual ~KartSusPhysics() {} - - KartSusPhysics(u32 wheelIdx, KartWheelType wheelType, s32 bspWheelIdx); - void reset(); - void init(); - void setInitialState(); - void calc(const EGG::Vector3f& forward, const EGG::Vector3f& vehicleMovement); - void calcCollision(const EGG::Vector3f& gravity, const EGG::Matrix34f& mtx, f32 dt); - -private: -public: - BspWheel* bspWheel; - KartWheelPhysics* wheelPhysics; -private: - KartWheelType wheelType; - u32 bspWheelIdx; - u32 wheelIdx; - // topmost point of the suspension the wheel can reach - EGG::Vector3f suspTop; - // bsp max suspension travel after vehicle scale is applied - f32 maxTravelScaled; - bool hasFloorCol; - s16 _36; - f32 _38; - EGG::Vector3f downDir; -}; -static_assert(sizeof(KartSusPhysics) == 0x48); class KartWheelPhysics : public KartObjectProxy { public: From be4b4b1eb60f8a33c0dac41065e6f7fe1e5951a7 Mon Sep 17 00:00:00 2001 From: Anthony Rossi Date: Fri, 11 Jul 2025 23:14:16 +0200 Subject: [PATCH 2/6] oops, fixed the split between Wheel and Sus physics --- config/RMCP01/module/splits.txt | 16 +++++++++++----- configure.py | 3 +++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/config/RMCP01/module/splits.txt b/config/RMCP01/module/splits.txt index 99eb9b7fb..e88d2c7fc 100644 --- a/config/RMCP01/module/splits.txt +++ b/config/RMCP01/module/splits.txt @@ -115,9 +115,13 @@ kart/KartSus.cpp: .data start:0x000039E0 end:0x00003AB8 kart/KartWheelPhysics.cpp: - .text start:0x00089058 end:0x0008A690 + .text start:0x00089058 end:0x00089B20 .rodata start:0x00002848 end:0x00002878 - .data start:0x00003AB8 end:0x00003AF0 + .data start:0x00003AB8 end:0x00003AE0 + +kart/KartSusPhysics.cpp: + .text start:0x00089B20 end:0x0008A690 + .data start:0x00003AE0 end:0x00003AF0 kart/KartPhysics.cpp: .text start:0x0008F208 end:0x000900CC @@ -151,18 +155,20 @@ ui/MessageGroup.cpp: .text start:0x000E8780 end:0x000E89A8 .rodata start:0x00006A28 end:0x00006A38 -Page.o: +ui/Page.cpp: .text start:0x000F15C8 end:0x000F2978 + .data start:0x000079F0 end:0x00007A54 -Section.o: +ui/Section.o: .text start:0x00111958 end:0x001142DC ui/SectionAutogens.cpp: .text start:0x0011BFF0 end:0x00122058 .data start:0x00009C40 end:0x0000A400 -SectionDirector.o: +ui/SectionManager.cpp: .text start:0x001247CC end:0x00125B04 + .bss start:0x00004758 end:0x00004760 net/MiscPacketHandler.cpp: .text start:0x00142E54 end:0x00145484 diff --git a/configure.py b/configure.py index d56d2071a..d616529f2 100755 --- a/configure.py +++ b/configure.py @@ -778,6 +778,7 @@ def MatchingFor(*versions): Object(NonMatching, "kart/KartState.cpp"), Object(NonMatching, "kart/KartSus.cpp"), Object(NonMatching, "kart/KartWheelPhysics.cpp"), + Object(NonMatching, "kart/KartSusPhysics.cpp"), Object(NonMatching, "kart/KartPhysics.cpp"), Object(Matching, "kart/KartPhysicsInstance.cpp"), Object(NonMatching, "kart/KartDynamics.cpp"), @@ -786,6 +787,8 @@ def MatchingFor(*versions): Object(Matching, "ui/ControlGroup.cpp"), Object(Matching, "ui/MessageGroup.cpp"), Object(NonMatching, "ui/SectionAutogens.cpp"), + Object(NonMatching, "ui/SectionManager.cpp"), + Object(NonMatching, "ui/Page.cpp"), Object(Equivalent, "enemy/AI.cpp"), Object(Equivalent, "enemy/AITrickHandler.cpp"), From 0e4b4212a70ac80b6bafcfcda537bb18e22f1d72 Mon Sep 17 00:00:00 2001 From: Anthony Rossi Date: Fri, 11 Jul 2025 23:46:32 +0200 Subject: [PATCH 3/6] Merged again Wheel and Sus physics --- config/RMCP01/module/splits.txt | 8 +- config/RMCP01/module/symbols.txt | 34 +++--- src/kart/KartSusPhysics.cpp | 178 ------------------------------- src/kart/KartSusPhysics.hpp | 49 --------- src/kart/KartWheelPhysics.cpp | 175 ++++++++++++++++++++++++++++++ src/kart/KartWheelPhysics.hpp | 36 +++++++ 6 files changed, 230 insertions(+), 250 deletions(-) delete mode 100644 src/kart/KartSusPhysics.cpp delete mode 100644 src/kart/KartSusPhysics.hpp diff --git a/config/RMCP01/module/splits.txt b/config/RMCP01/module/splits.txt index e88d2c7fc..72a477b6a 100644 --- a/config/RMCP01/module/splits.txt +++ b/config/RMCP01/module/splits.txt @@ -115,13 +115,9 @@ kart/KartSus.cpp: .data start:0x000039E0 end:0x00003AB8 kart/KartWheelPhysics.cpp: - .text start:0x00089058 end:0x00089B20 + .text start:0x00089058 end:0x0008A690 .rodata start:0x00002848 end:0x00002878 - .data start:0x00003AB8 end:0x00003AE0 - -kart/KartSusPhysics.cpp: - .text start:0x00089B20 end:0x0008A690 - .data start:0x00003AE0 end:0x00003AF0 + .data start:0x00003AB8 end:0x00003AF0 kart/KartPhysics.cpp: .text start:0x0008F208 end:0x000900CC diff --git a/config/RMCP01/module/symbols.txt b/config/RMCP01/module/symbols.txt index f2f7af69a..f51945bfc 100644 --- a/config/RMCP01/module/symbols.txt +++ b/config/RMCP01/module/symbols.txt @@ -2817,19 +2817,19 @@ __ct__Q24Kart15KartObjectProxyFv = .text:0x0007FDD8; // type:function size:0x44 setupSingle = .text:0x0007FE1C; // type:function size:0x3C scope:global align:4 getPos__Q24Kart15KartObjectProxyCFv = .text:0x0007FE58; // type:function size:0x18 scope:global align:4 PlayerPointers_getPlayerPhysicsHolderPosition = .text:0x0007FE70; // type:function size:0x14 scope:global align:4 -various_stuff_set_player_position = .text:0x0007FE84; // type:function size:0x2C scope:global align:4 -PlayerPointers_getMat = .text:0x0007FEB0; // type:function size:0x14 scope:global align:4 -fn_1_7FEC4 = .text:0x0007FEC4; // type:function size:0x10 -various_stuff_set_player_rotation = .text:0x0007FED4; // type:function size:0x54 scope:global align:4 -PlayerPointers_getWheelCount0 = .text:0x0007FF28; // type:function size:0x10 scope:global align:4 -PlayerPointers_getWheelCount1 = .text:0x0007FF38; // type:function size:0x10 scope:global align:4 -fn_1_7FF48 = .text:0x0007FF48; // type:function size:0x10 -fn_1_7FF58 = .text:0x0007FF58; // type:function size:0x10 -fn_1_7FF68 = .text:0x0007FF68; // type:function size:0x1C -fn_1_7FF84 = .text:0x0007FF84; // type:function size:0x18 +setPos__Q24Kart15KartObjectProxyFPQ23EGG8Vector3f = .text:0x0007FE84; // type:function size:0x2C scope:global align:4 +getPose__Q24Kart15KartObjectProxyCFv = .text:0x0007FEB0; // type:function size:0x14 scope:global align:4 +getBodyRot__Q24Kart15KartObjectProxyCFv = .text:0x0007FEC4; // type:function size:0x10 +setRot__Q24Kart15KartObjectProxyFQ23EGG5Quatf = .text:0x0007FED4; // type:function size:0x54 scope:global align:4 +getSuspCount__Q24Kart15KartObjectProxyFv = .text:0x0007FF28; // type:function size:0x10 scope:global align:4 +getWheelCount__Q24Kart15KartObjectProxyFv = .text:0x0007FF38; // type:function size:0x10 scope:global align:4 +getWheelCountRecip__Q24Kart15KartObjectProxyFv = .text:0x0007FF48; // type:function size:0x10 +getWheelCountPlusOneRecip__Q24Kart15KartObjectProxyFv = .text:0x0007FF58; // type:function size:0x10 +getWheelPos__Q24Kart15KartObjectProxyFUl = .text:0x0007FF68; // type:function size:0x1C +wheelIdxHasFloorCollision__Q24Kart15KartObjectProxyFUl = .text:0x0007FF84; // type:function size:0x18 fn_1_7FF9C = .text:0x0007FF9C; // type:function size:0x18 fn_1_7FFB4 = .text:0x0007FFB4; // type:function size:0x18 -fn_1_7FFCC = .text:0x0007FFCC; // type:function size:0x10 +setStartBoostIdx__Q24Kart15KartObjectProxyFl = .text:0x0007FFCC; // type:function size:0x10 fn_1_7FFDC = .text:0x0007FFDC; // type:function size:0x1C kartPhysics__Q24Kart15KartObjectProxyFv = .text:0x0007FFF8; // type:function size:0x10 scope:global align:4 kartPhysics__Q24Kart15KartObjectProxyCFv = .text:0x00080008; // type:function size:0x10 scope:global align:4 @@ -2842,9 +2842,9 @@ fn_1_800C4 = .text:0x000800C4; // type:function size:0xF4 fn_1_801B8 = .text:0x000801B8; // type:function size:0x4 fn_1_801BC = .text:0x000801BC; // type:function size:0xDC fn_1_80298 = .text:0x00080298; // type:function size:0x4 -PlayerPointers_isReal = .text:0x0008029C; // type:function size:0x14 scope:global align:4 +isLocal__Q24Kart15KartObjectProxyFv = .text:0x0008029C; // type:function size:0x14 scope:global align:4 isCpu__Q24Kart15KartObjectProxyCFv = .text:0x000802B0; // type:function size:0x14 scope:global align:4 -PlayerPointers_isGhost = .text:0x000802C4; // type:function size:0x14 scope:global align:4 +isGhost__Q24Kart15KartObjectProxyFv = .text:0x000802C4; // type:function size:0x14 scope:global align:4 PlayerModel_isMii = .text:0x000802D8; // type:function size:0x10 scope:global align:4 kartBody__Q24Kart15KartObjectProxyFv = .text:0x000802E8; // type:function size:0xC scope:global align:4 kartBody__Q24Kart15KartObjectProxyCFv = .text:0x000802F4; // type:function size:0xC scope:global align:4 @@ -2852,10 +2852,10 @@ kartSus__Q24Kart15KartObjectProxyFl = .text:0x00080300; // type:function size:0x kartSus__Q24Kart15KartObjectProxyCFl = .text:0x00080314; // type:function size:0x14 scope:global align:4 kartWheel__Q24Kart15KartObjectProxyFl = .text:0x00080328; // type:function size:0x14 scope:global align:4 kartWheel__Q24Kart15KartObjectProxyCFl = .text:0x0008033C; // type:function size:0x14 scope:global align:4 -PlayerPointers_getWheelPhysicsHolder = .text:0x00080350; // type:function size:0x18 scope:global align:4 -fn_1_80368 = .text:0x00080368; // type:function size:0x18 -PlayerPointers_getWheelPhysics = .text:0x00080380; // type:function size:0x18 scope:global align:4 -fn_1_80398 = .text:0x00080398; // type:function size:0x18 +kartSusPhysics__Q24Kart15KartObjectProxyFl = .text:0x00080350; // type:function size:0x18 scope:global align:4 +kartSusPhysics__Q24Kart15KartObjectProxyCFl = .text:0x00080368; // type:function size:0x18 +kartWheelPhysics__Q24Kart15KartObjectProxyFl = .text:0x00080380; // type:function size:0x18 scope:global align:4 +kartWheelPhysics__Q24Kart15KartObjectProxyCFl = .text:0x00080398; // type:function size:0x18 kartPhysicsEngine__Q24Kart15KartObjectProxyFv = .text:0x000803B0; // type:function size:0xC scope:global align:4 kartPhysicsEngine__Q24Kart15KartObjectProxyCFv = .text:0x000803BC; // type:function size:0xC scope:global align:4 kartMove__Q24Kart15KartObjectProxyFv = .text:0x000803C8; // type:function size:0xC scope:global align:4 diff --git a/src/kart/KartSusPhysics.cpp b/src/kart/KartSusPhysics.cpp deleted file mode 100644 index e2d98772a..000000000 --- a/src/kart/KartSusPhysics.cpp +++ /dev/null @@ -1,178 +0,0 @@ -#include "KartSusPhysics.hpp" - -namespace Kart { - -KartSusPhysics::KartSusPhysics(u32 wheelIdx, KartWheelType wheelType, s32 bspWheelIdx) : KartObjectProxy() { - this->wheelPhysics = nullptr; - this->wheelType = wheelType; - this->bspWheelIdx = bspWheelIdx; - this->wheelIdx = wheelIdx; - this->_38 = 1.0f; - } - - void KartSusPhysics::reset() { - this->_38 = 1.0f / this->bspWheel->maxTravel; - this->suspTop.setZero(); - this->maxTravelScaled = 0.0f; - this->hasFloorCol = false; - this->_36 = 0; - this->downDir.setZero(); - } - - void KartSusPhysics::init() { - this->wheelPhysics = this->KartObjectProxy::kartWheel(this->wheelIdx)->getPhysics(); - this->bspWheel = this->KartObjectProxy::bspWheel(this->bspWheelIdx); - this->reset(); - } - - void KartSusPhysics::setInitialState() { - EGG::Vector3f suspTop; - #ifdef __CWCC__ - __memcpy(&suspTop, &this->bspWheel->centerPos, sizeof(suspTop)); // why (assignment copy uses lfs/stfs) - #else - suspTop = this->bspWheel->centerPos; - #endif - - EGG::Vector3f bottom(0.0f, -1.0f, 0.0f); - if (wheelType == KART_WHEEL_KART_RIGHT) { - suspTop.x = -suspTop.x; - } - EGG::Vector3f suspTopWorld; - kartDynamics()->fullRot.rotateVector(suspTop, suspTopWorld); - suspTopWorld += kartDynamics()->pos; - EGG::Vector3f kartBottom; - kartDynamics()->fullRot.rotateVector(bottom, kartBottom); - - f32 travel = this->bspWheel->maxTravel; - EGG::Vector3f scaledBottom = travel * kartBottom; - EGG::Vector3f wheelPos; - wheelPos.x = suspTopWorld.x + scaledBottom.x; - wheelPos.y = suspTopWorld.y + scaledBottom.y; - wheelPos.z = suspTopWorld.z + scaledBottom.z; - wheelPhysics->wheelPos = wheelPos; - wheelPhysics->prevWheelPos = wheelPos; - - KartWheelPhysics* physics = wheelPhysics; - physics->prevWheelOffset.x = wheelPos.x - suspTopWorld.x; - physics->prevWheelOffset.y = wheelPos.y - suspTopWorld.y; - physics->prevWheelOffset.z = wheelPos.z - suspTopWorld.z; - - f32 scale = kartMove()->totalScale(); - f32 radius = wheelPhysics->effectiveRadius; - f32 currentRadius = radius * scale; - - KartWheelPhysics* physics2 = wheelPhysics; - physics2->wheelEdgePos.x = currentRadius * kartBottom.x + wheelPos.x; - physics2->wheelEdgePos.y = currentRadius * kartBottom.y + wheelPos.y; - physics2->wheelEdgePos.z = currentRadius * kartBottom.z + wheelPos.z; - - EGG::Vector3f& hitboxPos = wheelPhysics->getHitbox()->getHitbox(0).pos; - Hitbox& wheelHitbox = wheelPhysics->getHitbox()->getHitbox(0); - hitboxPos.x = wheelPos.x; - hitboxPos.y = wheelPos.y; - hitboxPos.z = wheelPos.z; - EGG::Vector3f dynamicsPos = kartDynamics()->pos; - dynamicsPos.y += wheelHitboxHeight; - wheelHitbox.lastPos = dynamicsPos; - this->suspTop = suspTopWorld; - } - - void KartSusPhysics::calcCollision(const EGG::Vector3f& gravity, const EGG::Matrix34f& mtx, f32 dt) { - this->maxTravelScaled = this->bspWheel->maxTravel * kartPhysicsEngine()->getYScale(); - const EGG::Vector3f& scale = getScale(); - EGG::Vector3f scaledRelPos; - scaledRelPos.x = this->bspWheel->centerPos.x * scale.x; - scaledRelPos.y = this->bspWheel->centerPos.y * scale.y; - scaledRelPos.z = this->bspWheel->centerPos.z * scale.z; - - EGG::Vector3f bottom(0.0f, -1.0f, 0.0f); - if (wheelType == KART_WHEEL_KART_RIGHT) { - scaledRelPos.x = -scaledRelPos.x; - } - EGG::Vector3f suspTopWorld = mtx.multVector(scaledRelPos); - EGG::Vector3f wheelPos; - EGG::Vector3f rotEuler(DEG2RAD(this->bspWheel->xRot), 0.0f, 0.0f); - EGG::Matrix34f_aligned8 rotMtx; - rotMtx.makeR(rotEuler); - bottom = rotMtx.multVector33(bottom); - this->downDir = mtx.multVector33(bottom); - - this->wheelPhysics->setColState(dt, this->maxTravelScaled, gravity); - - EGG::Vector3f& down = this->downDir; - f32 susTravel = this->wheelPhysics->getSusTravel(); - wheelPos.x = susTravel * down.x + suspTopWorld.x; - wheelPos.y = susTravel * down.y + suspTopWorld.y; - wheelPos.z = susTravel * down.z + suspTopWorld.z; - this->wheelPhysics->setWheelPos(wheelPos); - - if (!kartState()->on(KART_FLAG_SKIP_WHEEL_CALC)) { - this->wheelPhysics->calcCollision(down, suspTopWorld); - this->suspTop = suspTopWorld; - } - } - - void KartSusPhysics::calc(const EGG::Vector3f& forward, const EGG::Vector3f& movement) { - EGG::Vector3f prevWhlOff = this->wheelPhysics->prevWheelOffset; - this->wheelPhysics->calc(this->downDir, movement); - - HitboxGroup* hitboxGroup = wheelPhysics->hitboxGroup; - if ((hitboxGroup->getKartCollisionInfo().flags & COL_FLAG_FLOOR) != 0) { - EGG::Vector3f travelVector = wheelPhysics->wheelPos - suspTop; - f32 travel = EGG::Vector3f::dot(downDir, travelVector); - if (travel < 0.0f) travel = 0.0f; - - EGG::Vector3f wheelMovement = prevWhlOff - travelVector; - f32 suspMax = this->maxTravelScaled; - f32 travelSpeed = EGG::Vector3f::dot(downDir, wheelMovement); - if (_36 > 0 && kartPhysics()->speed.dot(hitboxGroup->getKartCollisionInfo().floorNrm) < -15.0f) { - f32 targetSuspSpeed = 0.0f; - if (maxTravelScaled > 0.0f) { - f32 travelPerc = travel / maxTravelScaled; - if (travelPerc > 0.0f) { - targetSuspSpeed = travelPerc <= 1.0f ? travelPerc : 1.0f; - } - travelSpeed *= unk_suspSpeedRate + (1.0f - unk_suspSpeedRate) * targetSuspSpeed; - } - - } - _36--; - if (_36 < 0) _36 = 0; - - EGG::Vector3f rawSuspForce; - rawSuspForce.z = -bspWheel->springStiffness * (suspMax - travel) + bspWheel->dampingFactor * travelSpeed; - rawSuspForce.x = downDir.x * rawSuspForce.z; - rawSuspForce.y = downDir.y * rawSuspForce.z; - rawSuspForce.z = downDir.z * rawSuspForce.z; - - bool isRespawning = inRespawn(); - if (isRespawning) { - if (rawSuspForce.y < -respawnSuspLimit) { - rawSuspForce.y = -respawnSuspLimit; - } else if (rawSuspForce.y > respawnSuspLimit) { - rawSuspForce.y = respawnSuspLimit; - } - } - - EGG::Vector3f suspForce = rawSuspForce; - EGG::Vector3f suspForcePlanar = rawSuspForce; - suspForcePlanar.y = 0.0f; - RKGeom::projUnit(suspForcePlanar, suspForcePlanar, hitboxGroup->getKartCollisionInfo().floorNrm); - suspForce.y += suspForcePlanar.y; - if (suspForce.y > kartStats()->maxVerticalAcc) { - suspForce.y = kartStats()->maxVerticalAcc; - } - if (kartDynamics()->externalVel.y > disableSuspForceVerticalXV) { - suspForce.y = 0.0f; - } - if (kartState()->on(KART_FLAG_DISABLE_Y_SUS_FORCE)) { - suspForce.y = 0.0f; - } - kartDynamics()->applySuspensionWrench(suspTop, suspForce, rawSuspForce, kartState()->on(KART_FLAG_WHEELIE_ROT)); - if (!kartState()->on(KART_FLAG_IN_A_BULLET)) { - wheelPhysics->unk80599dc0(forward); - } - } - hasFloorCol = (hitboxGroup->getKartCollisionInfo().flags & COL_FLAG_FLOOR) != 0; - } -} diff --git a/src/kart/KartSusPhysics.hpp b/src/kart/KartSusPhysics.hpp deleted file mode 100644 index bb8d4c8b1..000000000 --- a/src/kart/KartSusPhysics.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once -#include "KartObjectProxy.hpp" -#include "KartWheelPhysics.hpp" - -namespace Kart { - f32 rateForward = 0.1f; - f32 wheelColForceFactor = 10.0f; - f32 wheelHitboxHeight = 100.0f; - f32 forwardFactor = 0.3f; - f32 respawnSuspLimit = 1.0f; - f32 disableSuspForceVerticalXV = 5.0f; - f32 unk_suspSpeedRate = 0.3f; -enum KartWheelType { - KART_WHEEL_KART_LEFT, - KART_WHEEL_KART_RIGHT, - KART_WHEEL_BIKE, - }; - -class KartSusPhysics : public KartObjectProxy { - public: - virtual ~KartSusPhysics() {} - - KartSusPhysics(u32 wheelIdx, KartWheelType wheelType, s32 bspWheelIdx); - void reset(); - void init(); - void setInitialState(); - void calc(const EGG::Vector3f& forward, const EGG::Vector3f& vehicleMovement); - void calcCollision(const EGG::Vector3f& gravity, const EGG::Matrix34f& mtx, f32 dt); - - private: - public: - BspWheel* bspWheel; - KartWheelPhysics* wheelPhysics; - private: - KartWheelType wheelType; - u32 bspWheelIdx; - u32 wheelIdx; - // topmost point of the suspension the wheel can reach - EGG::Vector3f suspTop; - // bsp max suspension travel after vehicle scale is applied - f32 maxTravelScaled; - bool hasFloorCol; - s16 _36; - f32 _38; - EGG::Vector3f downDir; - }; - static_assert(sizeof(KartSusPhysics) == 0x48); - -} diff --git a/src/kart/KartWheelPhysics.cpp b/src/kart/KartWheelPhysics.cpp index 5fdef3091..9754be4b4 100644 --- a/src/kart/KartWheelPhysics.cpp +++ b/src/kart/KartWheelPhysics.cpp @@ -195,7 +195,115 @@ const KartCollisionInfo& KartWheelPhysics::getKartCollisionInfo() const { return this->hitboxGroup->getKartCollisionInfo(); } +KartSusPhysics::KartSusPhysics(u32 wheelIdx, KartWheelType wheelType, s32 bspWheelIdx) : KartObjectProxy() { + this->wheelPhysics = nullptr; + this->wheelType = wheelType; + this->bspWheelIdx = bspWheelIdx; + this->wheelIdx = wheelIdx; + this->_38 = 1.0f; +} + +void KartSusPhysics::reset() { + this->_38 = 1.0f / this->bspWheel->maxTravel; + this->suspTop.setZero(); + this->maxTravelScaled = 0.0f; + this->hasFloorCol = false; + this->_36 = 0; + this->downDir.setZero(); +} + +void KartSusPhysics::init() { + this->wheelPhysics = this->KartObjectProxy::kartWheel(this->wheelIdx)->getPhysics(); + this->bspWheel = this->KartObjectProxy::bspWheel(this->bspWheelIdx); + this->reset(); +} +void KartSusPhysics::setInitialState() { + EGG::Vector3f suspTop; +#ifdef __CWCC__ + __memcpy(&suspTop, &this->bspWheel->centerPos, sizeof(suspTop)); // why (assignment copy uses lfs/stfs) +#else + suspTop = this->bspWheel->centerPos; +#endif + + EGG::Vector3f bottom(0.0f, -1.0f, 0.0f); + if (wheelType == KART_WHEEL_KART_RIGHT) { + suspTop.x = -suspTop.x; + } + EGG::Vector3f suspTopWorld; + kartDynamics()->fullRot.rotateVector(suspTop, suspTopWorld); + suspTopWorld += kartDynamics()->pos; + EGG::Vector3f kartBottom; + kartDynamics()->fullRot.rotateVector(bottom, kartBottom); + + f32 travel = this->bspWheel->maxTravel; + EGG::Vector3f scaledBottom = travel * kartBottom; + EGG::Vector3f wheelPos; + wheelPos.x = suspTopWorld.x + scaledBottom.x; + wheelPos.y = suspTopWorld.y + scaledBottom.y; + wheelPos.z = suspTopWorld.z + scaledBottom.z; + wheelPhysics->wheelPos = wheelPos; + wheelPhysics->prevWheelPos = wheelPos; + + KartWheelPhysics* physics = wheelPhysics; + physics->prevWheelOffset.x = wheelPos.x - suspTopWorld.x; + physics->prevWheelOffset.y = wheelPos.y - suspTopWorld.y; + physics->prevWheelOffset.z = wheelPos.z - suspTopWorld.z; + + f32 scale = kartMove()->totalScale(); + f32 radius = wheelPhysics->effectiveRadius; + f32 currentRadius = radius * scale; + + KartWheelPhysics* physics2 = wheelPhysics; + physics2->wheelEdgePos.x = currentRadius * kartBottom.x + wheelPos.x; + physics2->wheelEdgePos.y = currentRadius * kartBottom.y + wheelPos.y; + physics2->wheelEdgePos.z = currentRadius * kartBottom.z + wheelPos.z; + + EGG::Vector3f& hitboxPos = wheelPhysics->getHitbox()->getHitbox(0).pos; + Hitbox& wheelHitbox = wheelPhysics->getHitbox()->getHitbox(0); + hitboxPos.x = wheelPos.x; + hitboxPos.y = wheelPos.y; + hitboxPos.z = wheelPos.z; + EGG::Vector3f dynamicsPos = kartDynamics()->pos; + dynamicsPos.y += wheelHitboxHeight; + wheelHitbox.lastPos = dynamicsPos; + this->suspTop = suspTopWorld; +} + +void KartSusPhysics::calcCollision(const EGG::Vector3f& gravity, const EGG::Matrix34f& mtx, f32 dt) { + this->maxTravelScaled = this->bspWheel->maxTravel * kartPhysicsEngine()->getYScale(); + const EGG::Vector3f& scale = getScale(); + EGG::Vector3f scaledRelPos; + scaledRelPos.x = this->bspWheel->centerPos.x * scale.x; + scaledRelPos.y = this->bspWheel->centerPos.y * scale.y; + scaledRelPos.z = this->bspWheel->centerPos.z * scale.z; + + EGG::Vector3f bottom(0.0f, -1.0f, 0.0f); + if (wheelType == KART_WHEEL_KART_RIGHT) { + scaledRelPos.x = -scaledRelPos.x; + } + EGG::Vector3f suspTopWorld = mtx.multVector(scaledRelPos); + EGG::Vector3f wheelPos; + EGG::Vector3f rotEuler(DEG2RAD(this->bspWheel->xRot), 0.0f, 0.0f); + EGG::Matrix34f_aligned8 rotMtx; + rotMtx.makeR(rotEuler); + bottom = rotMtx.multVector33(bottom); + this->downDir = mtx.multVector33(bottom); + + this->wheelPhysics->setColState(dt, this->maxTravelScaled, gravity); + + EGG::Vector3f& down = this->downDir; + f32 susTravel = this->wheelPhysics->getSusTravel(); + wheelPos.x = susTravel * down.x + suspTopWorld.x; + wheelPos.y = susTravel * down.y + suspTopWorld.y; + wheelPos.z = susTravel * down.z + suspTopWorld.z; + this->wheelPhysics->setWheelPos(wheelPos); + + if (!kartState()->on(KART_FLAG_SKIP_WHEEL_CALC)) { + this->wheelPhysics->calcCollision(down, suspTopWorld); + this->suspTop = suspTopWorld; + } +} } EGG::Vector3f EGG::Matrix34f::multVector33(const EGG::Vector3f& v) const { @@ -205,3 +313,70 @@ EGG::Vector3f EGG::Matrix34f::multVector33(const EGG::Vector3f& v) const { ret.x = mtx[0][0] * v.x + mtx[0][1] * v.y + mtx[0][2] * v.z; return ret; } + +namespace Kart { +// https://decomp.me/scratch/H62Zm +void KartSusPhysics::calc(const EGG::Vector3f& forward, const EGG::Vector3f& movement) { + EGG::Vector3f prevWhlOff = this->wheelPhysics->prevWheelOffset; + this->wheelPhysics->calc(this->downDir, movement); + + HitboxGroup* hitboxGroup = wheelPhysics->hitboxGroup; + if ((hitboxGroup->getKartCollisionInfo().flags & COL_FLAG_FLOOR) != 0) { + EGG::Vector3f travelVector = wheelPhysics->wheelPos - suspTop; + f32 travel = EGG::Vector3f::dot(downDir, travelVector); + if (travel < 0.0f) travel = 0.0f; + + EGG::Vector3f wheelMovement = prevWhlOff - travelVector; + f32 suspMax = this->maxTravelScaled; + f32 travelSpeed = EGG::Vector3f::dot(downDir, wheelMovement); + if (_36 > 0 && kartPhysics()->speed.dot(hitboxGroup->getKartCollisionInfo().floorNrm) < -15.0f) { + f32 targetSuspSpeed = 0.0f; + if (maxTravelScaled > 0.0f) { + f32 travelPerc = travel / maxTravelScaled; + if (travelPerc > 0.0f) { + targetSuspSpeed = travelPerc <= 1.0f ? travelPerc : 1.0f; + } + travelSpeed *= unk_suspSpeedRate + (1.0f - unk_suspSpeedRate) * targetSuspSpeed; + } + + } + _36--; + if (_36 < 0) _36 = 0; + + EGG::Vector3f rawSuspForce; + rawSuspForce.z = -bspWheel->springStiffness * (suspMax - travel) + bspWheel->dampingFactor * travelSpeed; + rawSuspForce.x = downDir.x * rawSuspForce.z; + rawSuspForce.y = downDir.y * rawSuspForce.z; + rawSuspForce.z = downDir.z * rawSuspForce.z; + + bool isRespawning = inRespawn(); + if (isRespawning) { + if (rawSuspForce.y < -respawnSuspLimit) { + rawSuspForce.y = -respawnSuspLimit; + } else if (rawSuspForce.y > respawnSuspLimit) { + rawSuspForce.y = respawnSuspLimit; + } + } + + EGG::Vector3f suspForce = rawSuspForce; + EGG::Vector3f suspForcePlanar = rawSuspForce; + suspForcePlanar.y = 0.0f; + RKGeom::projUnit(suspForcePlanar, suspForcePlanar, hitboxGroup->getKartCollisionInfo().floorNrm); + suspForce.y += suspForcePlanar.y; + if (suspForce.y > kartStats()->maxVerticalAcc) { + suspForce.y = kartStats()->maxVerticalAcc; + } + if (kartDynamics()->externalVel.y > disableSuspForceVerticalXV) { + suspForce.y = 0.0f; + } + if (kartState()->on(KART_FLAG_DISABLE_Y_SUS_FORCE)) { + suspForce.y = 0.0f; + } + kartDynamics()->applySuspensionWrench(suspTop, suspForce, rawSuspForce, kartState()->on(KART_FLAG_WHEELIE_ROT)); + if (!kartState()->on(KART_FLAG_IN_A_BULLET)) { + wheelPhysics->unk80599dc0(forward); + } + } + hasFloorCol = (hitboxGroup->getKartCollisionInfo().flags & COL_FLAG_FLOOR) != 0; +} +} diff --git a/src/kart/KartWheelPhysics.hpp b/src/kart/KartWheelPhysics.hpp index b78d72aae..664e2026c 100644 --- a/src/kart/KartWheelPhysics.hpp +++ b/src/kart/KartWheelPhysics.hpp @@ -17,6 +17,42 @@ #include "egg/math/eggMatrix.hpp" namespace Kart { +enum KartWheelType { + KART_WHEEL_KART_LEFT, + KART_WHEEL_KART_RIGHT, + KART_WHEEL_BIKE, +}; + +class KartWheelPhysics; +class KartSusPhysics : public KartObjectProxy { +public: + virtual ~KartSusPhysics() {} + + KartSusPhysics(u32 wheelIdx, KartWheelType wheelType, s32 bspWheelIdx); + void reset(); + void init(); + void setInitialState(); + void calc(const EGG::Vector3f& forward, const EGG::Vector3f& vehicleMovement); + void calcCollision(const EGG::Vector3f& gravity, const EGG::Matrix34f& mtx, f32 dt); + +private: +public: + BspWheel* bspWheel; + KartWheelPhysics* wheelPhysics; +private: + KartWheelType wheelType; + u32 bspWheelIdx; + u32 wheelIdx; + // topmost point of the suspension the wheel can reach + EGG::Vector3f suspTop; + // bsp max suspension travel after vehicle scale is applied + f32 maxTravelScaled; + bool hasFloorCol; + s16 _36; + f32 _38; + EGG::Vector3f downDir; +}; +static_assert(sizeof(KartSusPhysics) == 0x48); class KartWheelPhysics : public KartObjectProxy { public: From ab0aa1c25a3099968b51214ce773cbd9edf430da Mon Sep 17 00:00:00 2001 From: Anthony Rossi Date: Sat, 12 Jul 2025 12:10:48 +0200 Subject: [PATCH 4/6] Cleaned up code a bit --- src/kart/KartObjectProxy.cpp | 34 ++++++---------------------------- src/kart/KartObjectProxy.hpp | 4 ++-- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/kart/KartObjectProxy.cpp b/src/kart/KartObjectProxy.cpp index 08ae1e5be..2729821f6 100644 --- a/src/kart/KartObjectProxy.cpp +++ b/src/kart/KartObjectProxy.cpp @@ -39,40 +39,18 @@ const EGG::Vector3f& KartObjectProxy::getPos() const { return kartDynamics()->po const EGG::Vector3f& KartObjectProxy::getPrevPos() const { return kartPhysics()->pos; } -void KartObjectProxy::setPos(EGG::Vector3f *pos) { - float z,y,x; - KartDynamics* dynamics; - x = pos->x; - y = pos->y; - z = pos->z; - dynamics = kartDynamics(); - dynamics->pos.x = x; - dynamics->pos.y = y; - dynamics->pos.z = z; - - return; +void KartObjectProxy::setPos(const EGG::Vector3f &pos) { + kartDynamics()->pos = pos; } const EGG::Matrix34f& KartObjectProxy::getPose() const { return kartPhysics()->pose; } const EGG::Matrix34f& KartObjectProxy::getBodyRot() const { return kartBody()->pose; } -void KartObjectProxy::setRot(EGG::Quatf rot) { - KartDynamics* dynamics; - float w, x, y, z; - x = rot.x; - y = rot.y; - z = rot.z; - w = rot.w; - dynamics = kartDynamics(); - dynamics->fullRot.x = x; - dynamics->fullRot.y = y; - dynamics->fullRot.z = z; - dynamics->fullRot.w = w; - dynamics->mainRot.x = x; - dynamics->mainRot.y = y; - dynamics->mainRot.z = z; - dynamics->mainRot.w = w; +void KartObjectProxy::setRot(const EGG::Quatf &rot) { + KartDynamics* dynamics =kartDynamics(); + dynamics->fullRot = rot; + dynamics->mainRot = rot; } u16 KartObjectProxy::getSuspCount() { return kartSettings()->susCount; } diff --git a/src/kart/KartObjectProxy.hpp b/src/kart/KartObjectProxy.hpp index 8e6a2dea3..6f3826b5a 100644 --- a/src/kart/KartObjectProxy.hpp +++ b/src/kart/KartObjectProxy.hpp @@ -149,10 +149,10 @@ class KartObjectProxy { const EGG::Vector3f& getPos() const; const EGG::Vector3f& getPrevPos() const; - void setPos(EGG::Vector3f* pos); + void setPos(const EGG::Vector3f &pos); const EGG::Matrix34f& getPose() const; const EGG::Matrix34f& getBodyRot() const; - void setRot(EGG::Quatf rot); + void setRot(const EGG::Quatf& rot); u16 getSuspCount(); u16 getWheelCount(); float getWheelCountRecip(); From 82f76cb29791982376e2b8093f6a4b0a0b692fef Mon Sep 17 00:00:00 2001 From: Anthony Rossi Date: Sat, 12 Jul 2025 12:14:03 +0200 Subject: [PATCH 5/6] Style guide --- src/kart/KartSus.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/kart/KartSus.hpp b/src/kart/KartSus.hpp index 973f745d3..b71cc1df2 100644 --- a/src/kart/KartSus.hpp +++ b/src/kart/KartSus.hpp @@ -8,7 +8,8 @@ #include "kart/KartObjectProxy.hpp" namespace Kart { - class KartSusPhysics; +class KartSusPhysics; + class KartSus: KartPart { public: inline const KartSusPhysics* getPhysics() const { return susPhysics; } From c681e7e1dc674550f492268d14c8230939990e45 Mon Sep 17 00:00:00 2001 From: Anthony Rossi Date: Tue, 15 Jul 2025 08:52:50 +0200 Subject: [PATCH 6/6] styling --- src/kart/KartObjectProxy.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kart/KartObjectProxy.cpp b/src/kart/KartObjectProxy.cpp index 2729821f6..189e7adcd 100644 --- a/src/kart/KartObjectProxy.cpp +++ b/src/kart/KartObjectProxy.cpp @@ -48,7 +48,7 @@ const EGG::Matrix34f& KartObjectProxy::getPose() const { return kartPhysics()->p const EGG::Matrix34f& KartObjectProxy::getBodyRot() const { return kartBody()->pose; } void KartObjectProxy::setRot(const EGG::Quatf &rot) { - KartDynamics* dynamics =kartDynamics(); + KartDynamics* dynamics = kartDynamics(); dynamics->fullRot = rot; dynamics->mainRot = rot; }