A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
JugemMove.cc
1#include "JugemMove.hh"
2
3#include "game/field/BoxColManager.hh"
4#include "game/field/CollisionDirector.hh"
5#include "game/field/ObjectDirector.hh"
6
7namespace Kinoko::Field {
8
10JugemMove::JugemMove(const Kart::KartObject *kartObj) : m_kartObj(kartObj) {}
11
13JugemMove::~JugemMove() = default;
14
16void JugemMove::init() {
17 m_28 = EGG::Matrix34f::ident;
18 m_58 = EGG::Matrix34f::ident;
19 m_88 = EGG::Matrix34f::ident;
20 m_transform = EGG::Matrix34f::ident;
21 m_phaseX = 0.0f;
22 m_phaseY = 0.0f;
23 m_pos.setZero();
24 m_transPos.setZero();
25 m_lastKartObjPos = m_kartObj->pos();
26 m_velDir.setZero();
27 m_riseVel.setZero();
28 m_dir.setZero();
29 m_anchorPos.setZero();
30 m_currForward.setZero();
31 m_targetForward = EGG::Vector3f::ez;
32 m_isAwayOrDescending = false;
33 m_velDirInterpRate = 1.0f;
34 m_forwardInterpRate = 0.08f;
35 m_isDescending = true;
36 m_isRising = false;
37}
38
40void JugemMove::calc() {
41 constexpr EGG::Vector3f VEC_809C28FC = EGG::Vector3f(0.0f, 40.0f, 0.0f);
42
43 const EGG::Vector3f &pos = m_kartObj->pos();
44 f32 fVar2 = (EGG::Mathf::abs(m_anchorPos.y - m_pos.y) - 200.0f) / 100.0f;
45 f32 fVar7 = std::clamp(fVar2, 0.0f, 1.0f);
46
47 f32 dVar6 = 0.4f + fVar7 * (0.8f - 0.4f);
48 f32 dVar5 = std::clamp(dVar6, 0.0f, 1.0f);
49
50 EGG::Vector3f kartObjPosDelta = pos - m_lastKartObjPos;
51 kartObjPosDelta.y = dVar5 * (pos.y - m_lastKartObjPos.y);
52 EGG::Vector3f local_74 = m_anchorPos - kartObjPosDelta - m_pos;
53 EGG::Vector3f local_80 = local_74;
54
55 fVar7 = local_80.normalise();
56 if (fVar7 > 200.0f) {
57 fVar2 = 0.75f;
58 } else {
59 fVar2 = 0.5f;
60 }
61 local_80 *= fVar2;
62
63 if (!m_isAwayOrDescending) {
64 m_velDirInterpRate = 0.0f;
65
66 if (fVar7 > 100.0f) {
67 m_velDir += local_80;
68 } else {
69 if (m_velDir.x * local_80.x < 0.0f) {
70 m_velDir.x += local_80.x;
71 }
72 if (m_velDir.y * local_80.y < 0.0f) {
73 m_velDir.y += local_80.y;
74 }
75 if (m_velDir.z * local_80.z < 0.0f) {
76 m_velDir.z += local_80.z;
77 }
78 }
79
80 fVar7 = 8.0f;
81 } else {
82 m_velDirInterpRate = std::min(1.0f, m_velDirInterpRate + 0.02f);
83 m_velDir = Interpolate(m_velDirInterpRate, local_80, local_74);
84 fVar7 = 25.0f;
85 }
86
87 dVar6 = fVar7;
88 fVar7 = m_velDir.normalise();
89 dVar5 = fVar7;
90 if (m_isDescending && dVar6 < dVar5) {
91 dVar5 = dVar6;
92 }
93
94 fVar7 = m_velDir.y * dVar5;
95 dVar6 = fVar7;
96
97 m_velDir *= dVar5;
98
99 if (!m_isRising) {
100 m_pos += kartObjPosDelta;
101 }
102
103 EGG::Vector3f local_8c = EGG::Vector3f::zero;
104 m_58 = calcOrthonormalBasis();
105 EGG::Vector3f local_d4 = calcOscillation(m_58);
106 dVar6 = local_d4.x;
107 local_8c = local_d4;
108
109 if (m_isRising) {
110 EGG::Vector3f local_a4 = EGG::Vector3f(kartObjPosDelta.x, 0.0f, kartObjPosDelta.z);
111 m_pos = m_pos + m_riseVel + local_a4;
112 m_isRising = false;
113 } else {
114 m_pos += m_velDir;
115 }
116
117 EGG::Vector3f local_b0 = m_pos + local_8c;
118 m_28 = FUN_807202BC();
119
120 m_58.setBase(3, VEC_809C28FC);
121 m_28.setBase(3, local_b0);
122
123 EGG::Matrix34f local_50 = EGG::Matrix34f::ident;
124 local_50 = local_50.multiplyTo(m_28);
125 local_50 = local_50.multiplyTo(m_58);
126 local_50 = local_50.multiplyTo(m_88);
127
128 m_transform = local_50;
129 m_transPos = m_transform.base(3);
130 m_lastKartObjPos = pos;
131}
132
134void JugemMove::setForwardFromKartObjPosDelta(bool setCurr) {
135 constexpr f32 FAST_INTERP_DIST = 250.0f;
136 constexpr f32 SLOW_INTERP_RATE = 0.03f;
137 constexpr f32 FAST_INTERP_RATE = 0.08f;
138
139 EGG::Vector3f forward = m_kartObj->pos() - m_pos;
140 forward.y = 0.0f;
141 f32 dist = forward.normalise();
142
143 if (forward.squaredLength() <= std::numeric_limits<f32>::epsilon()) {
144 forward = EGG::Vector3f::ez;
145 }
146
147 if (setCurr) {
148 m_currForward = forward;
149 }
150
151 m_targetForward = forward;
152 m_forwardInterpRate = dist < FAST_INTERP_DIST ? SLOW_INTERP_RATE : FAST_INTERP_RATE;
153}
154
156void JugemMove::setForwardFromKartObjMainRot(bool setCurr) {
157 EGG::Vector3f forward = m_kartObj->mainRot().rotateVector(EGG::Vector3f::ez);
158 forward.y = 0.0f;
159 forward *= -1.0f;
160 forward.normalise2();
161
162 if (forward.squaredLength() <= std::numeric_limits<f32>::epsilon()) {
163 forward = EGG::Vector3f::ez;
164 }
165
166 if (setCurr) {
167 m_currForward = forward;
168 }
169
170 m_targetForward = forward;
171}
172
174EGG::Matrix34f JugemMove::calcOrthonormalBasis() {
175 m_currForward = Interpolate(m_forwardInterpRate, m_currForward, m_targetForward);
176 m_currForward.normalise();
177
178 const EGG::Vector3f &up = EGG::Vector3f::ey;
179 EGG::Vector3f forward = m_currForward;
180
181 if (forward.squaredLength() <= std::numeric_limits<f32>::epsilon()) {
182 forward = EGG::Vector3f::ez;
183 }
184
185 EGG::Vector3f right = up.cross(forward);
186 right.normalise();
187
188 forward = right.cross(up);
189 forward.normalise();
190
191 EGG::Matrix34f mat = EGG::Matrix34f::ident;
192 mat.setBase(0, right);
193 mat.setBase(1, up);
194 mat.setBase(2, forward);
195
196 return mat;
197}
198
200EGG::Vector3f JugemMove::calcOscillation(const EGG::Matrix34f &mat) {
201 constexpr f32 PHASE_X_STEP = 0.04f;
202 constexpr f32 PHASE_Y_STEP = 0.08f;
203 constexpr f32 AMPLITUDE_X = 80.0f;
204 constexpr f32 AMPLITUDE_Y = 30.0f;
205
206 m_phaseX += PHASE_X_STEP;
207 m_phaseY += PHASE_Y_STEP;
208
209 if (m_phaseX > F_TAU) {
210 m_phaseX -= F_TAU;
211 }
212
213 if (m_phaseY > F_TAU) {
214 m_phaseY -= F_TAU;
215 }
216
217 f32 cosX = EGG::Mathf::CosFIdx(RAD2FIDX * m_phaseX);
218 f32 sinY = EGG::Mathf::SinFIdx(RAD2FIDX * m_phaseY);
219 EGG::Vector3f v = EGG::Vector3f(AMPLITUDE_X * cosX, AMPLITUDE_Y * sinY, 0.0f);
220
221 return mat.ps_multVector(v);
222}
223
225EGG::Matrix34f JugemMove::FUN_807202BC() {
226 constexpr EGG::Vector3f VEC_809C28E4 = EGG::Vector3f(0.0f, 100.0f, 0.0f);
227
228 m_dir = Interpolate(0.1f, m_dir, m_velDir);
229 f32 fVar2 = m_dir.normalise();
230 fVar2 = std::min(20.0f, fVar2);
231
232 m_dir *= fVar2;
233 EGG::Vector3f avStack_38 = m_dir * 1.5f;
234 EGG::Vector3f up = VEC_809C28E4 - avStack_38;
235 fVar2 = VEC_809C28E4.length();
236 f32 dVar1 = fVar2;
237 fVar2 = up.length();
238 dVar1 = fVar2 / dVar1;
239 up.normalise();
240
241 up *= dVar1;
242 if (up.squaredLength() <= std::numeric_limits<f32>::epsilon()) {
243 up = EGG::Vector3f::ey;
244 }
245
246 EGG::Matrix34f mat = EGG::Matrix34f::ident;
247 mat.setBase(0, EGG::Vector3f::ex);
248 mat.setBase(1, up);
249 mat.setBase(2, EGG::Vector3f::ez);
250
251 return mat;
252}
253
254} // namespace Kinoko::Field
Pertains to collision.