1#include "KartCamera.hh"
3#include "game/field/CollisionDirector.hh"
4#include "game/field/ObjectDrivableDirector.hh"
14 constexpr f32 HOP_POS_INTERP_RATE = 0.8f;
15 constexpr f32 FORWARD_INTERP_RATE = 0.35f;
16 constexpr f32 HORIZ_POS_INTERP_RATE = 0.05f;
17 constexpr f32 VERT_POS_INTERP_RATE = 0.03f;
18 constexpr f32 FAST_VERT_POS_INTERP_RATE = 0.1f;
20 if (!Field::ObjectDrivableDirector::Instance()->hasCalcObjects()) {
24 const auto *kartObj = Kart::KartObjectManager::Instance()->object(0);
29 calcForward(FORWARD_INTERP_RATE, kartObj);
30 calcDriftOffset(kartObj);
32 calcCamera(HORIZ_POS_INTERP_RATE, VERT_POS_INTERP_RATE, FAST_VERT_POS_INTERP_RATE,
34 calcCamera(HORIZ_POS_INTERP_RATE, VERT_POS_INTERP_RATE, FAST_VERT_POS_INTERP_RATE,
43 s_instance = EGG::egg_new<KartCamera>();
47void KartCamera::DestroyInstance() {
49 auto *instance = s_instance;
51 EGG::egg_delete(instance);
55KartCamera::KartCamera() : m_hopPosY(0), m_forward(EGG::Vector3f::zero), m_camParams(nullptr) {}
58KartCamera::~KartCamera() =
default;
61void KartCamera::calcDriftOffset(
const Kart::KartObjectProxy *proxy) {
62 constexpr f32 MAX_DRIFT_YAW_AUTOMATIC = 10.0f;
63 constexpr f32 MAX_DRIFT_YAW_MANUAL = 15.0f;
64 constexpr f32 YAW_STEP_AUTOMATIC = 0.5f;
65 constexpr f32 YAW_STEP_MANUAL = 1.0f;
67 const auto &status = proxy->status();
69 f32 yaw =
static_cast<f32
>(proxy->hopStickX()) * -0.5f;
70 if (proxy->vehicleType() == Kart::KartParam::Stats::DriftType::Inside_Drift_Bike) {
77 f32 pitch = 90.0f - RAD2DEG * EGG::Mathf::acos(m_forward.dot(EGG::Vector3f::ey));
79 yawMax += 0.1f * EGG::Mathf::abs(pitch);
94void KartCamera::calcCamera(f32 horizInterpRate, f32 vertInterpRate, f32 fastVertInterpRate,
95 KartCameraState &state,
bool isBackwards,
const Kart::KartObjectProxy *proxy,
96 const EGG::Vector3f &targetPos)
const {
97 constexpr f32 BIG_AIR_PITCH_CAP = 89.0f * DEG2RAD;
99 EGG::Vector3f forwardDir = isBackwards ? -m_forward : m_forward;
100 EGG::Vector3f pitchAxis = m_right.cross(forwardDir);
101 pitchAxis.normalise();
105 const auto &status = proxy->status();
109 f32 bigAirPitch = std::min(BIG_AIR_PITCH_CAP, state.m_bigAirFallPitch);
111 EGG::Matrix34f bigAirPitchMat;
112 EGG::Matrix34f yawRotMat;
113 yawRotMat.setAxisRotation(driftYaw, m_right);
114 bigAirPitchMat.setAxisRotation(bigAirPitch, pitchAxis);
115 EGG::Vector3f orbitDir = yawRotMat.ps_multVector(bigAirPitchMat.ps_multVector(forwardDir));
118 RAD2DEG * EGG::Mathf::acos(std::clamp(orbitDir.dot(EGG::Vector3f::ey), -1.0f, 1.0f));
122 EGG::Matrix34f downPitchMat;
124 state.m_1c = state.m_1c + 0.2f * (fVar16 - state.m_1c);
125 downPitchMat.setAxisRotation(DEG2RAD * pitch * state.m_1c, pitchAxis);
126 orbitDir = downPitchMat.ps_multVector(orbitDir);
129 calcAirtimeHeight(state, proxy);
130 state.m_pos += targetPos - state.m_targetPos;
131 EGG::Vector3f posOffset = state.m_dist * orbitDir;
132 posOffset.y +=
m_camParams->posY - proxy->cameraDistY() + state.m_bigAirHeight;
134 EGG::Vector3f horizDelta = targetPos + posOffset - state.m_pos;
135 f32 vertDelta = horizDelta.y;
137 state.m_pos += horizInterpRate * horizDelta;
140 vertInterpRate = fastVertInterpRate;
142 state.m_pos.y += vertDelta * vertInterpRate;
144 EGG::Vector3f targetDelta = state.m_pos - targetPos;
145 if (targetDelta.ps_length() != 0.0f) {
146 state.m_pos = targetPos + state.m_dist * targetDelta.ps_normalize();
149 state.m_targetPos = targetPos;
154 const Kart::KartObjectProxy *proxy)
const {
155 constexpr f32 BIG_AIR_HEIGHT_CAP = 300.0f;
157 f32 targetPitch = 0.0f;
158 f32 interpRate = 0.2f;
159 const auto &status = proxy->status();
162 state.m_bigAirHeight = std::min(BIG_AIR_HEIGHT_CAP, state.m_bigAirHeight + 10.0f);
164 const EGG::Vector3f &vel = proxy->velocity();
166 targetPitch = std::min(0.3f, 0.005f * -vel.y);
170 state.m_bigAirHeight = 0.0f;
173 state.m_bigAirFallPitch += interpRate * (targetPitch - state.m_bigAirFallPitch);
177void KartCamera::initPos() {
178 constexpr f32 FORWARD_INTERP_RATE = 1.0f;
179 constexpr f32 HORIZ_POS_INTERP_RATE = 1.0f;
180 constexpr f32 VERT_POS_INTERP_RATE = 1.0f;
181 constexpr f32 FAST_VERT_POS_INTERP_RATE = 1.0f;
189 const auto *kartObj = Kart::KartObjectManager::Instance()->object(0);
190 calcForward(FORWARD_INTERP_RATE, kartObj);
191 calcCamera(HORIZ_POS_INTERP_RATE, VERT_POS_INTERP_RATE, FAST_VERT_POS_INTERP_RATE,
196void KartCamera::calcCollision(
KartCameraState &state,
bool isBackwards)
const {
197 constexpr f32 FRONT_RADIUS = 80.0f;
198 constexpr f32 BACK_RADIUS = 140.0f;
200 f32 radius = isBackwards ? BACK_RADIUS : FRONT_RADIUS;
201 Field::CollisionInfo info;
202 Field::KCLTypeMask mask;
206 Field::CollisionDirector::Instance()->resetCollisionEntries(&mask);
208 if (!Field::ObjectDrivableDirector::Instance()->checkSphereFullPush(radius, state.m_pos,
209 state.m_prevPos, KCL_TYPE_CAMERA_COLLIDABLE, &info, &mask, 0)) {
210 state.m_prevPos = state.m_pos;
Tracks the current state of the front and backwards player cameras.
Manager class for the forward and backwards cameras.
const Kart::KartParam::KartCameraParam * m_camParams
f32 m_hopPosY
Induces a downwards camera position offset.
f32 m_driftYaw
Rotation induced when drifting.
KartCameraState m_forwardCamera
Forward camera state.
KartCameraState m_backwardCamera
Rear camera state.
@ Hop
Set while we are in a drift hop. Clears when we land.
@ AirtimeOver20
Set after 20 frames of airtime, resets on landing.
@ DriftManual
Currently in a drift w/ manual.
@ AutoDrift
True if auto transmission, false if manual.
@ TouchingGround
Set when any part of the vehicle is colliding with floor KCL.
Pertains to rendering the kart model.