A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectFirebar.cc
1#include "ObjectFirebar.hh"
2
3namespace Kinoko::Field {
4
6ObjectFirebar::ObjectFirebar(const System::MapdataGeoObj &params) : ObjectCollidable(params) {
7 m_spokes = std::max<u32>(1, params.setting(3));
8 size_t fireballCount = std::max<u32>(1, params.setting(0) * m_spokes);
9 m_angSpeed = static_cast<f32>(static_cast<s16>(params.setting(1)));
10
11 m_fireballs = owning_span<ObjectFireball *>(fireballCount);
12
13 for (size_t i = 0; i < fireballCount; ++i) {
14 m_fireballs[i] = EGG::egg_new<ObjectFireball>(params);
15 m_fireballs[i]->load();
16
17 f32 ring = 1.0f + static_cast<f32>(i / m_spokes);
18 m_fireballs[i]->setDistance(
19 ring * (100.0f * static_cast<f32>(static_cast<s16>(params.setting(2)))));
20 m_fireballs[i]->setAngle((360.0f / m_spokes) * (i % m_spokes));
21 }
22
23 EGG::Matrix34f mat;
24 mat.makeR(rot());
25 m_axis = mat.base(2);
26 m_axis.normalise();
27 m_initDir = m_axis.cross(RotateAxisAngle(F_PI / 2.0f, EGG::Vector3f::ex, m_axis));
28 m_initDir.normalise();
29}
30
32ObjectFirebar::~ObjectFirebar() = default;
33
35void ObjectFirebar::init() {
36 m_degAngle = 0.0f;
37}
38
40void ObjectFirebar::calc() {
41 m_degAngle += m_angSpeed / 60.0f;
42
43 if (m_degAngle > 360.0f) {
44 m_degAngle -= 360.0f;
45 } else if (m_degAngle < 0.0f) {
46 m_degAngle += 360.0f;
47 }
48
49 // Every fireball on the same spoke shares the same angle. For Kinoko, we can leverage this fact
50 // to introduce a small performance improvement by building each spoke's rotation matrix once
51 // instead of calling RotateAxisAngle() once per fireball.
52 size_t spokeCount = std::min<size_t>(m_spokes, m_fireballs.size());
53 for (size_t spoke = 0; spoke < spokeCount; ++spoke) {
54 EGG::Matrix34f mat;
55 mat.setBase(3, EGG::Vector3f::zero);
56 mat.setAxisRotation((m_degAngle + m_fireballs[spoke]->angle()) * DEG2RAD, m_axis);
57
58 for (size_t i = spoke; i < m_fireballs.size(); i += m_spokes) {
59 auto *fireball = m_fireballs[i];
60 fireball->setPos(pos() + mat.ps_multVector(m_initDir * fireball->distance()));
61 }
62 }
63}
64
65} // namespace Kinoko::Field
Pertains to collision.