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}
39
41void ObjectBase::calcModel() {
42 calcTransform();
43}
44
46const char *ObjectBase::getResources() const {
47 const auto &flowTable = ObjectDirector::Instance()->flowTable();
48 const auto *collisionSet = flowTable.set(flowTable.slot(id()));
49 ASSERT(collisionSet);
50 return collisionSet->resources;
51}
52
54void ObjectBase::loadGraphics() {
55 const char *name = getResources();
56 if (strcmp(name, "-") == 0) {
57 return;
58 }
59
60 char filename[128];
61 snprintf(filename, sizeof(filename), "%s.brres", name);
62
63 auto *resMgr = System::ResourceManager::Instance();
64 const void *resFile = resMgr->getFile(filename, nullptr, System::ArchiveId::Course);
65 if (resFile) {
66 m_resFile = new Abstract::g3d::ResFile(resFile);
67 m_drawMdl = new Render::DrawMdl;
68 }
69}
70
72void ObjectBase::loadRail() {
73 if (!m_mapObj) {
74 return;
75 }
76
77 s16 pathId = m_mapObj->pathId();
78
79 if (pathId == -1) {
80 return;
81 }
82
83 auto *point = System::CourseMap::Instance()->getPointInfo(pathId);
84 f32 speed = static_cast<f32>(m_mapObj->setting(0));
85
86 if (point->setting(0) == 0) {
87 m_railInterpolator = new RailLinearInterpolator(speed, pathId);
88 } else {
89 m_railInterpolator = new RailSmoothInterpolator(speed, pathId);
90 }
91}
92
94[[nodiscard]] const char *ObjectBase::getName() const {
95 const auto &flowTable = ObjectDirector::Instance()->flowTable();
96 const auto *collisionSet = flowTable.set(flowTable.slot(id()));
97 ASSERT(collisionSet);
98 return collisionSet->name;
99}
100
102const char *ObjectBase::getKclName() const {
103 const auto &flowTable = ObjectDirector::Instance()->flowTable();
104 const auto *collisionSet = flowTable.set(flowTable.slot(id()));
105 ASSERT(collisionSet);
106 return collisionSet->resources;
107}
108
110void ObjectBase::calcTransform() {
111 if (m_flags.onBit(eFlags::Rotation)) {
112 m_transform.makeRT(m_rot, m_pos);
113 m_flags.resetBit(eFlags::Rotation, eFlags::Position);
114 } else if (m_flags.onBit(eFlags::Position)) {
115 m_transform.setBase(3, m_pos);
116 m_flags.setBit(eFlags::Matrix);
117 }
118}
119
120void ObjectBase::calcRotLock() {
121 if (!m_rotLock) {
122 m_rotLock = true;
123 m_rot = m_transform.calcRPY();
124 }
125}
126
128void ObjectBase::linkAnims(const std::span<const char *> &names,
129 const std::span<Render::AnmType> types) {
130 if (!m_drawMdl) {
131 return;
132 }
133
134 ASSERT(names.size() == types.size());
135
136 for (size_t i = 0; i < names.size(); ++i) {
137 m_drawMdl->linkAnims(i, m_resFile, names[i], types[i]);
138 }
139}
140
142void ObjectBase::setMatrixTangentTo(const EGG::Vector3f &up, const EGG::Vector3f &tangent) {
143 m_rotLock = false;
144 m_flags.setBit(eFlags::Matrix);
145 SetRotTangentHorizontal(m_transform, up, tangent);
146 m_transform.setBase(3, m_pos);
147}
148
150void ObjectBase::setMatrixFromOrthonormalBasisAndPos(const EGG::Vector3f &v) {
151 m_flags.setBit(eFlags::Matrix);
152 m_transform = OrthonormalBasis(v);
153 m_transform.setBase(3, m_pos);
154}
155
158f32 ObjectBase::CheckPointAgainstLineSegment(const EGG::Vector3f &point, const EGG::Vector3f &a,
159 const EGG::Vector3f &b) {
160 return (b.x - a.x) * (point.z - a.z) - (point.x - a.x) * (b.z - a.z);
161}
162
165EGG::Vector3f ObjectBase::RotateXZByYaw(f32 angle, const EGG::Vector3f &v) {
166 f32 y = EGG::Mathf::SinFIdx(RAD2FIDX * (0.5f * angle));
167 f32 w = EGG::Mathf::CosFIdx(RAD2FIDX * (0.5f * angle));
168 EGG::Quatf quat = EGG::Quatf(w, 0.0f, y, 0.0f);
169 return quat.rotateVector(EGG::Vector3f(v.x, 0.0f, v.z));
170}
171
173EGG::Vector3f ObjectBase::RotateAxisAngle(f32 angle, const EGG::Vector3f &axis,
174 const EGG::Vector3f &v1) {
175 EGG::Matrix34f mat;
176 mat.setBase(3, EGG::Vector3f::zero);
177 mat.setAxisRotation(angle, axis);
178 return mat.ps_multVector(v1);
179}
180
182void ObjectBase::SetRotTangentHorizontal(EGG::Matrix34f &mat, const EGG::Vector3f &up,
183 const EGG::Vector3f &tangent) {
184 EGG::Vector3f vec = tangent - up * tangent.dot(up);
185 vec.normalise2();
186
187 mat.setBase(0, up.cross(vec));
188 mat.setBase(1, up);
189 mat.setBase(2, vec);
190}
191
193EGG::Matrix34f ObjectBase::OrthonormalBasis(const EGG::Vector3f &v) {
194 EGG::Vector3f z = v;
195
196 if (EGG::Mathf::abs(z.y) < 0.001f) {
197 z.y = 0.001f;
198 }
199
200 EGG::Vector3f h = EGG::Vector3f(v.x, 0.0f, v.z);
201 h.normalise2();
202
203 EGG::Vector3f x = (z.y > 0.0f) ? -h.cross(z) : h.cross(z);
204 x.normalise2();
205
206 EGG::Matrix34f mat;
207 mat.setBase(3, EGG::Vector3f::zero);
208 mat.setBase(0, x);
209 mat.setBase(1, z.cross(x));
210 mat.setBase(2, z);
211
212 return mat;
213}
214
216EGG::Matrix34f ObjectBase::RailOrthonormalBasis(const RailInterpolator &railInterpolator) {
217 EGG::Matrix34f mat = OrthonormalBasis(railInterpolator.curTangentDir());
218 mat.setBase(3, railInterpolator.curPos());
219 return mat;
220}
221
223EGG::Vector3f ObjectBase::AdjustVecForward(f32 sidewaysScalar, f32 forwardScalar, f32 minSpeed,
224 const EGG::Vector3f &src, EGG::Vector3f forward) {
225 if (forward.y > 0.0f) {
226 forward.y = 0.0f;
227 auto [mag, tmp] = forward.ps_normalized();
228
229 if (mag <= 0.0f) {
230 return src;
231 }
232
233 forward = tmp;
234 }
235
236 EGG::Vector3f proj = forward * src.ps_dot(forward);
237 EGG::Vector3f sideways = (src - proj) * sidewaysScalar;
238
239 EGG::Vector3f newForward = proj * -forwardScalar;
240 if (newForward.squaredLength() < minSpeed * minSpeed) {
241 newForward = forward * minSpeed;
242 }
243
244 return sideways + newForward;
245}
246
247} // 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