NWengine 0.9
Loading...
Searching...
No Matches
Maths.h
1#pragma once
2#include <cmath>
3#include <cstdint>
4
5#pragma warning(disable: 4244)
6
7#define PI 3.14159265359
8#define ONEDIV180 0.00555555555
9
10inline float DegToRad(float degree) {
11 return degree * PI * ONEDIV180;
12}
13
14inline float RadToDeg(float rad) {
15 return 180.0 * rad / PI;
16}
17
18
19
20template<typename T>
21class Vector2 {
22public:
23 struct {
24 T x;
25 T y;
26 };
27 Vector2(T x = 0.0f, T y = 0.0f);
28
29 Vector2<float> normalize();
30 float magnitude();
31 T Dot(Vector2 const& vec1);
32 Vector2 Project(Vector2 const& vec1);
33 Vector2 Rotate(float const& angle); //In degree
34
35 Vector2 operator + (Vector2 const& vec1);
36 Vector2 operator + (T const& num);
37 Vector2 operator - (Vector2 const& vec1);
38 Vector2 operator - (T const& num);
39 template<typename T1>
40 Vector2 operator * (T1 const& num);
41 Vector2 operator * (Vector2 const& vec1);
42 bool operator == (Vector2 const& vec1);
43 bool operator != (Vector2 const& vec1);
44
45 operator Vector2<int>() const { return Vector2<int>(x,y); }
46 operator Vector2<float>() const { return Vector2<float>(x, y); }
47
48 T* operator [] (int index);
49};
50
51
52template<typename T>
54 float magnitude = pow(x * x + y * y, 0.5);
55 if (magnitude == 0) {
56 return Vector2<float>(0, 0);
57 }
58 return Vector2<float>(x / magnitude, y / magnitude);
59}
60template<typename T>
62 return pow(x * x + y * y, 0.5);
63}
64
65template<typename T>
66T Vector2<T>::Dot(Vector2 const& vec1) {
67 return x * vec1.x + y * vec1.y;
68};
69
70template<typename T>
71//Vec1 should be normalized
73 return Dot(vec1) * vec1;
74}
75
76template<typename T>
77Vector2<T> Vector2<T>::Rotate(float const& angle) {
78 float angle0 = DegToRad(angle);
79 return Vector2<T>(cos(angle0) * x - sin(angle0) * y,
80 sin(angle0) * x + cos(angle0) * y);
81}
82template<typename T>
84 Vector2::x = x;
85 Vector2::y = y;
86}
87template<typename T>
90 sum.x = x + vec1.x;
91 sum.y = y + vec1.y;
92 return sum;
93}
94template<typename T>
97 sub.x = x - vec1.x;
98 sub.y = y - vec1.y;
99 return sub;
100}
101
102template<class T>
105 newVec.x = x * vec1.x;
106 newVec.y = y * vec1.y;
107 return newVec;
108}
109template<typename T>
112 newVec.x = x + num;
113 newVec.y = y + num;
114 return newVec;
115}
116template<typename T>
119 newVec.x = x - num;
120 newVec.y = y - num;
121 return newVec;
122}
123
124template<typename T>
125template<typename T1>
128 newVec.x = x * num;
129 newVec.y = y * num;
130 return newVec;
131}
132
133template<typename T>
135 return (x == vec1.x) && (y == vec1.y);
136}
137
138template<typename T>
140 return (x != vec1.x) && (y != vec1.y);
141}
142
143template<typename T>
144T* Vector2<T>::operator [] (int index) {
145 return index == 0 ? &x : &y;
146}
147
148
149
150template<typename T>
151int Sign(T number) {
152 if (number < 0) return -1;
153 return 1;
154}
155
156template<typename T>
157T Min(T x, T y) {
158 return x <= y ? x : y;
159};
160
161template<typename T>
162T Max(T x, T y) {
163 return x >= y ? x : y;
164};
165
166template<typename T>
167T Clamp(T num, T min, T max) {
168 if (num < min) return min;
169 else if (num > max) return max;
170 return num;
171}
172
173template<typename T>
174class Vector3 {
175public:
176 union {
177 struct {
178 T x;
179 T y;
180 T z;
181 };
182
183 struct {
184 T r;
185 T g;
186 T b;
187 };
188 };
189 Vector3(T x = 0.0f, T y = 0.0f, T z = 0.0f);
190
191 Vector3<float> normalize() const;
192 float magnitude();
193 T Dot(Vector3 const& vec1);
194
195 Vector3 Project(Vector3 const& vec1);
196
198 Vector3 operator + (T const& num);
199 Vector3 operator * (T const& num);
201 bool operator == (Vector3 const& vec1);
202 bool operator != (Vector3 const& vec1);
203};
204
205template<typename T>
207 float magnitude = pow(x * x + y * y + z * z, 0.5);
208 return Vector3<float>(x / magnitude, y / magnitude, z / magnitude);
209}
210template<typename T>
211float Vector3<T>::magnitude() {
212 return pow(x * x + y * y + z * z,0.5);
213}
214template<typename T>
216 return x * vec1.x + y * vec1.y + z * vec1.z;
217};
218
219template<typename T>
220//Vec1 should be normalized
222 return vec1; //TODO::
223}
224
225template<class T>
226Vector3<T>::Vector3(T x, T y, T z) {
227 Vector3::x = x;
228 Vector3::y = y;
229 Vector3::z = z;
230}
231template<typename T>
233 Vector3 sum;
234 sum.x = x + vec1.x;
235 sum.y = y + vec1.y;
236 sum.z = z + vec1.z;
237 return sum;
238}
239template<typename T>
242 newVec.x = x * vec1.x;
243 newVec.y = y * vec1.y;
244 newVec.z = z * vec1.z;
245 return newVec;
246}
247template<typename T>
250 newVec.x = x + num;
251 newVec.y = y + num;
252 newVec.z = z + num;
253 return newVec;
254}
255
256template<typename T>
259 newVec.x = x * num;
260 newVec.y = y * num;
261 newVec.z = z * num;
262 return newVec;
263}
264template<typename T>
266 return (x == vec1.x) && (y == vec1.y) && (z == vec1.z);
267}
268
269template<typename T>
271 return (x != vec1.x) && (y != vec1.y) && (z != vec1.z);
272}
273
274template<typename T>
275class Vector4 { //TODO::Complete this class
276public:
277 union {
278 struct {
279 T x;
280 T y;
281 T z;
282 T w;
283 };
284
285 struct {
286 T r;
287 T g;
288 T b;
289 T a;
290 };
291 };
292 Vector4(T x = 0.0f, T y = 0.0f, T z = 0.0f, T w = 0.0f);
293
294};
295
296template<typename T>
297Vector4<T>::Vector4(T x, T y, T z, T w) {
298 this->x = x;
299 this->y = y;
300 this->z = z;
301 this->w = w;
302}
303
304
305template<uint8_t n, uint8_t m, typename T>
306class Matrix {
307public:
308 Vector2<int> dimension;
309 T coeff[n*m];
310 Matrix(T* data);
311 Matrix operator + (T const& num);
312 Matrix operator * (T const& num);
314 void operator += (T const& num);
315 void operator *= (T const& num);
316 void operator += (Matrix* const& matrix);
317 template<uint8_t b>
319 //void operator *= (Matrix<m, b, T>* const& matrix); Can you do it without creating another matrix??
320
321};
322
323template<uint8_t n, uint8_t m, typename T>
325 dimension.x = n;
326 dimension.y = m;
327 int size = sizeof(T) * n * m;
328 if (data!=nullptr) memcpy(coeff, data, size);
329 else {
330 for (int i = 0; i < n * m; i++) {
331 coeff[i] = (T)0;
332 };
333 }
334
335};
336
337template<uint8_t n, uint8_t m, typename T>
340 for (uint8_t i = 0; i < n * m; i++) {
341 result.coeff[i] += num;
342 };
343 return result;
344}
345
346template<uint8_t n, uint8_t m, typename T>
348 for (uint8_t i = 0; i < n * m; i++) {
349 coeff[i] += num;
350 };
351}
352
353template<uint8_t n, uint8_t m, typename T>
356 for (uint8_t i = 0; i < n * m; i++) {
357 result.coeff[i] *= num;
358 };
359 return result;
360}
361
362template<uint8_t n, uint8_t m, typename T>
364 for (uint8_t i = 0; i < n * m; i++) {
365 coeff[i] *= num;
366 };
367}
368
369template<uint8_t n, uint8_t m, typename T>
372 for (uint8_t i = 0; i < n * m; i++) {
373 result.coeff[i] += coeff[i] + matrix->coeff[i];
374 }
375 return result;
376}
377
378template<uint8_t n, uint8_t m, typename T>
380 for (uint8_t i = 0; i < n * m; i++) {
381 coeff[i] += matrix->coeff[i];
382 }
383}
384
385template<uint8_t n, uint8_t m, typename T>
386template<uint8_t b>
389 for (uint8_t i = 0; i < n; i++) {
390 for (uint8_t j = 0; j < b; j++) {
391 T sum = 0;
392 for (uint8_t cur = 0; cur < m; cur++) {
393 sum += coeff[m * i + cur] * matrix->coeff[j + cur*b];
394 };
395 result.coeff[i * b + j] = sum;
396 };
397 }
398 return result;
399}
400
401
402enum class MATFLAG {
403 NOINIT,
404};
405
406template<typename T>
407class Matrix2 {
408 T values[4]; //Column major
409 Matrix2();
410 Matrix2(T diag);
411 Matrix2(MATFLAG flag);
413 void operator *=(const Matrix2& other);
414 T operator ()(int i, int j); //Row major access
415};
416template<typename T>
418 values[0] = diag; values[1] = 0;
419 values[2] = 0 ; values[3] = diag:
420}
421template<typename T>
422Matrix2<T>::Matrix2<T>() : Matrix2<T>((T)1.0) {};
423
424template<typename T>
426
427template<typename T>
429 Matrix2<T> result = Matrix2(MATFLAG::NOINIT);
430 result.values[0] = this->values[0] * other.values[0] + this->values[1] * other.values[2];
431 result.values[1] = this->values[0] * other.values[1] + this->values[1] * other.values[3];
432 result.values[2] = this->values[2] * other.values[0] + this->values[3] * other.values[2];
433 result.values[3] = this->values[2] * other.values[1] + this->values[3] * other.values[3];
434 return result;
435}
436
437template<typename T>
439 Matrix2<T> result = Matrix2(MATFLAG::NOINIT);
440 result.values[0] = other.values[0] * values[0] + other.values[1] * values[2];
441 result.values[1] = other.values[0] * values[1] + other.values[1] * values[3];
442 result.values[2] = other.values[2] * values[0] + other.values[3] * values[2];
443 result.values[3] = other.values[2] * values[1] + other.values[3] * values[3];
444 this->values = memcpy(this->values, result.values, 4 * sizeof(T))
445}
446
447template<typename T>
448T Matrix2<T>::operator()(int i, int j) {
449 return j * 2 + i;
450}
451
452template<typename T>
453class Matrix3 {
454 T values[9]; //Column major
455 Matrix3();
456 Matrix3(T diag);
457 Matrix3(MATFLAG flag);
459 void operator *=(const Matrix3& other);
460 T operator ()(int i, int j);
461};
462
463template<typename T>
465 values[0] = diag; values[1] = 0 ; values[2] = 0;
466 values[3] = 0 ; values[4] = diag; values[5] = 0;
467 values[6] = 0 ; values[7] = 0 ; values[8] = diag;
468}
469
470template<typename T>
471Matrix3<T>::Matrix3<T>() : Matrix2<T>((T)1.0) {};
472
473template<typename T>
475
476template<typename T>
478 Matrix3<T> result = Matrix3(MATFLAG::NOINIT);
479 result.values[0] = other.values[0] * values[0] + other.values[1] * values[3] + other.values[2] * values[6];
480 result.values[1] = other.values[0] * values[1] + other.values[1] * values[4] + other.values[2] * values[7];
481 result.values[2] = other.values[0] * values[2] + other.values[1] * values[5] + other.values[2] * values[8];
482 result.values[3] = other.values[3] * values[0] + other.values[4] * values[3] + other.values[5] * values[6];
483 result.values[4] = other.values[3] * values[1] + other.values[4] * values[4] + other.values[5] * values[7];
484 result.values[5] = other.values[3] * values[2] + other.values[4] * values[5] + other.values[5] * values[8];
485 result.values[6] = other.values[6] * values[0] + other.values[7] * values[3] + other.values[8] * values[6];
486 result.values[7] = other.values[6] * values[1] + other.values[7] * values[4] + other.values[8] * values[7];
487 result.values[8] = other.values[6] * values[2] + other.values[7] * values[5] + other.values[8] * values[8];
488 return result;
489}
490
491template<typename T>
493 Matrix3<T> result = Matrix3<T>(MATFLAG::NOINIT);
494 result.values[0] = other.values[0] * values[0] + other.values[1] * values[3] + other.values[2] * values[6];
495 result.values[1] = other.values[0] * values[1] + other.values[1] * values[4] + other.values[2] * values[7];
496 result.values[2] = other.values[0] * values[2] + other.values[1] * values[5] + other.values[2] * values[8];
497 result.values[3] = other.values[3] * values[0] + other.values[4] * values[3] + other.values[5] * values[6];
498 result.values[4] = other.values[3] * values[1] + other.values[4] * values[4] + other.values[5] * values[7];
499 result.values[5] = other.values[3] * values[2] + other.values[4] * values[5] + other.values[5] * values[8];
500 result.values[6] = other.values[6] * values[0] + other.values[7] * values[3] + other.values[8] * values[6];
501 result.values[7] = other.values[6] * values[1] + other.values[7] * values[4] + other.values[8] * values[7];
502 result.values[8] = other.values[6] * values[2] + other.values[7] * values[5] + other.values[8] * values[8];
503 this->values = memcpy(this->values, result.values, 4 * sizeof(T))
504}
505
506template<typename T>
507T Matrix3<T>::operator()(int i, int j) {
508 return j * 3 + i;
509}
510
511//4x4--------------------------
512template<typename T>
513class Matrix4 {
514public:
515 T values[16]; //Column major
516 Matrix4();
517 Matrix4(T diag);
518 Matrix4(MATFLAG flag);
521 void operator *=(const Matrix4& other);
522 T operator ()(int i, int j); //Row major access
523};
524
525template<typename T>
527 values[0] = diag; values[1] = 0; values[2] = 0; values[3] = 0;
528 values[4] = 0; values[5] = diag; values[6] = 0; values[7] = 0;
529 values[8] = 0; values[9] = 0; values[10] = diag; values[11] = 0;
530 values[12] = 0; values[13] = 0; values[14] = 0; values[15] = diag;
531}
532template<typename T>
533Matrix4<T>::Matrix4<T>() : Matrix4<T>((T)1.0) {};
534
535template<typename T>
537
538template<typename T>
540 Matrix4<T> result = Matrix4(MATFLAG::NOINIT);
541#define TMP_MAT_4x4_MUL \
542 result.values[0] = other.values[0] * values[0] + other.values[1] * values[4] + other.values[2] * values[8] + other.values[3] * values[12]; \
543 result.values[1] = other.values[0] * values[1] + other.values[1] * values[5] + other.values[2] * values[9] + other.values[3] * values[13]; \
544 result.values[2] = other.values[0] * values[2] + other.values[1] * values[6] + other.values[2] * values[10] + other.values[3] * values[14]; \
545 result.values[3] = other.values[0] * values[3] + other.values[1] * values[7] + other.values[2] * values[11] + other.values[3] * values[15]; \
546 result.values[4] = other.values[4] * values[0] + other.values[5] * values[4] + other.values[6] * values[8] + other.values[7] * values[12]; \
547 result.values[5] = other.values[4] * values[1] + other.values[5] * values[5] + other.values[6] * values[9] + other.values[7] * values[13]; \
548 result.values[6] = other.values[4] * values[2] + other.values[5] * values[6] + other.values[6] * values[10] + other.values[7] * values[14]; \
549 result.values[7] = other.values[4] * values[3] + other.values[5] * values[7] + other.values[6] * values[11] + other.values[7] * values[15]; \
550 result.values[8] = other.values[8] * values[0] + other.values[9] * values[4] + other.values[10] * values[8] + other.values[11] * values[12]; \
551 result.values[9] = other.values[8] * values[1] + other.values[9] * values[5] + other.values[10] * values[9] + other.values[11] * values[13]; \
552 result.values[10] = other.values[8] * values[2] + other.values[9] * values[6] + other.values[10] * values[10] + other.values[11] * values[14]; \
553 result.values[11] = other.values[8] * values[3] + other.values[9] * values[7] + other.values[10] * values[11] + other.values[11] * values[15]; \
554 result.values[12] = other.values[12] * values[0] + other.values[13] * values[4] + other.values[14] * values[8] + other.values[15] * values[12]; \
555 result.values[13] = other.values[12] * values[1] + other.values[13] * values[5] + other.values[14] * values[9] + other.values[15] * values[13]; \
556 result.values[14] = other.values[12] * values[2] + other.values[13] * values[6] + other.values[14] * values[10] + other.values[15] * values[14]; \
557 result.values[15] = other.values[12] * values[3] + other.values[13] * values[7] + other.values[14] * values[11] + other.values[15] * values[15];
558
559 TMP_MAT_4x4_MUL
560 return result;
561}
562
563template<typename T>
565 Matrix4<T> result = Matrix4(MATFLAG::NOINIT);
566 TMP_MAT_4x4_MUL
567 this->values = memcpy(this->values, result.values, 4 * sizeof(T))
568}
569#undef TMP_MAT_4x4_MUL
570
571template<typename T>
574 result.x = values[0] * other.x + values[4] * other.y + values[8] * other.z + values[12] * other.w;
575 result.y = values[1] * other.x + values[5] * other.y + values[9] * other.z + values[13] * other.w;
576 result.z = values[2] * other.x + values[6] * other.y + values[10] * other.z + values[14] * other.w;
577 result.w = values[3] * other.x + values[7] * other.y + values[11] * other.z + values[15] * other.w;
578 return result;
579}
580
581
582
583template<typename T>
584T Matrix4<T>::operator()(int i, int j) {
585 return j * 4 + i;
586}
587
588//Matrix passed as reference to this function should be identity matrix; otherwise, behaviour is undefined
589inline void OrthorgraphicMat(Matrix4<float>& matrix, float left, float right, float buttom, float top, float near = 1.0f, float far = -1.0f) {
590 float rml = 1.0f / (right - left);
591 float tmb = 1.0f / (top - buttom);
592 float fmn = 1.0f / (far - near);
593 matrix.values[0] = 2.0f * rml;
594 matrix.values[5] = 2.0f * tmb;
595 matrix.values[10] = -2.0f * fmn;
596
597 matrix.values[12] = (-right - left) * rml;
598 matrix.values[13] = (- top - buttom)* tmb;
599 matrix.values[14] = (- far - near) * fmn;
600}
601
602template<typename T>
603void TranslateMat(Matrix4<T>&matrix, const Vector3<T>& coeff) {
604 matrix.values[12] += coeff.x;
605 matrix.values[13] += coeff.y;
606 matrix.values[14] += coeff.z;
607}
608
609template<typename T>
610void ScaleMat(Matrix4<T>& matrix, const Vector3<T>& coeff) {
611 matrix.values[0] *= coeff.x ;
612 matrix.values[5] *= coeff.y;
613 matrix.values[10] *= coeff.z;
614}
615
616//TODO::Optimize this and do it in palce
617template<typename T>
618void RotateMat(Matrix4<T>& matrix, float degAngle, const Vector3<T>& axis) {
619 Matrix4<T> newMat(MATFLAG::NOINIT);
620 degAngle = DegToRad(degAngle);
621 float c = cos(degAngle);
622 float cmpC = 1.0f - c; // NAME: Complementary of cos
623 float s = sin(degAngle);
624
625 Vector3<float> n = axis.normalize();
626
627 newMat.values[0] = c + n.x * n.x * cmpC;
628 newMat.values[1] = cmpC * n.x * n.y + n.z * s;
629 newMat.values[2] = cmpC * n.z * n.x - n.y * s;
630 newMat.values[3] = 0;
631
632 newMat.values[4] = cmpC * n.x * n.y - n.z * s;
633 newMat.values[5] = c + n.y * n.y * cmpC;
634 newMat.values[6] = n.y * n.z * cmpC + n.x * s;
635 newMat.values[7] = 0;
636
637 newMat.values[8] = n.x * n.z * cmpC + n.y * s;
638 newMat.values[9] = n.y * n.z * cmpC - n.x * s;
639 newMat.values[10] = c + n.z * n.z * cmpC;
640 newMat.values[11] = 0;
641
642 newMat.values[12] = 0;
643 newMat.values[13] = 0;
644 newMat.values[14] = 0;
645 newMat.values[15] = 1;
646
647 matrix = newMat * matrix;
648}
649
650
651//Functions---------------------------------------
652
653template<typename T, typename T1>
654T lerp(T source, T target, T1 percent) {
655 percent = Clamp<T1>(percent, (T1)0.0, (T1)1.0);
656 return source + (target - source) * percent;
657}
658
659template<typename T, typename T1>
660Vector2<T> lerpVector2(Vector2<T> source, Vector2<T> target, Vector2<T1> percent) {
661 return Vector2<T>(lerp(source.x, target.x, percent.x), lerp(source.y, target.y, percent.y));
662};
663
664template<typename T, typename T1>
665Vector3<T> lerpVector3(Vector3<T> source, Vector3<T> target, Vector3<T1> percent) {
666 return Vector3<T>(lerp(source.x, target.x, percent.x), lerp(source.y, target.y, percent.y),
667 lerp(source.z, target.z, percent.z));
668};
669//Quadratic Bezier
670template<typename T, typename T1>
671T Qbezier(T source, T target, T point, T1 percent) {
672 percent = Clamp<T1>(percent, (T1)0.0, (T1)1.0);
673 T1 t2 = percent * percent;
674 T1 x = 1 - percent;
675 T1 x2 = x * x;
676
677 return x2 * source + 2 * x * percent * point + t2 * target;
678}
679
680template<typename T, typename T1>
681Vector2<T> QbezierVector2(Vector2<T> source, Vector2<T> target, Vector2<T> point, Vector2<T1> percent) {
682 return Vector2<T>(Qbezier(source.x, target.x, point.x, percent.x),
683 Qbezier(source.y, target.y, point.y, percent.y));
684 //DevNote: Should maybe rewrite code for each so it's optimized, look at how many time calculation is redone
685}
686
687template<typename T, typename T1>
688Vector3<T> QbezierVector3(Vector3<T> source, Vector3<T> target, Vector3<T> point, Vector3<T1> percent) {
689 return Vector3<T>(Qbezier(source.x, target.x, point.x, percent.x),
690 Qbezier(source.y, target.y, point.y, percent.y),
691 Qbezier(source.z, target.z, point.z, percent.z));
692}
693
694//Cubic bezier
695template<typename T, typename T1>
696T Cbezier(T source, T target, T point1, T point2, T1 percent) {
697 percent = Clamp<T1>(percent, (T1)0.0, (T1)1.0);
698 T1 t2 = percent * percent;
699 T1 t3 = percent * t2; //t3
700 T1 x = 1 - percent;
701 T1 x2 = x * x; //(1-t)^2
702 T1 x3 = x2 * x; //(1-t)^3
703
704 return x3 * source + 3 * percent * x2 * point1 + 3 * t2 * x * point2 + t3 * target;
705}
706
707template<typename T, typename T1>
709 return Vector2<T>(Cbezier(source.x, target.x, point1.x, point2.x, percent.x),
710 Cbezier(source.y, target.y, point1.y, point2.y, percent.y));
711 //DevNote: Should maybe rewrite code for each so it's optimized, look at how many time calculation is redone
712}
713
714template<typename T, typename T1>
716 return Vector3<T>(Cbezier(source.x, target.x, point1.x, point2.x, percent.x),
717 Cbezier(source.y, target.y, point1.y, point2.y, percent.y),
718 Cbezier(source.z, target.z, point1.z, point2.z, percent.z));
719}
720
721
722
723
724template<typename T>
725T Det2(Vector2<T> a, Vector2<T> b) {
726 return a.x * b.y - a.y * b.x;
727}
Definition Maths.h:407
Definition Maths.h:453
Definition Maths.h:513
Definition Maths.h:306
Definition Maths.h:21
Definition Maths.h:174
Definition Maths.h:275