A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
CollisionGroup.cc
1#include "CollisionGroup.hh"
2
3namespace Kart {
4
6void CollisionData::reset() {
7 tangentOff.setZero();
8 floorNrm.setZero();
9 wallNrm.setZero();
10 vel.setZero();
11 relPos.setZero();
12 movement.setZero();
13 roadVelocity.setZero();
14 speedFactor = 1.0f;
15 rotFactor = 0.0f;
17 closestFloorSettings = 0xffffffff;
19 closestFloorSettings = 0xffffffff;
20 intensity = 0.0f;
21 colPerpendicularity = 0.0f;
22
23 bFloor = false;
24 bWall = false;
25 bInvisibleWall = false;
26 bWall3 = false;
27 bInvisibleWallOnly = false;
28 bSoftWall = false;
29 bTrickable = false;
30 bHasRoadVel = false;
31 bWallAtLeftCloser = false;
32 bWallAtRightCloser = false;
33}
34
36Hitbox::Hitbox() : m_bspHitbox(nullptr), m_ownsBSP(false) {}
37
39Hitbox::~Hitbox() {
40 if (m_ownsBSP) {
41 delete m_bspHitbox;
42 }
43}
44
47void Hitbox::calc(f32 totalScale, f32 sinkDepth, const EGG::Vector3f &scale, const EGG::Quatf &rot,
48 const EGG::Vector3f &pos) {
49 f32 fVar1 = 0.0f;
50 if (scale.y < totalScale) {
51 fVar1 = (totalScale - scale.y) * m_bspHitbox->radius;
52 }
53
54 EGG::Vector3f scaledPos = m_bspHitbox->position * scale;
55 scaledPos.y = (m_bspHitbox->position.y + sinkDepth) * scale.y + fVar1;
56
57 m_relPos = rot.rotateVector(scaledPos);
58 m_worldPos = m_relPos + pos;
59}
60
62void Hitbox::reset() {
63 m_worldPos.setZero();
64 m_lastPos.setZero();
65 m_relPos.setZero();
66}
67
69void Hitbox::setLastPos(const EGG::Vector3f &scale, const EGG::Matrix34f &pose) {
70 f32 yScaleFactor = scale.y;
71 EGG::Vector3f scaledPos = m_bspHitbox->position;
72 scaledPos.x *= scale.x;
73 scaledPos.z *= scale.z;
74
75 if (scale.y != scale.z && scale.y < 1.0f) {
76 scaledPos.y += (1.0f - scale.y) * m_radius;
77 yScaleFactor = scale.z;
78 }
79
80 scaledPos.y *= yScaleFactor;
81 m_lastPos = pose.ps_multVector(scaledPos);
82}
83
85CollisionGroup::CollisionGroup() : m_hitboxScale(1.0f) {
86 m_collisionData.reset();
87}
88
89CollisionGroup::~CollisionGroup() {
90 delete[] m_hitboxes.data();
91}
92
100f32 CollisionGroup::initHitboxes(const std::array<BSP::Hitbox, 16> &hitboxes) {
101 u16 bspHitboxCount = 0;
102
103 for (const auto &hitbox : hitboxes) {
104 if (parse<u16>(hitbox.enable)) {
105 ++bspHitboxCount;
106 }
107 }
108
109 m_hitboxes = std::span<Hitbox>(new Hitbox[bspHitboxCount], bspHitboxCount);
110 u16 hitboxIdx = 0;
111
112 for (const auto &bspHitbox : hitboxes) {
113 if (parse<u16>(bspHitbox.enable)) {
114 m_hitboxes[hitboxIdx++].setBspHitbox(&bspHitbox);
115 }
116 }
117
118 return computeCollisionLimits();
119}
120
125 EGG::Vector3f max = EGG::Vector3f::zero;
126
127 for (const auto &hitbox : m_hitboxes) {
128 const BSP::Hitbox *bspHitbox = hitbox.bspHitbox();
129
130 if (bspHitbox->enable == 0) {
131 continue;
132 }
133
134 max = max.maximize(bspHitbox->position.abs() + bspHitbox->radius);
135 }
136
137 // Get largest component of the vector
138 f32 maxComponent = max.z;
139
140 if (max.x <= max.y) {
141 if (max.z < max.y) {
142 maxComponent = max.y;
143 }
144 } else if (max.z < max.x) {
145 maxComponent = max.x;
146 }
147
148 m_boundingRadius = maxComponent;
149
150 return max.z * 0.5f;
151}
152
156void CollisionGroup::createSingleHitbox(f32 radius, const EGG::Vector3f &relPos) {
157 m_hitboxes = std::span<Hitbox>(new Hitbox[1], 1);
158
159 // TODO: Do we need for loop if this is just one?
160 // And how exactly will we identify to free the BSP::Hitbox on destruction?
161 for (auto &hitbox : m_hitboxes) {
162 hitbox.reset();
163 BSP::Hitbox *bspHitbox = new BSP::Hitbox;
164 hitbox.setBspHitbox(bspHitbox, true);
165 bspHitbox->position = relPos;
166 bspHitbox->radius = radius;
167 hitbox.setRadius(radius);
168 }
169 m_boundingRadius = radius;
170}
171
173void CollisionGroup::reset() {
174 m_collisionData.reset();
175
176 for (auto &hitbox : m_hitboxes) {
177 hitbox.reset();
178 hitbox.setRadius(hitbox.bspHitbox()->radius * m_hitboxScale);
179 }
180}
181
182void CollisionGroup::resetCollision() {
183 m_collisionData.reset();
184}
185
187void CollisionGroup::setHitboxScale(f32 scale) {
188 m_hitboxScale = scale;
189
190 for (auto &hitbox : m_hitboxes) {
191 hitbox.setRadius(hitbox.bspHitbox()->radius * m_hitboxScale);
192 }
193}
194
195} // namespace Kart
A 3 x 4 matrix.
Definition Matrix.hh:8
Vector3f ps_multVector(const Vector3f &vec) const
Paired-singles impl. of multVector.
Definition Matrix.cc:224
void createSingleHitbox(f32 radius, const EGG::Vector3f &relPos)
Creates a hitbox to represent a tire.
f32 computeCollisionLimits()
Sets the bounding radius.
f32 initHitboxes(const std::array< BSP::Hitbox, 16 > &hitboxes)
Initializes the hitbox array based on the KartParam's BSP hitboxes.
Represents a hitbox for the kart body or a wheel.
Pertains to kart-related functionality.
A quaternion, used to represent 3D rotation.
Definition Quat.hh:12
Vector3f rotateVector(const Vector3f &vec) const
Rotates a vector based on the quat.
Definition Quat.cc:55
A 3D float vector.
Definition Vector.hh:87
Vector3f abs() const
Returns the absolute value of each element of the vector.
Definition Vector.hh:213
Vector3f maximize(const Vector3f &rhs) const
Returns a vector whose elements are the max of the elements of both vectors.
Definition Vector.cc:65
Represents one of the many hitboxes that make up a vehicle.
Definition KartParam.hh:10
u16 enable
Specifies if this is an active hitbox (since BSP always has 16).
Definition KartParam.hh:11
EGG::Vector3f position
The relative position of the hitbox.
Definition KartParam.hh:12
Field::KCLTypeMask closestWallFlags
The colliding wall KCL flag's KColType.
u32 closestFloorSettings
The colliding floor KCL flag's "variant".
bool bFloor
Set if colliding with KCL which satisfies KCL_TYPE_FLOOR.
bool bWall3
Set if colliding with COL_TYPE_WALL_2.
bool bWall
Set if colliding with KCL which satisfies KCL_TYPE_WALL.
Field::KCLTypeMask closestFloorFlags
The colliding floor KCL flag's KColType.
s32 intensity
The KCL flag's "wheel depth".