Jagguar Game Engine

Loading...
Searching...
No Matches
TinyMath.hpp
1#ifndef TINYMATH_HPP
2#define TINYMATH_HPP
3
4#include <cmath>
5#include <ostream>
6
7// Forward references of each of the structs
8 struct Vec2D;
9 struct Matrix3D;
10
11// Vec2D performs vector operations with 3-dimensions
12// The purpose of this class is primarily for 3D graphics
13// applications.
14 struct Vec2D {
15
16 // I'm wrapping all of our member variables in a union.
17 // So long as you make sure the byte-size is equivalent, this
18 // allows you to access the data in whatever form is most convenient.
19 // Meaning I can access Vec2D[0] or equivalently Vec2D.x .
20 // I can also pass Vec2D internal array or just individual values if needed conveniently.
21 union {
22 struct {
23 // Note: x,y are a convention
24 // x,y could be position, but also any 2-component value.
25 float x;
26 float y;
27 float w; // 'w' is a third hidden component that could be used
28 // to determine if this is being used as a vector or a point
29 // If w=0 then a vector, if w=1 then a point
30 // DO not use 'w' for any computation however.
31 };
32 float data[3]; // for convenience if you want to access as 'data' or pass Vec2D as an array
33 };
34
35 // Default conostrutcor
36 // 'why default?' https://stackoverflow.com/questions/20828907/the-new-keyword-default-in-c11
37 // Vec2D() = default;
38
39 // The "Real" constructor we want to use.
40 // This initializes the values x,y, and the 'w' value
41 Vec2D(float _x = 0, float _y = 0, float _w = 0) {
42 // TODO:
43 x = _x;
44 y = _y;
45 w = _w;
46 }
47
48 // Index operator, allowing us to access the individual
49 // x,y components of our vector.
50 float &operator[](int i) {
51 // NOTE: Think about why this works.
52 // There is no code to change here.
53 return ((&x)[i]);
54 }
55
56 // Index operator, allowing us to access the individual
57 // x,y components of our vector.
58 const float &operator[](int i) const {
59 // NOTE: Think about why this works.
60 // There is no code to change here.
61 return ((&x)[i]);
62 }
63
64 // General Note
65 // You'll observer that some of the operator overloads appear in this class
66 // as member functions versus some that are free functions.
67 // In general, if you need access to private member variables or the 'this' pointer
68 // then you must use a member function. Otherwise, I recommend to 'free your functions'
69 // and not make them part of the class for maximum use.
70 //
71 // Multiplication Operator
72 // Multiply vector by a uniform-scalar.
73 Vec2D &operator*=(float s) {
74 // TODO:
75 x *= s;
76 y *= s;
77
78 return (*this);
79 }
80
81 // Division Operator
82 Vec2D &operator/=(float s) {
83 // TODO:
84 x /= s;
85 y /= s;
86
87 return (*this);
88 }
89
90 // Addition operator
91 Vec2D &operator+=(const Vec2D &v) {
92 // TODO:
93 x += v.x;
94 y += v.y;
95
96 return (*this);
97 }
98
99 // Subtraction operator
100 Vec2D &operator-=(const Vec2D &v) {
101 // TODO:
102 x -= v.x;
103 y -= v.y;
104
105 return (*this);
106 }
107};
108
109// Compute the dot product of a Vec2D
110 inline float Dot(const Vec2D &a, const Vec2D &b) {
111 // TODO:
112 return a.x * b.x + a.y * b.y + a.w * b.w;
113}
114
115/*
116// Test for equality
117// NOTE: Comparing floats is somewhat tricky, meaning that
118// you will want to take the fabs(lhs.x - lhs.y) < 0.00001
119// of each component to see if they are 'close enough'
120 bool operator==(Vec2D &lhs, Vec2D &rhs)
121{
122 bool result = true;
123 // TODO
124 if (fabs(lhs.x - rhs.x) > 0.00001 || fabs(lhs.y - rhs.y) > 0.00001 || fabs(lhs.w - rhs.w) > 0.00001)
125 {
126 result = false;
127 }
128 return result;
129}
130*/
131
132// Multiplication of a vector by a scalar values
133 inline Vec2D operator*(const Vec2D &v, float s) {
134 // TODO:
135 Vec2D vec;
136
137 vec.x = v.x * s;
138 vec.y = v.y * s;
139 vec.w = v.w;
140
141 return vec;
142}
143
144 inline Vec2D operator*(float s, const Vec2D &v) {
145 // TODO:
146 Vec2D vec;
147
148 vec.x = v.x * s;
149 vec.y = v.y * s;
150 vec.w = v.w;
151
152 return vec;
153}
154
155// Division of a vector by a scalar value.
156 inline Vec2D operator/(const Vec2D &v, float s) {
157 // TODO:
158 Vec2D vec;
159
160 vec.x = v.x / s;
161 vec.y = v.y / s;
162 vec.w = v.w;
163
164 return vec;
165}
166
167// Negation of a vector
168// Use Case: Sometimes it is handy to apply a force in an opposite direction
169 inline Vec2D operator-(const Vec2D &v) {
170 // TODO:
171 Vec2D vec;
172
173 vec.x = v.x * -1.0f;
174 vec.y = v.y * -1.0f;
175 vec.w = v.w;
176
177 return vec;
178}
179
180// Return the magnitude of a vector
181 inline float Magnitude(const Vec2D &v) {
182 // TODO:
183 return sqrt(v.x * v.x + v.y * v.y);
184}
185
186// Add two vectors together
187 inline Vec2D operator+(const Vec2D &a, const Vec2D &b) {
188 // TODO:
189 Vec2D vec;
190
191 vec.x = a.x + b.x;
192 vec.y = a.y + b.y;
193 //?
194 vec.w = a.w;
195
196 return vec;
197}
198
199// Subtract two vectors
200 inline Vec2D operator-(const Vec2D &a, const Vec2D &b) {
201 // TODO:
202 Vec2D vec;
203
204 vec.x = a.x - b.x;
205 vec.y = a.y - b.y;
206 //?
207 vec.w = a.w;
208
209 return vec;
210}
211
212// Vector Projection
213 inline Vec2D Project(const Vec2D &a, const Vec2D &b) {
214 // TODO:
215 Vec2D vec;
216
217 return b * (float) (Dot(a, b) / (float) pow(Magnitude(b), 2));
218}
219
220// Set a vectors magnitude to 1
221// Note: This is NOT generating a normal vector
222 inline Vec2D Normalize(const Vec2D &v) {
223 // TODO:
224 Vec2D vec;
225
226 float mag = Magnitude(v);
227 vec.x = v.x / mag;
228 vec.y = v.y / mag;
229 vec.w = v.w;
230
231 return vec;
232}
233
234// a x b (read: 'a crossed b')
235// With a 3D vector we would yield another perpendicular cross product
236// For 2D cross product, this will yield a scalar.
237// You should write this to yield a scalar value.
238 inline float CrossProduct(const Vec2D &a, const Vec2D &b) {
239 // TODO:
240 float result;
241
242 result = a.x * b.y - b.x * a.y;
243
244 return result;
245}
246
247// Pretty print a vector
248// std::ostream& could be 'std::cout' for example'
249// This function is primarily used for debugging purposes
250 inline void PrettyPrint(std::ostream &os, const Vec2D &a) {
251 os << "x : " << a.x << std::endl;
252 os << "y : " << a.y << std::endl;
253 os << "(w): " << a.w << std::endl;
254}
255
256// Matrix 3D represents 3x3 matrices in Math
257 struct Matrix3D {
258 private:
259 float n[3][3]; // Store each value of the matrix
260
261 public:
262 // Initializes to a identity matrix by default
263 Matrix3D() {
264 n[0][0] = 1;
265 n[0][1] = 0;
266 n[0][2] = 0;
267 n[1][0] = 0;
268 n[1][1] = 1;
269 n[1][2] = 0;
270 n[2][0] = 0;
271 n[2][1] = 0;
272 n[2][2] = 1;
273 }
274
275 // TODO: Row or column major order you decide!
276 // Matrix constructor with 9 scalar values.
277 Matrix3D(float n00, float n01, float n02,
278 float n10, float n11, float n12,
279 float n20, float n21, float n22) {
280
281 n[0][0] = n00;
282 n[0][1] = n01;
283 n[0][2] = n02;
284 n[1][0] = n10;
285 n[1][1] = n11;
286 n[1][2] = n12;
287 n[2][0] = n20;
288 n[2][1] = n21;
289 n[2][2] = n22;
290 }
291
292 // Matrix constructor from three vectors.
293 Matrix3D(const Vec2D &a, const Vec2D &b, const Vec2D &c) {
294 n[0][0] = a.x;
295 n[0][1] = a.y;
296 n[0][2] = a.w;
297 n[1][0] = b.x;
298 n[1][1] = b.y;
299 n[1][2] = b.w;
300 n[2][0] = c.x;
301 n[2][1] = c.y;
302 n[2][2] = c.w;
303 }
304
305 // Index operator with two dimensions
306 // Example: M(1,1) returns row 1 and column 1 of matrix M.
307 float &operator()(int i, int j) {
308 return (n[i][j]);
309 }
310
311 // Index operator with two dimensions
312 // Example: M(1,1) returns row 1 and column 1 of matrix M.
313 const float &operator()(int i, int j) const {
314 return (n[i][j]);
315 }
316
317 // Return a row from a matrix as a vector.
318 Vec2D &operator[](int j) {
319 return (*reinterpret_cast<Vec2D *>(n[j]));
320 }
321
322 // Return a row from a matrix as a vector.
323 const Vec2D &operator[](int j) const {
324 return (*reinterpret_cast<const Vec2D *>(n[j]));
325 }
326};
327
328/*
329// Matrix Multiplication
330 Matrix3D operator*(const Matrix3D &A, const Matrix3D &B)
331{
332 // TODO:
333 Matrix3D result;
334
335 float a = A(0, 0);
336 float b = A(0, 1);
337 float c = A(0, 2);
338 float d = A(1, 0);
339 float e = A(1, 1);
340 float f = A(1, 2);
341 float g = A(2, 0);
342 float h = A(2, 1);
343 float i = A(2, 2);
344
345 float j = B(0, 0);
346 float k = B(0, 1);
347 float l = B(0, 2);
348 float m = B(1, 0);
349 float n = B(1, 1);
350 float o = B(1, 2);
351 float p = B(2, 0);
352 float q = B(2, 1);
353 float r = B(2, 2);
354
355 result = Matrix3D(
356 a * j + b * m + c * p, a * k + b * n + c * q, a * l + b * o + c * r,
357 d * j + e * m + f * p, d * k + e * n + f * q, d * l + e * o + f * r,
358 g * j + h * m + i * p, g * k + h * n + i * q, g * l + h * o + i * r);
359
360 return result;
361}
362
363// Matrix multiply by a vector
364 Vec2D operator*(const Matrix3D &M, const Vec2D &v)
365{
366 // TODO:
367 float a = M(0, 0);
368 float b = M(0, 1);
369 float c = M(0, 2);
370 float d = M(1, 0);
371 float e = M(1, 1);
372 float f = M(1, 2);
373 float g = M(2, 0);
374 float h = M(2, 1);
375 float i = M(2, 2);
376
377 float j = v.x;
378 float k = v.y;
379 float l = v.w;
380
381 Vec2D vec = Vec2D(
382 a * j + b * k + c * l,
383 d * j + e * k + f * l,
384 g * j + h * k + i * l);
385
386 return vec;
387}
388
389// Pretty print a matrix
390 void PrettyPrintMatrix(std::ostream &os, const Matrix3D &a)
391{
392 for (int i = 0; i < 3; ++i)
393 {
394 for (int j = 0; j < 3; ++j)
395 {
396 os << i << ", " << j << ": " << a(i, j) << std::endl;
397 }
398 }
399}
400*/
401#endif
Matrix3D
Definition: TinyMath.hpp:257
Vec2D
Definition: TinyMath.hpp:14