1#include "KartSuspensionPhysics.hh"
3#include "game/kart/KartBody.hh"
4#include "game/kart/KartCollide.hh"
5#include "game/kart/KartDynamics.hh"
6#include "game/kart/KartState.hh"
7#include "game/kart/KartSub.hh"
8#include "game/kart/KartTire.hh"
10#include <egg/math/Math.hh>
15WheelPhysics::WheelPhysics(
u16 wheelIdx,
u16 bspWheelIdx)
16 : m_wheelIdx(wheelIdx), m_bspWheelIdx(bspWheelIdx), m_bspWheel(nullptr) {}
19WheelPhysics::~WheelPhysics() {
24void WheelPhysics::init() {
25 m_hitboxGroup =
new CollisionGroup;
26 m_hitboxGroup->createSingleHitbox(10.0f, EGG::Vector3f::zero);
30void WheelPhysics::initBsp() {
31 m_bspWheel = &bsp().wheels[m_bspWheelIdx];
35void WheelPhysics::reset() {
38 m_lastPosDiff.setZero();
42 m_wheelEdgePos.setZero();
43 m_effectiveRadius = 0.0f;
44 m_targetEffectiveRadius = 0.0f;
46 m_topmostPos.setZero();
49 m_suspTravel = m_bspWheel->maxTravel;
50 m_effectiveRadius = m_bspWheel->wheelRadius;
56 const EGG::Vector3f topmostPos = m_topmostPos + vehicleMovement;
57 f32 scaledMaxTravel = m_bspWheel->maxTravel * sub()->someScale();
58 f32 suspTravel = bottom.
dot(m_pos - topmostPos);
59 m_suspTravel = std::max(0.0f, std::min(scaledMaxTravel, suspTravel));
60 m_pos = topmostPos + m_suspTravel * bottom;
61 m_speed = m_pos - m_lastPos;
62 m_speed -= dynamics()->intVel();
63 m_speed -= dynamics()->movingObjVel();
64 m_speed -= collisionData().movement;
65 m_speed -= collide()->movement();
66 m_hitboxGroup->collisionData().vel += m_speed;
68 m_lastPosDiff = m_pos - topmostPos;
73 m_targetEffectiveRadius = m_bspWheel->wheelRadius;
74 auto &status = KartObjectProxy::status();
76 if (status.offBit(eStatus::SkipWheelCalc)) {
77 f32 nextRadius = m_bspWheel->sphereRadius;
78 f32 scalar = m_effectiveRadius * scale().y - nextRadius * move()->totalScale();
81 scalar = 0.3f * (nextRadius * move()->leanRot()) * move()->totalScale();
82 center += scalar * bodyForward();
84 if (status.onBit(eStatus::HalfpipeMidair, eStatus::InCannon)) {
85 m_hitboxGroup->collisionData().reset();
87 m_hitboxGroup->setHitboxScale(move()->totalScale());
88 if (status.onBit(eStatus::UNK2)) {
89 m_hitboxGroup->hitbox(0).setLastPos(dynamics()->pos());
92 collide()->calcWheelCollision(m_wheelIdx, m_hitboxGroup, m_colVel, center, nextRadius);
93 CollisionData &colData = m_hitboxGroup->collisionData();
95 if (colData.bFloor || colData.bWall || colData.bWall3) {
96 m_pos += colData.tangentOff;
97 if (colData.intensity > -1) {
98 f32 sinkDepth = 3.0f *
static_cast<f32
>(colData.intensity);
99 m_targetEffectiveRadius = m_bspWheel->wheelRadius - sinkDepth;
100 body()->trySetTargetSinkDepth(sinkDepth);
104 m_hitboxGroup->hitbox(0).setLastPos(center);
107 m_topmostPos = topmostPos;
108 m_wheelEdgePos = m_pos + m_effectiveRadius * move()->totalScale() * bottom;
109 m_effectiveRadius += (m_targetEffectiveRadius - m_effectiveRadius) * 0.1f;
110 m_suspTravel = bottom.
dot(m_pos - topmostPos);
112 if (m_suspTravel < 0.0f) {
115 sub()->updateSuspOvertravel(suspBottom);
122void WheelPhysics::calcSuspension(
const EGG::Vector3f &forward) {
124 status().onBit(eStatus::SomethingWallCollision) ? 0.01f : collide()->floorMomentRate();
126 collide()->applySomeFloorMoment(0.1f, rate, m_hitboxGroup, forward, move()->dir(), speed(),
127 true,
true, status().offBit(eStatus::LargeFlipHit, eStatus::WheelieRot));
131KartSuspensionPhysics::KartSuspensionPhysics(
u16 wheelIdx, TireType tireType,
u16 bspWheelIdx)
132 : m_tirePhysics(nullptr), m_tireType(tireType), m_bspWheelIdx(bspWheelIdx),
133 m_wheelIdx(wheelIdx) {}
136KartSuspensionPhysics::~KartSuspensionPhysics() =
default;
139void KartSuspensionPhysics::init() {
140 m_tirePhysics = tire(m_wheelIdx)->wheelPhysics();
141 m_bspWheel = &bsp().wheels[m_bspWheelIdx];
145void KartSuspensionPhysics::reset() {
146 m_topmostPos.setZero();
147 m_maxTravelScaled = 0.0f;
148 m_bottomDir.setZero();
152void KartSuspensionPhysics::setInitialState() {
154 if (m_tireType == TireType::KartReflected) {
155 relPos.x = -relPos.x;
158 const EGG::Vector3f rotatedRelPos = dynamics()->fullRot().rotateVector(relPos) + pos();
159 const EGG::Vector3f unitRotated = dynamics()->fullRot().rotateVector(-EGG::Vector3f::ey);
161 m_tirePhysics->setPos(rotatedRelPos + m_bspWheel->maxTravel * unitRotated);
162 m_tirePhysics->setLastPos(rotatedRelPos + m_bspWheel->maxTravel * unitRotated);
163 m_tirePhysics->setLastPosDiff(m_tirePhysics->pos() - rotatedRelPos);
164 m_tirePhysics->setWheelEdgePos(m_tirePhysics->pos() +
165 (m_tirePhysics->effectiveRadius() * move()->totalScale() * unitRotated));
166 m_tirePhysics->hitboxGroup()->hitbox(0).setWorldPos(m_tirePhysics->pos());
167 m_tirePhysics->hitboxGroup()->hitbox(0).setLastPos(pos() + 100 * EGG::Vector3f::ey);
168 m_topmostPos = rotatedRelPos;
172void KartSuspensionPhysics::calcCollision(f32 dt,
const EGG::Vector3f &gravity,
174 m_maxTravelScaled = m_bspWheel->maxTravel * sub()->someScale();
176 EGG::Vector3f scaledRelPos = m_bspWheel->relPosition * scale();
177 if (m_tireType == TireType::KartReflected) {
178 scaledRelPos.x = -scaledRelPos.x;
183 EGG::Vector3f euler_angles(m_bspWheel->xRot * DEG2RAD, 0.0f, 0.0f);
184 mStack_60.
makeR(euler_angles);
188 f32 y_down = m_tirePhysics->suspTravel() + 5.0f * sub()->someScale();
189 m_tirePhysics->setSuspTravel(std::max(0.0f, std::min(m_maxTravelScaled, y_down)));
190 m_tirePhysics->setColVel(dt * 10.0f * gravity);
191 m_tirePhysics->setPos(topmostPos + m_tirePhysics->suspTravel() * m_bottomDir);
193 if (status().offBit(eStatus::SkipWheelCalc)) {
194 m_tirePhysics->updateCollision(m_bottomDir, topmostPos);
195 m_topmostPos = topmostPos;
206 m_tirePhysics->realign(m_bottomDir, vehicleMovement);
208 CollisionData &collisionData = m_tirePhysics->hitboxGroup()->collisionData();
209 if (!collisionData.
bFloor) {
214 f32 yDown = std::max(0.0f, m_bottomDir.dot(topDiff));
216 f32 travel = m_maxTravelScaled - yDown;
217 f32 speedScalar = m_bottomDir.dot(speed);
220 -(m_bspWheel->springStiffness * travel + m_bspWheel->dampingFactor * speedScalar);
225 fRot.y = std::max(-1.0f, std::min(1.0f, fRot.y));
232 rotProj = rotProj.
proj(collisionData.floorNrm);
233 fLinear.y += rotProj.y;
234 fLinear.y = std::min(fLinear.y, param()->stats().maxNormalAcceleration);
236 auto &status = KartObjectProxy::status();
238 if (dynamics()->extVel().y > 5.0f || status.onBit(eStatus::JumpPadDisableYsusForce)) {
242 dynamics()->applySuspensionWrench(m_topmostPos, fLinear, fRot,
243 status.onBit(eStatus::WheelieRot));
245 m_tirePhysics->calcSuspension(forward);
Vector3f multVector33(const Vector3f &vec) const
Multiplies a 3x3 matrix by a vector.
void makeR(const Vector3f &r)
Sets 3x3 rotation matrix from a vector of Euler angles.
Vector3f ps_multVector(const Vector3f &vec) const
Paired-singles impl. of multVector.
Pertains to kart-related functionality.
f32 dot(const Vector3f &rhs) const
The dot product between two vectors.
Vector3f proj(const Vector3f &rhs) const
The projection of this vector onto rhs.
Information about the current collision and its properties.
bool bFloor
Set if colliding with KCL which satisfies KCL_TYPE_FLOOR.