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 Kinoko::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_mapObj(&params), m_pos(params.pos()), m_scale(params.scale()),
19 m_rot(params.rot() * DEG2RAD), m_rotLock(true), m_transform(EGG::Matrix34f::ident) {
20 m_flags.setBit(eFlags::Position, eFlags::Rotation, eFlags::Scale);
21}
22
24ObjectBase::ObjectBase(const char *name, const EGG::Vector3f &pos, const EGG::Vector3f &rot,
25 const EGG::Vector3f &scale)
26 : m_drawMdl(nullptr), m_resFile(nullptr), m_railInterpolator(nullptr), m_mapObj(nullptr),
27 m_pos(pos), m_scale(scale), m_rot(rot), m_rotLock(true), m_transform(EGG::Matrix34f::ident) {
28 m_flags.setBit(eFlags::Position, eFlags::Rotation, eFlags::Scale);
29 m_id = ObjectDirector::Instance()->flowTable().getIdFromName(name);
30}
31
33ObjectBase::~ObjectBase() {
34 delete m_resFile;
35 delete m_drawMdl;
36 delete m_railInterpolator;
37}
38
40void ObjectBase::calcModel() {
41 calcTransform();
42}
43
45const char *ObjectBase::getResources() const {
46 const auto &flowTable = ObjectDirector::Instance()->flowTable();
47 const auto *collisionSet = flowTable.set(flowTable.slot(id()));
48 ASSERT(collisionSet);
49 return collisionSet->resources;
50}
51
53void ObjectBase::loadGraphics() {
54 const char *name = getResources();
55 if (strcmp(name, "-") == 0) {
56 return;
57 }
58
59 char filename[128];
60 snprintf(filename, sizeof(filename), "%s.brres", name);
61
62 auto *resMgr = System::ResourceManager::Instance();
63 const void *resFile = resMgr->getFile(filename, nullptr, System::ArchiveId::Course);
64 if (resFile) {
65 m_resFile = new Abstract::g3d::ResFile(resFile);
66 m_drawMdl = new Render::DrawMdl;
67 }
68}
69
71void ObjectBase::loadRail() {
72 if (!m_mapObj) {
73 return;
74 }
75
76 s16 pathId = m_mapObj->pathId();
77
78 if (pathId == -1) {
79 return;
80 }
81
82 auto *point = System::CourseMap::Instance()->getPointInfo(pathId);
83 f32 speed = static_cast<f32>(m_mapObj->setting(0));
84
85 if (point->setting(0) == 0) {
86 m_railInterpolator = new RailLinearInterpolator(speed, pathId);
87 } else {
88 m_railInterpolator = new RailSmoothInterpolator(speed, pathId);
89 }
90}
91
93[[nodiscard]] const char *ObjectBase::getName() const {
94 const auto &flowTable = ObjectDirector::Instance()->flowTable();
95 const auto *collisionSet = flowTable.set(flowTable.slot(id()));
96 ASSERT(collisionSet);
97 return collisionSet->name;
98}
99
101const char *ObjectBase::getKclName() const {
102 const auto &flowTable = ObjectDirector::Instance()->flowTable();
103 const auto *collisionSet = flowTable.set(flowTable.slot(id()));
104 ASSERT(collisionSet);
105 return collisionSet->resources;
106}
107
109void ObjectBase::calcTransform() {
110 if (m_flags.onBit(eFlags::Rotation)) {
111 m_transform.makeRT(m_rot, m_pos);
112 m_flags.resetBit(eFlags::Rotation, eFlags::Position);
113 } else if (m_flags.onBit(eFlags::Position)) {
114 m_transform.setBase(3, m_pos);
115 m_flags.setBit(eFlags::Matrix);
116 }
117}
118
119void ObjectBase::calcRotLock() {
120 if (!m_rotLock) {
121 m_rotLock = true;
122 m_rot = m_transform.calcRPY();
123 }
124}
125
127void ObjectBase::linkAnims(const std::span<const char *> &names,
128 const std::span<Render::AnmType> types) {
129 if (!m_drawMdl) {
130 return;
131 }
132
133 ASSERT(names.size() == types.size());
134
135 for (size_t i = 0; i < names.size(); ++i) {
136 m_drawMdl->linkAnims(i, m_resFile, names[i], types[i]);
137 }
138}
139
141void ObjectBase::setMatrixTangentTo(const EGG::Vector3f &up, const EGG::Vector3f &tangent) {
142 m_rotLock = false;
143 m_flags.setBit(eFlags::Matrix);
144 SetRotTangentHorizontal(m_transform, up, tangent);
145 m_transform.setBase(3, m_pos);
146}
147
149void ObjectBase::setMatrixFromOrthonormalBasisAndPos(const EGG::Vector3f &v) {
150 m_flags.setBit(eFlags::Matrix);
151 m_transform = OrthonormalBasis(v);
152 m_transform.setBase(3, m_pos);
153}
154
158 const EGG::Vector3f &b) {
159 return (b.x - a.x) * (point.z - a.z) - (point.x - a.x) * (b.z - a.z);
160}
161
165 f32 y = EGG::Mathf::SinFIdx(RAD2FIDX * (0.5f * angle));
166 f32 w = EGG::Mathf::CosFIdx(RAD2FIDX * (0.5f * angle));
167 EGG::Quatf quat = EGG::Quatf(w, 0.0f, y, 0.0f);
168 return quat.rotateVector(EGG::Vector3f(v.x, 0.0f, v.z));
169}
170
172EGG::Vector3f ObjectBase::RotateAxisAngle(f32 angle, const EGG::Vector3f &axis,
173 const EGG::Vector3f &v1) {
174 EGG::Matrix34f mat;
175 mat.setBase(3, EGG::Vector3f::zero);
176 mat.setAxisRotation(angle, axis);
177 return mat.ps_multVector(v1);
178}
179
181void ObjectBase::SetRotTangentHorizontal(EGG::Matrix34f &mat, const EGG::Vector3f &up,
182 const EGG::Vector3f &tangent) {
183 EGG::Vector3f vec = tangent - up * tangent.dot(up);
184 vec.normalise2();
185
186 mat.setBase(0, up.cross(vec));
187 mat.setBase(1, up);
188 mat.setBase(2, vec);
189}
190
192EGG::Matrix34f ObjectBase::OrthonormalBasis(const EGG::Vector3f &v) {
193 EGG::Vector3f z = v;
194
195 if (EGG::Mathf::abs(z.y) < 0.001f) {
196 z.y = 0.001f;
197 }
198
199 EGG::Vector3f h = EGG::Vector3f(v.x, 0.0f, v.z);
200 h.normalise2();
201
202 EGG::Vector3f x = (z.y > 0.0f) ? -h.cross(z) : h.cross(z);
203 x.normalise2();
204
205 EGG::Matrix34f mat;
206 mat.setBase(3, EGG::Vector3f::zero);
207 mat.setBase(0, x);
208 mat.setBase(1, z.cross(x));
209 mat.setBase(2, z);
210
211 return mat;
212}
213
215EGG::Matrix34f ObjectBase::RailOrthonormalBasis(const RailInterpolator &railInterpolator) {
216 EGG::Matrix34f mat = OrthonormalBasis(railInterpolator.curTangentDir());
217 mat.setBase(3, railInterpolator.curPos());
218 return mat;
219}
220
222EGG::Vector3f ObjectBase::AdjustVecForward(f32 sidewaysScalar, f32 forwardScalar, f32 minSpeed,
223 const EGG::Vector3f &src, EGG::Vector3f forward) {
224 if (forward.y > 0.0f) {
225 forward.y = 0.0f;
226 auto [mag, tmp] = forward.ps_normalized();
227
228 if (mag <= 0.0f) {
229 return src;
230 }
231
232 forward = tmp;
233 }
234
235 EGG::Vector3f proj = forward * src.ps_dot(forward);
236 EGG::Vector3f sideways = (src - proj) * sidewaysScalar;
237
238 EGG::Vector3f newForward = proj * -forwardScalar;
239 if (newForward.squaredLength() < minSpeed * minSpeed) {
240 newForward = forward * minSpeed;
241 }
242
243 return sideways + newForward;
244}
245
246} // namespace Kinoko::Field
A 3 x 4 matrix.
Definition Matrix.hh:10
constexpr void setAxisRotation(f32 angle, const EGG::Vector3f &axis)
Rotates the matrix about an axis.
Definition Matrix.hh:216
constexpr Vector3f ps_multVector(const Vector3f &vec) const
Paired-singles impl. of multVector.
Definition Matrix.hh:273
constexpr void setBase(size_t col, const Vector3f &base)
Sets one column of a matrix.
Definition Matrix.hh:230
static f32 CheckPointAgainstLineSegment(const EGG::Vector3f &point, const EGG::Vector3f &a, const EGG::Vector3f &b)
Calculates on what side of line segment ab point lies.
static EGG::Vector3f RotateXZByYaw(f32 angle, const EGG::Vector3f &v)
Rotates a vector around the Y-axis and returns the XZ-plane portion of the vector.
Pertains to collision.
A quaternion, used to represent 3D rotation.
Definition Quat.hh:12
constexpr Vector3f rotateVector(const Vector3f &vec) const
Rotates a vector based on the quat.
Definition Quat.hh:136
A 3D float vector.
Definition Vector.hh:107
constexpr f32 dot(const Vector3f &rhs) const
The dot product between two vectors.
Definition Vector.hh:206