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
6namespace Field {
7
9ObjectPillarBase::ObjectPillarBase(const System::MapdataGeoObj &params) : ObjectKCL(params) {}
10
12ObjectPillarBase::~ObjectPillarBase() = default;
13
15ObjectPillarC::ObjectPillarC(const System::MapdataGeoObj &params)
16 : ObjectCollidable(params), m_fallStart(static_cast<u32>(params.setting(0))) {}
17
19ObjectPillarC::~ObjectPillarC() = default;
20
22void ObjectPillarC::calcCollisionTransform() {
23 constexpr f32 HEIGHT = 1900.0f;
24
25 if (!m_collision) {
26 return;
27 }
28
29 EGG::Matrix34f mat = EGG::Matrix34f::zero;
30 mat.makeT(EGG::Vector3f(0.0f, 2.0f * (HEIGHT * m_scale.y) / 3.0f, 0.0f));
31
32 calcTransform();
33
34 EGG::Vector3f speed = m_transform.ps_multVector(EGG::Vector3f::ez * 1000.0f);
35 m_collision->transform(m_transform.multiplyTo(mat), m_scale, speed);
36}
37
39ObjectPillar::ObjectPillar(const System::MapdataGeoObj &params)
40 : ObjectKCL(params), m_state(State::Upright), m_fallStart(static_cast<u32>(params.setting(0))),
41 m_targetRotation(F_PI * static_cast<f32>(params.setting(1)) / 180.0f), m_initRot(m_rot.x),
42 m_setupRot(EGG::Vector3f::zero) {
43 m_base = new ObjectPillarBase(params);
44 m_collidable = new ObjectPillarC(params);
45
46 m_base->load();
47 m_collidable->load();
48
49 m_groundFrame = std::numeric_limits<s32>::max();
50}
51
53ObjectPillar::~ObjectPillar() = default;
54
56void ObjectPillar::init() {
57 ObjectBase::init();
58
59 m_collidable->disableCollision();
60 m_setupRot = m_rot;
61 disableCollision();
62}
63
65void ObjectPillar::calc() {
66 u32 time = System::RaceManager::Instance()->timer();
67
68 if (m_state == State::Upright && time < m_fallStart) {
69 m_collidable->enableCollision();
70 } else if (m_state == State::Upright && time == m_fallStart) {
71 // The pillar has now started to fall.
72 m_state = State::Break;
73 } else if (m_state == State::Break) {
74 f32 rot = calcRot(static_cast<s32>(time));
75 if (rot < m_targetRotation) {
76 m_transform = getUpdatedMatrix(0);
77 m_pos = m_transform.base(3);
78
79 m_collidable->setTransform(m_transform);
80 m_collidable->setPos(m_pos);
81
82 m_flags.setBit(eFlags::Matrix, eFlags::Rotation);
83 m_rot = EGG::Vector3f(rot, m_setupRot.y, m_setupRot.z);
84 } else {
85 // The pillar has finished falling.
86 // We can now drive on top of the base and on the pillar itself.
87 m_state = State::Ground;
88
89 m_collidable->disableCollision();
90 enableCollision();
91 m_groundFrame = time;
92 }
93
94 } else {
95 m_state = State::Ground;
96 }
97}
98
100const EGG::Matrix34f &ObjectPillar::getUpdatedMatrix(u32 timeOffset) {
101 f32 rot = calcRot(System::RaceManager::Instance()->timer() - timeOffset);
102 m_workMat.makeRT(EGG::Vector3f(rot, m_setupRot.y, m_setupRot.z), m_pos);
103 return m_workMat;
104}
105
107f32 ObjectPillar::calcRot(s32 frame) const {
108 constexpr f32 STEP = 1e-7f;
109
110 if (m_groundFrame < frame) {
111 return m_targetRotation;
112 }
113
114 frame -= m_fallStart;
115 return std::min(m_targetRotation, m_initRot + STEP * static_cast<f32>(frame * frame * frame));
116}
117
118} // namespace Field
A 3 x 4 matrix.
Definition Matrix.hh:8
EGG core library.
Definition Archive.cc:6
Pertains to collision.
A 3D float vector.
Definition Vector.hh:88