A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectPropeller.cc
1#include "ObjectPropeller.hh"
2
3#include "game/field/ObjectDirector.hh"
4
5namespace Kinoko::Field {
6
8ObjectPropeller::ObjectPropeller(const System::MapdataGeoObj &params)
9 : ObjectCollidable(params), m_angle(0.0f) {
10 m_blades.fill(nullptr);
11}
12
14ObjectPropeller::~ObjectPropeller() {
15 for (auto *&blade : m_blades) {
16 EGG::egg_delete(blade);
17 }
18}
19
21void ObjectPropeller::init() {
22 ASSERT(m_mapObj);
23 m_angVel = static_cast<f32>(static_cast<s16>(m_mapObj->setting(0)));
24 if (m_mapObj->setting(1) == 1) {
25 m_angVel = -m_angVel;
26 }
27
28 m_rotMat.makeR(rot());
29 m_rotMat.setBase(3, pos());
30 m_axis = m_rotMat.base(2);
31}
32
34void ObjectPropeller::calc() {
35 m_angle += m_angVel * 0.5f;
36 m_curRot = EGG::Matrix34f::ident;
37 m_curRot.setAxisRotation(m_angle * DEG2RAD, m_axis);
38 EGG::Matrix34f transform = m_curRot.multiplyTo(m_rotMat);
39 transform.setBase(3, pos());
40 setTransform(transform);
41}
42
44void ObjectPropeller::createCollision() {
45 ObjectCollidable::createCollision();
46
47 const auto &colCenter = collisionCenter();
48 const auto &flowTable = ObjectDirector::Instance()->flowTable();
49 const auto &params = flowTable.set(flowTable.slot(id()))->params.cylinder;
50 f32 radius = static_cast<f32>(parse<s16>(params.radius));
51 f32 height = static_cast<f32>(parse<s16>(params.height));
52
53 for (auto *&blade : m_blades) {
54 blade = EGG::egg_new<ObjectCollisionCylinder>(radius, height, colCenter);
55 }
56}
57
59void ObjectPropeller::calcCollisionTransform() {
60 constexpr f32 BLADE_LENGTH = 250.0f;
61
62 for (u32 i = 0; i < m_blades.size(); ++i) {
63 EGG::Matrix34f mat;
64 mat.setBase(3, EGG::Vector3f::zero);
65 mat.setAxisRotation(static_cast<f32>(i * 120) * DEG2RAD, m_axis);
66 calcTransform();
67 mat = mat.multiplyTo(transform());
68 EGG::Vector3f dir = mat.base(1);
69 dir.normalise();
70 dir *= BLADE_LENGTH;
71 mat.setBase(3, pos() + dir);
72
73 auto *&blade = m_blades[i];
74 blade->transform(mat, scale());
75 }
76}
77
80 const auto &flowTable = ObjectDirector::Instance()->flowTable();
81 const auto &params = flowTable.set(flowTable.slot(id()))->params.box;
82 f32 z = scale().z * static_cast<f32>(parse<s16>(params.z));
83 f32 x = scale().x * static_cast<f32>(parse<s16>(params.x));
84
85 return 5.0f * std::max(z, x);
86}
87
89bool ObjectPropeller::checkCollision(ObjectCollisionBase *lhs, EGG::Vector3f &dist) {
90 EGG::Vector3f dist0 = EGG::Vector3f::zero;
91 EGG::Vector3f dist1 = EGG::Vector3f::zero;
92 EGG::Vector3f dist2 = EGG::Vector3f::zero;
93
94 bool hasCol = lhs->check(*m_blades[0], dist0);
95 hasCol = hasCol || lhs->check(*m_blades[1], dist1);
96 hasCol = hasCol || lhs->check(*m_blades[2], dist2);
97
98 dist = dist0 + dist1 + dist2;
99
100 return hasCol;
101}
102
103} // namespace Kinoko::Field
The base class that all objects' collision inherits from.
f32 getCollisionRadius() const override
Finds the radius that fits fully in a BoxColUnit.
Pertains to collision.
A 3D float vector.
Definition Vector.hh:107