A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectPillar.cc
1
2#include "ObjectPillar.hh"
3
4#include "game/field/ObjectDirector.hh"
5
6#include "game/kart/Reaction.hh"
7
8namespace Kinoko::Field {
9
11ObjectPillarBase::ObjectPillarBase(const System::MapdataGeoObj &params) : ObjectKCL(params) {}
12
14ObjectPillarBase::~ObjectPillarBase() = default;
15
17ObjectPillarC::ObjectPillarC(const System::MapdataGeoObj &params)
18 : ObjectCollidable(params), m_fallStart(static_cast<u32>(params.setting(0))) {}
19
21ObjectPillarC::~ObjectPillarC() = default;
22
24void ObjectPillarC::calcCollisionTransform() {
25 constexpr f32 HEIGHT = 1900.0f;
26
27 if (!m_collision) {
28 return;
29 }
30
31 EGG::Matrix34f mat = EGG::Matrix34f::zero;
32 mat.makeT(EGG::Vector3f(0.0f, 2.0f * (HEIGHT * scale().y) / 3.0f, 0.0f));
33
34 calcTransform();
35
36 EGG::Vector3f speed = transform().ps_multVector(EGG::Vector3f::ez * 1000.0f);
37 m_collision->transform(transform().multiplyTo(mat), scale(), speed);
38}
39
41ObjectPillar::ObjectPillar(const System::MapdataGeoObj &params)
42 : ObjectKCL(params), m_state(State::Upright), m_fallStart(static_cast<u32>(params.setting(0))),
43 m_targetRotation(F_PI * static_cast<f32>(params.setting(1)) / 180.0f), m_initRot(rot().x),
44 m_setupRot(EGG::Vector3f::zero) {
45 m_base = EGG::egg_new<ObjectPillarBase>(params);
46 m_collidable = EGG::egg_new<ObjectPillarC>(params);
47
48 m_base->load();
49 m_collidable->load();
50
51 m_groundFrame = std::numeric_limits<s32>::max();
52}
53
55ObjectPillar::~ObjectPillar() = default;
56
58void ObjectPillar::init() {
59 ObjectBase::init();
60
61 m_collidable->disableCollision();
62 m_setupRot = rot();
63 disableCollision();
64}
65
67void ObjectPillar::calc() {
68 u32 time = System::RaceManager::Instance()->timer();
69
70 if (m_state == State::Upright && time < m_fallStart) {
71 m_collidable->enableCollision();
72 } else if (m_state == State::Upright && time == m_fallStart) {
73 // The pillar has now started to fall.
74 m_state = State::Break;
75 } else if (m_state == State::Break) {
76 f32 rot = calcRot(static_cast<s32>(time));
77 if (rot < m_targetRotation) {
78 setTransform(getUpdatedMatrix(0));
79 m_collidable->setTransform(transform());
80
81 setRot(EGG::Vector3f(rot, m_setupRot.y, m_setupRot.z));
82 } else {
83 // The pillar has finished falling.
84 // We can now drive on top of the base and on the pillar itself.
85 m_state = State::Ground;
86
87 m_collidable->disableCollision();
88 enableCollision();
89 m_groundFrame = time;
90 }
91
92 } else {
93 m_state = State::Ground;
94 }
95}
96
98const EGG::Matrix34f &ObjectPillar::getUpdatedMatrix(u32 timeOffset) {
99 f32 rot = calcRot(System::RaceManager::Instance()->timer() - timeOffset);
100 m_workMat.makeRT(EGG::Vector3f(rot, m_setupRot.y, m_setupRot.z), pos());
101 return m_workMat;
102}
103
105f32 ObjectPillar::calcRot(s32 frame) const {
106 constexpr f32 STEP = 1e-7f;
107
108 if (m_groundFrame < frame) {
109 return m_targetRotation;
110 }
111
112 frame -= m_fallStart;
113 return std::min(m_targetRotation, m_initRot + STEP * static_cast<f32>(frame * frame * frame));
114}
115
116} // namespace Kinoko::Field
Pertains to collision.