A reimplementation of Mario Kart Wii's physics engine in C++
Loading...
Searching...
No Matches
Vector.hh
1#pragma once
2
3#include "egg/math/Math.hh"
4
5#include "egg/util/Stream.hh"
6
7#include <format>
8
9namespace Kinoko::EGG {
10
12struct Vector2f {
13#ifdef BUILD_DEBUG
14 constexpr Vector2f()
15 : x(std::numeric_limits<f32>::signaling_NaN()),
16 y(std::numeric_limits<f32>::signaling_NaN()) {}
17#else
18 constexpr Vector2f() = default;
19#endif
20 constexpr Vector2f(f32 x_, f32 y_) : x(x_), y(y_) {}
21 constexpr ~Vector2f() = default;
22
23 constexpr inline void set(f32 val) {
24 x = y = val;
25 }
26
27 [[nodiscard]] constexpr Vector2f operator-() const {
28 return Vector2f(-x, -y);
29 }
30
31 [[nodiscard]] constexpr Vector2f operator-(const Vector2f &rhs) const {
32 return Vector2f(x - rhs.x, y - rhs.y);
33 }
34
35 [[nodiscard]] constexpr Vector2f operator+(const Vector2f &rhs) const {
36 return Vector2f(x + rhs.x, y + rhs.y);
37 }
38
39 constexpr Vector2f &operator+=(const Vector2f &rhs) {
40 return *this = *this + rhs;
41 }
42
43 [[nodiscard]] constexpr Vector2f operator*(const f32 scalar) const {
44 return Vector2f(x * scalar, y * scalar);
45 }
46
47 constexpr Vector2f &operator*=(const f32 scalar) {
48 return *this = *this * scalar;
49 }
50
51 friend constexpr Vector2f operator*(f32 scalar, const Vector2f &rhs) {
52 return Vector2f(scalar * rhs.x, scalar * rhs.y);
53 }
54
55 [[nodiscard]] constexpr f32 cross(const Vector2f &rhs) const {
56 return x * rhs.y - y * rhs.x;
57 }
58
59 [[nodiscard]] constexpr f32 dot(const Vector2f &rhs) const {
60 return x * rhs.x + y * rhs.y;
61 }
62
63 [[nodiscard]] constexpr f32 dot() const {
64 return x * x + y * y;
65 }
66
67 [[nodiscard]] constexpr f32 length() const {
68 return dot() > std::numeric_limits<f32>::epsilon() ? Mathf::sqrt(dot()) : 0.0f;
69 }
70
72 constexpr f32 normalise() {
73 f32 len = length();
74 if (len != 0.0f) {
75 *this = *this * (1.0f / len);
76 }
77
78 return len;
79 }
80
82 constexpr void normalise2() {
83 f32 sqLen = dot();
84 if (sqLen > std::numeric_limits<f32>::epsilon()) {
85 *this *= EGG::Mathf::frsqrt(sqLen);
86 }
87 }
88
90 void read(Stream &stream) {
91 x = stream.read_f32();
92 y = stream.read_f32();
93 }
94
95 f32 x;
96 f32 y;
97
98 static const Vector2f zero;
99 static const Vector2f ex, ey;
100};
101
102inline constexpr Vector2f Vector2f::zero = Vector2f(0.0f, 0.0f);
103inline constexpr Vector2f Vector2f::ex = Vector2f(1.0f, 0.0f);
104inline constexpr Vector2f Vector2f::ey = Vector2f(0.0f, 1.0f);
105
107struct Vector3f {
108#ifdef BUILD_DEBUG
109 constexpr Vector3f()
110 : x(std::numeric_limits<f32>::signaling_NaN()),
111 y(std::numeric_limits<f32>::signaling_NaN()),
112 z(std::numeric_limits<f32>::signaling_NaN()) {}
113#else
114 constexpr Vector3f() = default;
115#endif
116 constexpr Vector3f(f32 x_, f32 y_, f32 z_) : x(x_), y(y_), z(z_) {}
117
118 // NOTE: Defining the destructor in the header ensures the struct is trivially destructible
119 constexpr ~Vector3f() = default;
120
121 constexpr inline void setZero() {
122 set(0.0f);
123 }
124
125 constexpr inline void set(f32 val) {
126 x = y = z = val;
127 }
128
129 [[nodiscard]] constexpr Vector3f operator-() const {
130 return Vector3f(-x, -y, -z);
131 }
132
133 [[nodiscard]] constexpr Vector3f operator-(const Vector3f &rhs) const {
134 return Vector3f(x - rhs.x, y - rhs.y, z - rhs.z);
135 }
136
137 constexpr Vector3f &operator-=(const Vector3f &rhs) {
138 return *this = *this - rhs;
139 }
140
141 [[nodiscard]] constexpr Vector3f operator+(const Vector3f &rhs) const {
142 return Vector3f(x + rhs.x, y + rhs.y, z + rhs.z);
143 }
144
145 constexpr Vector3f &operator+=(const Vector3f &rhs) {
146 return *this = *this + rhs;
147 }
148
149 [[nodiscard]] constexpr Vector3f operator+(f32 val) const {
150 return Vector3f(x + val, y + val, z + val);
151 }
152
153 constexpr Vector3f &operator+=(f32 val) {
154 return *this = *this + val;
155 }
156
157 [[nodiscard]] constexpr Vector3f operator*(const Vector3f &rhs) const {
158 return Vector3f(x * rhs.x, y * rhs.y, z * rhs.z);
159 }
160
161 [[nodiscard]] constexpr Vector3f operator*(f32 scalar) const {
162 return Vector3f(x * scalar, y * scalar, z * scalar);
163 }
164
165 [[nodiscard]] friend constexpr Vector3f operator*(f32 scalar, const Vector3f &rhs) {
166 return rhs * scalar;
167 }
168
169 constexpr Vector3f &operator*=(f32 scalar) {
170 return *this = *this * scalar;
171 }
172
173 [[nodiscard]] constexpr Vector3f operator/(f32 scalar) const {
174 return Vector3f(x / scalar, y / scalar, z / scalar);
175 }
176
177 constexpr Vector3f &operator/=(f32 scalar) {
178 return *this = *this / scalar;
179 }
180
181 [[nodiscard]] constexpr bool operator==(const Vector3f &rhs) const {
182 return x == rhs.x && y == rhs.y && z == rhs.z;
183 }
184
185 [[nodiscard]] constexpr bool operator!=(const Vector3f &rhs) const {
186 return !(*this == rhs);
187 }
188
190 [[nodiscard]] explicit operator std::string() const {
191 return std::format("[0x{:08X}, 0x{:08X}, 0x{:08X}] | [{}, {}, {}]", f2u(x), f2u(y), f2u(z),
192 x, y, z);
193 }
194
196 [[nodiscard]] constexpr Vector3f cross(const Vector3f &rhs) const {
197 return Vector3f(y * rhs.z - z * rhs.y, z * rhs.x - x * rhs.z, x * rhs.y - y * rhs.x);
198 }
199
201 [[nodiscard]] constexpr f32 squaredLength() const {
202 return x * x + y * y + z * z;
203 }
204
206 [[nodiscard]] constexpr f32 dot(const Vector3f &rhs) const {
207 return x * rhs.x + y * rhs.y + z * rhs.z;
208 }
209
211 [[nodiscard]] constexpr f32 length() const {
212 return Mathf::sqrt(squaredLength());
213 }
214
216 [[nodiscard]] constexpr f32 ps_length() const {
217 f32 dot = Mathf::fma(z, z, x * x + y * y);
218 return dot == 0.0f ? 0.0f : Mathf::sqrt(dot);
219 }
220
223 [[nodiscard]] constexpr Vector3f proj(const Vector3f &rhs) const {
224 return rhs * rhs.dot(*this);
225 }
226
229 [[nodiscard]] constexpr Vector3f rej(const Vector3f &rhs) const {
230 return *this - proj(rhs);
231 }
232
234 [[nodiscard]] constexpr std::pair<Vector3f, Vector3f> projAndRej(const Vector3f &rhs) const {
235 return std::pair(proj(rhs), rej(rhs));
236 }
237
239 [[nodiscard]] constexpr Vector3f abs() const {
240 return Vector3f(Mathf::abs(x), Mathf::abs(y), Mathf::abs(z));
241 }
242
244 [[nodiscard]] constexpr f32 sqDistance(const Vector3f &rhs) const {
245 const EGG::Vector3f diff = *this - rhs;
246 return diff.squaredLength();
247 }
248
251 [[nodiscard]] constexpr EGG::Vector3f multInv(f32 val) const {
252 return *this * (1.0f / val);
253 }
254
256 [[nodiscard]] constexpr f32 ps_dot() const {
257 return ps_dot(*this);
258 }
259
262 [[nodiscard]] constexpr f32 ps_dot(const Vector3f &rhs) const {
263 f32 y_ = y * rhs.y;
264 f32 xy = Mathf::fma(x, rhs.x, y_);
265 return xy + z * rhs.z;
266 }
267
269 [[nodiscard]] constexpr f32 ps_squareMag() const {
270 f32 x_ = x * x;
271 f32 zx = Mathf::fma(z, z, x_);
272 return zx + y * y;
273 }
274
278 constexpr f32 normalise() {
279 f32 len = 0.0f;
280
281 if (squaredLength() > std::numeric_limits<f32>::epsilon()) {
282 len = length();
283 *this *= (1.0f / len);
284 }
285
286 return len;
287 }
288
290 [[nodiscard]] constexpr EGG::Vector3f ps_normalize() const {
291 f32 dot = Mathf::fma(z, z, x * x) + y * y;
292 return *this * EGG::Mathf::frsqrt(dot);
293 }
294
296 [[nodiscard]] constexpr std::pair<f32, EGG::Vector3f> ps_normalized() {
297 f32 mag = ps_length();
298 if (mag <= 0.0f) {
299 return std::make_pair(mag, EGG::Vector3f::zero);
300 }
301
302 return std::make_pair(mag, *this * (1.0f / mag));
303 }
304
306 constexpr void normalise2() {
307 f32 sqLen = squaredLength();
308 if (sqLen > std::numeric_limits<f32>::epsilon()) {
309 *this *= Mathf::frsqrt(sqLen);
310 }
311 }
312
315 [[nodiscard]] constexpr Vector3f maximize(const Vector3f &rhs) const {
316 Vector3f out;
317
318 out.x = x > rhs.x ? x : rhs.x;
319 out.y = y > rhs.y ? y : rhs.y;
320 out.z = z > rhs.z ? z : rhs.z;
321
322 return out;
323 }
324
327 [[nodiscard]] constexpr Vector3f minimize(const Vector3f &rhs) const {
328 Vector3f out;
329
330 out.x = x < rhs.x ? x : rhs.x;
331 out.y = y < rhs.y ? y : rhs.y;
332 out.z = z < rhs.z ? z : rhs.z;
333
334 return out;
335 }
336
339 [[nodiscard]] constexpr f32 ps_sqDistance(const Vector3f &rhs) const {
340 const EGG::Vector3f diff = *this - rhs;
341 return diff.ps_dot();
342 }
343
346 [[nodiscard]] constexpr Vector3f perpInPlane(const EGG::Vector3f &rhs, bool normalise) const {
347 if (Mathf::abs(dot(rhs)) == 1.0f) {
348 return EGG::Vector3f::zero;
349 }
350
351 f32 _x = (rhs.z * x - rhs.x * z) * rhs.z - (rhs.x * y - rhs.y * x) * rhs.y;
352 f32 _y = (rhs.x * y - rhs.y * x) * rhs.x - (rhs.y * z - rhs.z * y) * rhs.z;
353 f32 _z = (rhs.y * z - rhs.z * y) * rhs.y - (rhs.z * x - rhs.x * z) * rhs.x;
354
355 EGG::Vector3f ret(_x, _y, _z);
356
357 if (normalise) {
358 ret.normalise();
359 }
360
361 return ret;
362 }
363
365 void read(Stream &stream) {
366 x = stream.read_f32();
367 y = stream.read_f32();
368 z = stream.read_f32();
369 }
370
371 f32 x;
372 f32 y;
373 f32 z;
374
375 static const Vector3f zero;
376 static const Vector3f unit;
377 static const Vector3f ex, ey, ez;
378 static const Vector3f inf;
379};
380
381inline constexpr Vector3f Vector3f::zero = Vector3f(0.0f, 0.0f, 0.0f);
382inline constexpr Vector3f Vector3f::unit = Vector3f(1.0f, 1.0f, 1.0f);
383inline constexpr Vector3f Vector3f::ex = Vector3f(1.0f, 0.0f, 0.0f);
384inline constexpr Vector3f Vector3f::ey = Vector3f(0.0f, 1.0f, 0.0f);
385inline constexpr Vector3f Vector3f::ez = Vector3f(0.0f, 0.0f, 1.0f);
386
388inline constexpr Vector3f Vector3f::inf = Vector3f(std::numeric_limits<f32>::infinity(),
389 std::numeric_limits<f32>::infinity(), std::numeric_limits<f32>::infinity());
390
391} // namespace Kinoko::EGG
A stream of data, abstracted to allow for continuous seeking.
Definition Stream.hh:10
static constexpr f32 frsqrt(f32 x)
Definition Math.hh:716
static constexpr f32 fma(f32 x, f32 y, f32 z)
Fused multiply-add operation.
Definition Math.hh:33
EGG core library.
Definition Archive.cc:6
A 2D float vector.
Definition Vector.hh:12
void read(Stream &stream)
Initializes a Vector2f by reading 8 bytes from the stream.
Definition Vector.hh:90
A 3D float vector.
Definition Vector.hh:107
constexpr Vector3f rej(const Vector3f &rhs) const
The rejection of this vector onto rhs.
Definition Vector.hh:229
constexpr f32 normalise()
Normalizes the vector and returns the original length.
Definition Vector.hh:278
constexpr f32 squaredLength() const
The dot product between the vector and itself.
Definition Vector.hh:201
constexpr f32 ps_dot(const Vector3f &rhs) const
Paired-singles dot product implementation.
Definition Vector.hh:262
constexpr Vector3f abs() const
Returns the absolute value of each element of the vector.
Definition Vector.hh:239
constexpr f32 ps_sqDistance(const Vector3f &rhs) const
Paired-singles impl. of sqDistance.
Definition Vector.hh:339
void read(Stream &stream)
Initializes a Vector3f by reading 12 bytes from the stream.
Definition Vector.hh:365
constexpr Vector3f minimize(const Vector3f &rhs) const
Returns a vector whose elements are the min of the elements of both vectors.
Definition Vector.hh:327
constexpr f32 ps_dot() const
Paired-singles dot product implementation.
Definition Vector.hh:256
constexpr Vector3f maximize(const Vector3f &rhs) const
Returns a vector whose elements are the max of the elements of both vectors.
Definition Vector.hh:315
constexpr f32 length() const
The square root of the vector's dot product.
Definition Vector.hh:211
constexpr Vector3f proj(const Vector3f &rhs) const
The projection of this vector onto rhs.
Definition Vector.hh:223
constexpr f32 dot(const Vector3f &rhs) const
The dot product between two vectors.
Definition Vector.hh:206
constexpr f32 sqDistance(const Vector3f &rhs) const
The square of the distance between two vectors.
Definition Vector.hh:244
constexpr EGG::Vector3f multInv(f32 val) const
Multiplies a vector by the inverse of val.
Definition Vector.hh:251
constexpr f32 ps_squareMag() const
Differs from ps_dot due to variation in which operands are fused.
Definition Vector.hh:269
constexpr Vector3f perpInPlane(const EGG::Vector3f &rhs, bool normalise) const
Calculates the orthogonal vector, based on the plane defined by this vector and rhs.
Definition Vector.hh:346