A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectCollidable.cc
1#include "ObjectCollidable.hh"
2
3#include "game/field/ObjectCollisionBox.hh"
4#include "game/field/ObjectCollisionCylinder.hh"
5#include "game/field/ObjectCollisionSphere.hh"
6#include "game/field/ObjectDirector.hh"
7
8#include "game/kart/KartObject.hh"
9
10namespace Kinoko::Field {
11
13ObjectCollidable::ObjectCollidable(const System::MapdataGeoObj &params)
14 : ObjectBase(params), m_collision(nullptr) {}
15
17ObjectCollidable::ObjectCollidable(const char *name, const EGG::Vector3f &pos,
18 const EGG::Vector3f &rot, const EGG::Vector3f &scale)
19 : ObjectBase(name, pos, rot, scale), m_collision(nullptr) {}
20
22ObjectCollidable::~ObjectCollidable() {
23 EGG::egg_delete(m_collision);
24}
25
27void ObjectCollidable::load() {
28 loadGraphics();
29 loadAnims();
30 createCollision();
31
32 if (m_collision) {
33 loadAABB(0.0f);
34 }
35
36 loadRail();
37
38 ObjectDirector::Instance()->addObject(this);
39}
40
42void ObjectCollidable::calcCollisionTransform() {
43 calcTransform();
44 m_collision->transform(transform(), scale(), getCollisionTranslation());
45}
46
52 const auto &flowTable = ObjectDirector::Instance()->flowTable();
53 const auto *collisionSet = flowTable.set(flowTable.slot(id()));
54
55 f32 zRadius = scale().z * static_cast<f32>(parse<s16>(collisionSet->params.box.z));
56 f32 xRadius = scale().x * static_cast<f32>(parse<s16>(collisionSet->params.box.x));
57
58 return std::max(xRadius, zRadius);
59}
60
62void ObjectCollidable::loadAABB(f32 maxSpeed) {
63 loadAABB(getCollisionRadius(), maxSpeed);
64}
65
67void ObjectCollidable::loadAABB(f32 radius, f32 maxSpeed) {
68 auto *boxColMgr = BoxColManager::Instance();
69 const EGG::Vector3f &pos = getPosition();
70 bool alwaysRecalc = loadFlags() & 0x5;
71 m_boxColUnit = boxColMgr->insertObject(radius, maxSpeed, &pos, alwaysRecalc, this);
72}
73
75void ObjectCollidable::processKartReactions(Kart::KartObject *kartObj,
76 Kart::Reaction &reactionOnKart, Kart::Reaction &reactionOnObj) {
77 // Process the reaction on kart
78 if (kartObj->speedRatioCapped() < 0.5f) {
79 if (reactionOnKart == Kart::Reaction::SpinSomeSpeed) {
80 reactionOnKart = Kart::Reaction::WallAllSpeed;
81 } else if (reactionOnKart == Kart::Reaction::SpinHitSomeSpeed) {
82 reactionOnKart = Kart::Reaction::None;
83 }
84 } else {
85 if (reactionOnKart == Kart::Reaction::SpinHitSomeSpeed) {
86 reactionOnKart = Kart::Reaction::SpinSomeSpeed;
87 }
88 }
89
90 // Process the reaction on object
91 if (reactionOnObj == Kart::Reaction::UNK_3 || reactionOnObj == Kart::Reaction::UNK_4) {
92 reactionOnObj = Kart::Reaction::None;
93 }
94}
95
97bool ObjectCollidable::checkCollision(ObjectCollisionBase *lhs, EGG::Vector3f &dist) {
98 return lhs->check(*collision(), dist);
99}
100
102void ObjectCollidable::createCollision() {
103 const auto &flowTable = ObjectDirector::Instance()->flowTable();
104 const auto *collisionSet = flowTable.set(flowTable.slot(id()));
105
106 if (!collisionSet) {
107 PANIC("Invalid object ID when creating primitive collision! ID: %zu",
108 static_cast<size_t>(id()));
109 }
110
111 switch (static_cast<CollisionMode>(parse<s16>(collisionSet->mode))) {
112 case CollisionMode::Sphere:
113 m_collision = EGG::egg_new<ObjectCollisionSphere>(
114 parse<s16>(collisionSet->params.sphere.radius), collisionCenter());
115 break;
116 case CollisionMode::Cylinder:
117 m_collision = EGG::egg_new<ObjectCollisionCylinder>(
118 parse<s16>(collisionSet->params.cylinder.radius),
119 parse<s16>(collisionSet->params.cylinder.height), collisionCenter());
120 break;
121 case CollisionMode::Box:
122 m_collision = EGG::egg_new<ObjectCollisionBox>(parse<s16>(collisionSet->params.box.x),
123 parse<s16>(collisionSet->params.box.y), parse<s16>(collisionSet->params.box.z),
124 collisionCenter());
125 break;
126 default:
127 PANIC("Invalid collision mode when creating primitive collision! ID: %zu; Mode: %d",
128 static_cast<size_t>(id()), parse<s16>(collisionSet->mode));
129 break;
130 }
131}
132
134void ObjectCollidable::registerManagedObject() {
135 ObjectDirector::Instance()->addManagedObject(this);
136}
137
138} // namespace Kinoko::Field
f32 getCollisionRadius() const override
Finds the radius that fits fully in a BoxColUnit.
Pertains to collision.
CollisionMode
Maps to SObjectCollisionSet::mode. Determines what type of collision an object has.
A 3D float vector.
Definition Vector.hh:107