A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
ObjectBase.cc
1#include "ObjectBase.hh"
2
3#include "game/field/ObjectDirector.hh"
4
5#include "game/system/CourseMap.hh"
6#include "game/system/ResourceManager.hh"
7#include "game/system/map/MapdataPointInfo.hh"
8
9#include <egg/math/Math.hh>
10
11#include <cstring>
12
13namespace Field {
14
16ObjectBase::ObjectBase(const System::MapdataGeoObj &params)
17 : m_drawMdl(nullptr), m_resFile(nullptr), m_id(static_cast<ObjectId>(params.id())),
18 m_railInterpolator(nullptr), m_pos(params.pos()), m_scale(params.scale()),
19 m_rot(params.rot() * DEG2RAD), m_rotLock(true), m_transform(EGG::Matrix34f::ident),
20 m_mapObj(&params) {
21 m_flags.setBit(eFlags::Position, eFlags::Rotation, eFlags::Scale);
22}
23
25ObjectBase::ObjectBase(const char *name, const EGG::Vector3f &pos, const EGG::Vector3f &rot,
26 const EGG::Vector3f &scale)
27 : m_drawMdl(nullptr), m_resFile(nullptr), m_railInterpolator(nullptr), m_pos(pos),
28 m_scale(scale), m_rot(rot), m_rotLock(true), m_transform(EGG::Matrix34f::ident),
29 m_mapObj(nullptr) {
30 m_flags.setBit(eFlags::Position, eFlags::Rotation, eFlags::Scale);
31 m_id = ObjectDirector::Instance()->flowTable().getIdFromName(name);
32}
33
35ObjectBase::~ObjectBase() {
36 delete m_resFile;
37 delete m_drawMdl;
38 delete m_railInterpolator;
39}
40
42void ObjectBase::calcModel() {
43 calcTransform();
44}
45
47const char *ObjectBase::getResources() const {
48 const auto &flowTable = ObjectDirector::Instance()->flowTable();
49 const auto *collisionSet = flowTable.set(flowTable.slot(id()));
50 ASSERT(collisionSet);
51 return collisionSet->resources;
52}
53
55void ObjectBase::loadGraphics() {
56 const char *name = getResources();
57 if (strcmp(name, "-") == 0) {
58 return;
59 }
60
61 char filename[128];
62 snprintf(filename, sizeof(filename), "%s.brres", name);
63
64 auto *resMgr = System::ResourceManager::Instance();
65 const void *resFile = resMgr->getFile(filename, nullptr, System::ArchiveId::Course);
66 if (resFile) {
67 m_resFile = new Abstract::g3d::ResFile(resFile);
68 m_drawMdl = new Render::DrawMdl;
69 }
70}
71
73void ObjectBase::loadRail() {
74 if (!m_mapObj) {
75 return;
76 }
77
78 s16 pathId = m_mapObj->pathId();
79
80 if (pathId == -1) {
81 return;
82 }
83
84 auto *point = System::CourseMap::Instance()->getPointInfo(pathId);
85 f32 speed = static_cast<f32>(m_mapObj->setting(0));
86
87 if (point->setting(0) == 0) {
88 m_railInterpolator = new RailLinearInterpolator(speed, pathId);
89 } else {
90 m_railInterpolator = new RailSmoothInterpolator(speed, pathId);
91 }
92}
93
95[[nodiscard]] const char *ObjectBase::getName() const {
96 const auto &flowTable = ObjectDirector::Instance()->flowTable();
97 const auto *collisionSet = flowTable.set(flowTable.slot(id()));
98 ASSERT(collisionSet);
99 return collisionSet->name;
100}
101
103const char *ObjectBase::getKclName() const {
104 const auto &flowTable = ObjectDirector::Instance()->flowTable();
105 const auto *collisionSet = flowTable.set(flowTable.slot(id()));
106 ASSERT(collisionSet);
107 return collisionSet->resources;
108}
109
111void ObjectBase::calcTransform() {
112 if (m_flags.onBit(eFlags::Rotation)) {
113 m_transform.makeRT(m_rot, m_pos);
114 m_flags.resetBit(eFlags::Rotation, eFlags::Position);
115 } else if (m_flags.onBit(eFlags::Position)) {
116 m_transform.setBase(3, m_pos);
117 m_flags.setBit(eFlags::Matrix);
118 }
119}
120
121void ObjectBase::calcRotLock() {
122 if (!m_rotLock) {
123 m_rotLock = true;
124 m_rot = m_transform.calcRPY();
125 }
126}
127
129void ObjectBase::linkAnims(const std::span<const char *> &names,
130 const std::span<Render::AnmType> types) {
131 if (!m_drawMdl) {
132 return;
133 }
134
135 ASSERT(names.size() == types.size());
136
137 for (size_t i = 0; i < names.size(); ++i) {
138 m_drawMdl->linkAnims(i, m_resFile, names[i], types[i]);
139 }
140}
141
143void ObjectBase::setMatrixTangentTo(const EGG::Vector3f &up, const EGG::Vector3f &tangent) {
144 m_rotLock = false;
145 m_flags.setBit(eFlags::Matrix);
146 SetRotTangentHorizontal(m_transform, up, tangent);
147 m_transform.setBase(3, m_pos);
148}
149
151void ObjectBase::setMatrixFromOrthonormalBasisAndPos(const EGG::Vector3f &v) {
152 m_flags.setBit(eFlags::Matrix);
153 m_transform = OrthonormalBasis(v);
154 m_transform.setBase(3, m_pos);
155}
156
159f32 ObjectBase::CheckPointAgainstLineSegment(const EGG::Vector3f &point, const EGG::Vector3f &a,
160 const EGG::Vector3f &b) {
161 return (b.x - a.x) * (point.z - a.z) - (point.x - a.x) * (b.z - a.z);
162}
163
166EGG::Vector3f ObjectBase::RotateXZByYaw(f32 angle, const EGG::Vector3f &v) {
167 f32 y = EGG::Mathf::SinFIdx(RAD2FIDX * (0.5f * angle));
168 f32 w = EGG::Mathf::CosFIdx(RAD2FIDX * (0.5f * angle));
169 EGG::Quatf quat = EGG::Quatf(w, 0.0f, y, 0.0f);
170 return quat.rotateVector(EGG::Vector3f(v.x, 0.0f, v.z));
171}
172
174EGG::Vector3f ObjectBase::RotateAxisAngle(f32 angle, const EGG::Vector3f &axis,
175 const EGG::Vector3f &v1) {
176 EGG::Matrix34f mat;
177 mat.setBase(3, EGG::Vector3f::zero);
178 mat.setAxisRotation(angle, axis);
179 return mat.ps_multVector(v1);
180}
181
183void ObjectBase::SetRotTangentHorizontal(EGG::Matrix34f &mat, const EGG::Vector3f &up,
184 const EGG::Vector3f &tangent) {
185 EGG::Vector3f vec = tangent - up * tangent.dot(up);
186 vec.normalise2();
187
188 mat.setBase(0, up.cross(vec));
189 mat.setBase(1, up);
190 mat.setBase(2, vec);
191}
192
194EGG::Matrix34f ObjectBase::OrthonormalBasis(const EGG::Vector3f &v) {
195 EGG::Vector3f z = v;
196
197 if (EGG::Mathf::abs(z.y) < 0.001f) {
198 z.y = 0.001f;
199 }
200
201 EGG::Vector3f h = EGG::Vector3f(v.x, 0.0f, v.z);
202 h.normalise2();
203
204 EGG::Vector3f x = (z.y > 0.0f) ? -h.cross(z) : h.cross(z);
205 x.normalise2();
206
207 EGG::Matrix34f mat;
208 mat.setBase(3, EGG::Vector3f::zero);
209 mat.setBase(0, x);
210 mat.setBase(1, z.cross(x));
211 mat.setBase(2, z);
212
213 return mat;
214}
215
217EGG::Matrix34f ObjectBase::RailOrthonormalBasis(const RailInterpolator &railInterpolator) {
218 EGG::Matrix34f mat = OrthonormalBasis(railInterpolator.curTangentDir());
219 mat.setBase(3, railInterpolator.curPos());
220 return mat;
221}
222
224EGG::Vector3f ObjectBase::AdjustVecForward(f32 sidewaysScalar, f32 forwardScalar, f32 minSpeed,
225 const EGG::Vector3f &src, EGG::Vector3f forward) {
226 if (forward.y > 0.0f) {
227 forward.y = 0.0f;
228 auto [mag, tmp] = forward.ps_normalized();
229
230 if (mag <= 0.0f) {
231 return src;
232 }
233
234 forward = tmp;
235 }
236
237 EGG::Vector3f proj = forward * src.ps_dot(forward);
238 EGG::Vector3f sideways = (src - proj) * sidewaysScalar;
239
240 EGG::Vector3f newForward = proj * -forwardScalar;
241 if (newForward.squaredLength() < minSpeed * minSpeed) {
242 newForward = forward * minSpeed;
243 }
244
245 return sideways + newForward;
246}
247
248} // namespace Field
Represents a binary resource file which contains object models, textures, and animations.
Definition ResFile.hh:15
A 3 x 4 matrix.
Definition Matrix.hh:8
void setBase(size_t col, const Vector3f &base)
Sets one column of a matrix.
Definition Matrix.cc:194
void setAxisRotation(f32 angle, const Vector3f &axis)
Rotates the matrix about an axis.
Definition Matrix.cc:180
Vector3f ps_multVector(const Vector3f &vec) const
Paired-singles impl. of multVector.
Definition Matrix.cc:237
EGG core library.
Definition Archive.cc:6
Pertains to collision.
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:88
f32 dot(const Vector3f &rhs) const
The dot product between two vectors.
Definition Vector.hh:187
f32 squaredLength() const
The dot product between the vector and itself.
Definition Vector.hh:182
f32 ps_dot() const
Paired-singles dot product implementation.
Definition Vector.cc:30