CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
Math.hpp
Go to the documentation of this file.
1//
2// CeresEngine - A game development framework
3//
4// Created by Rogiel Sulzbach.
5// Copyright (c) 2018-2022 Rogiel Sulzbach. All rights reserved.
6//
7
8#pragma once
9
10#include "FloatingPoint.hpp"
11#include "Matrix.hpp"
12#include "Quaternion.hpp"
13#include "Vector.hpp"
14
16
20#include <glm/common.hpp>
21#include <glm/exponential.hpp>
22#include <glm/geometric.hpp>
23#include <glm/gtc/constants.hpp>
24#include <glm/gtc/matrix_inverse.hpp>
25#include <glm/gtc/matrix_transform.hpp>
26#include <glm/trigonometric.hpp>
27
28#include <glm/vector_relational.hpp>
29
30#define GLM_ENABLE_EXPERIMENTAL
31#include <glm/ext/matrix_clip_space.hpp>
32#include <glm/gtc/matrix_transform.hpp>
33#include <glm/gtc/type_ptr.hpp>
34#include <glm/gtx/matrix_decompose.hpp>
35#include <glm/gtx/matrix_major_storage.hpp>
36#include <glm/gtx/matrix_transform_2d.hpp>
37#include <glm/gtx/norm.hpp>
38#include <glm/gtx/normal.hpp>
39
40#include <glm/gtx/rotate_vector.hpp>
41#include <glm/gtx/string_cast.hpp>
43
44#include <algorithm>
45#include <cmath>
46
47#define IMPORT_FROM_GLM(Symbol) \
48 namespace CeresEngine::inline Math { \
49 using glm::Symbol; \
50 }
51
52// Common functions
55IMPORT_FROM_GLM(floor)
56IMPORT_FROM_GLM(trunc)
57IMPORT_FROM_GLM(round)
58IMPORT_FROM_GLM(roundEven)
63IMPORT_FROM_GLM(clamp)
66IMPORT_FROM_GLM(smoothstep)
67IMPORT_FROM_GLM(isnan)
68IMPORT_FROM_GLM(isinf)
69IMPORT_FROM_GLM(fma) //< a///b + c.
70IMPORT_FROM_GLM(frexp) //< significand///exp(2, exponent)
71IMPORT_FROM_GLM(ldexp) //< significand///exp(2, exponent)
72
73// Exponential functions
80IMPORT_FROM_GLM(inversesqrt)
81
82// Trigonometric functions
83IMPORT_FROM_GLM(radians)
84IMPORT_FROM_GLM(degrees)
94IMPORT_FROM_GLM(asinh)
95IMPORT_FROM_GLM(acosh)
96IMPORT_FROM_GLM(atanh)
97
98// Geometric functions
99IMPORT_FROM_GLM(length)
100IMPORT_FROM_GLM(length2)
101IMPORT_FROM_GLM(distance)
103IMPORT_FROM_GLM(cross)
104IMPORT_FROM_GLM(normalize)
105IMPORT_FROM_GLM(faceforward)
106IMPORT_FROM_GLM(reflect)
107IMPORT_FROM_GLM(refract)
108
109// Vector relational functions
110IMPORT_FROM_GLM(lessThan);
111IMPORT_FROM_GLM(lessThanEqual);
112IMPORT_FROM_GLM(greaterThan);
113IMPORT_FROM_GLM(greaterThanEqual);
114IMPORT_FROM_GLM(equal);
115IMPORT_FROM_GLM(notEqual);
116IMPORT_FROM_GLM(any);
117IMPORT_FROM_GLM(all);
118IMPORT_FROM_GLM(not_)
119
120// Matrix operations
121IMPORT_FROM_GLM(inverse)
122IMPORT_FROM_GLM(transpose)
123IMPORT_FROM_GLM(inverseTranspose)
124IMPORT_FROM_GLM(identity)
125
126// Matrix transformations functions
127IMPORT_FROM_GLM(translate)
128IMPORT_FROM_GLM(rotate)
129IMPORT_FROM_GLM(scale)
130
131// Projections and transform operations functions
132IMPORT_FROM_GLM(unProject)
133IMPORT_FROM_GLM(pickMatrix)
134IMPORT_FROM_GLM(lookAt)
135
136// String casting functions
137// IMPORT_FROM_GLM(to_string)
138IMPORT_FROM_GLM(decompose)
139
140#undef IMPORT_FROM_GLM
141
142namespace CeresEngine::inline Math {
143
144 static constexpr double PI = 3.14159265358979323846;
145
146 template<typename T> [[nodiscard]] TMatrix4<T> inline constexpr flipProjectionY(TMatrix4<T> proj) noexcept {
147 // Flip Y in clipspace. X = -1, Y = -1 is topLeft in Vulkan.
148 proj[1][1] *= T(-1);
149 return proj;
150 }
151
157 template<typename T> [[nodiscard]] inline constexpr TMatrix4<T> frustum(T left, T right, T bottom, T top, T zNear, T zFar) noexcept {
158 return flipProjectionY(glm::frustum(left, right, bottom, top, zNear, zFar));
159 }
160
170 template<typename T> [[nodiscard]] inline constexpr TMatrix4<T> perspective(T fovy, T aspect, T zNear, T zFar) noexcept {
171 return flipProjectionY(glm::perspective(fovy, aspect, zNear, zFar));
172 }
173
183 template<typename T> [[nodiscard]] inline constexpr TMatrix4<T> perspectiveFov(T fov, T width, T height, T zNear, T zFar) noexcept {
184 return flipProjectionY(glm::perspectiveFov(fov, width, height, zNear, zFar));
185 }
186
194 template<typename T> [[nodiscard]] inline constexpr TMatrix4<T> infinitePerspective(T fovy, T aspect, T zNear) noexcept {
195 return flipProjectionY(glm::infinitePerspective(fovy, aspect, zNear));
196 }
197
205 template<typename T> [[nodiscard]] inline constexpr TMatrix4<T> tweakedInfinitePerspective(T fovy, T aspect, T zNear) noexcept {
206 return flipProjectionY(glm::tweakedInfinitePerspective(fovy, aspect, zNear));
207 }
208
217 template<typename T> [[nodiscard]] inline constexpr TMatrix4<T> tweakedInfinitePerspective(T fovy, T aspect, T zNear, T ep) noexcept {
218 return flipProjectionY(glm::tweakedInfinitePerspective(fovy, aspect, zNear, ep));
219 }
220
227 template<typename T> [[nodiscard]] inline constexpr TMatrix4<T> ortho(T left, T right, T bottom, T top, T zNear, T zFar) {
228 return flipProjectionY(glm::ortho(left, right, bottom, top, zNear, zFar));
229 }
230
231 // ---------------------------------------------------------------------------------------------
232
234 template<typename T> inline double smoothStep(T val1, T val2, T t) {
235 t = clamp((t - val1) / (val2 - val1), 0.0, 1.0);
236 return t * t * (3.0 - 2.0 * t);
237 }
238
241 template<typename T> inline T quintic(T val) { return val * val * val * (val * (val * 6.0 - 15.0) + 10.0); }
242
246 template<typename T, typename U> inline auto cubic(T val1, T val2, T val3, T val4, U f) {
247 auto t = (val4 - val3) - (val1 - val2);
248 return f * f * f * t + f * f * ((val1 - val2) - t) + f * (val3 - val1) + val2;
249 }
250
251 // ---------------------------------------------------------------------------------------------
252
254 template<typename T, glm::length_t D>
255 inline bool approxEquals(const TVector<D, T>& a, const TVector<D, T>& b, T tolerance = std::numeric_limits<T>::epsilon()) {
257 for(glm::length_t i = 0; i < D; i++) {
258 result[i] = approxEquals(a[i], b[i], tolerance);
259 }
260 return all(result);
261 }
262
264 template<typename T, glm::length_t D> inline bool approxEquals(const TVector<D, T>& a, T b, T tolerance = std::numeric_limits<T>::epsilon()) {
265 return approxEquals(a, TVector<D, T>(b), tolerance);
266 }
267
269 template<typename T> inline bool approxEquals(const TQuaternion<T>& a, const TQuaternion<T>& b, T tolerance = std::numeric_limits<T>::epsilon()) {
270 return approxEquals(a.x, b.x, tolerance) && approxEquals(a.y, b.y, tolerance) && approxEquals(a.z, b.z, tolerance) && approxEquals(a.w, b.w, tolerance);
271 }
272
273 // ---------------------------------------------------------------------------------------------
274
278 template<typename T> inline T lerp(T t, T min, T max) { return (1.0 - t) * min + t * max; }
279
283 template<typename T> inline T invLerp(T val, T min, T max) { return clamp((val - min) / std::max(max - min, 0.0001), T(0), T(1)); }
284
286 template<typename A, typename B> inline std::common_type_t<A, B> gcd(const A& a, const B& b) { return (b == 0) ? a : gcd(b, a % b); }
287
289 template<typename A, typename B> inline std::common_type_t<A, B> lcm(const A& a, const B& b) { return (a * b) / gcd(a, b); }
290
291 // ---------------------------------------------------------------------------------------------
292
301 template<typename T> inline int solveLinear(T A, T B, T* roots) {
302 if(!approxEquals(A, T(0))) {
303 roots[0] = -B / A;
304 return 1;
305 }
306
307 roots[0] = T(0);
308 return 1;
309 }
310
321 template<typename T> inline int solveQuadratic(T A, T B, T C, T* roots) {
322 if(!approxEquals(A, T(0))) {
323 T p = B / (2 * A);
324 T q = C / A;
325 T D = p * p - q;
326
327 if(!approxEquals(D, T(0))) {
328 if(D < T(0)) {
329 return 0;
330 }
331
332 T sqrtD = sqrt(D);
333 roots[0] = sqrtD - p;
334 roots[1] = -sqrtD - p;
335
336 return 2;
337 }
338 roots[0] = -p;
339 roots[1] = -p;
340
341 return 1;
342 }
343 return solveLinear(B, C, roots);
344 }
345
357 template<typename T> inline int solveCubic(T A, T B, T C, T D, T* roots) {
358 static constexpr T THIRD = (1 / T(3));
359
360 T invA = 1 / A;
361 A = B * invA;
362 B = C * invA;
363 C = D * invA;
364
365 T sqA = A * A;
366 T p = THIRD * (-THIRD * sqA + B);
367 T q = (T(0.5)) * ((2 / T(27)) * A * sqA - THIRD * A * B + C);
368
369 T cbp = p * p * p;
370 D = q * q + cbp;
371
372 int numRoots = 0;
373 if(!approxEquals(D, T(0))) {
374 if(D < 0.0) {
375 T phi = THIRD * ::acos(-q / sqrt(-cbp));
376 T t = 2 * sqrt(-p);
377
378 roots[0] = t * cos(phi);
379 roots[1] = -t * cos(phi + PI * THIRD);
380 roots[2] = -t * cos(phi - PI * THIRD);
381
382 numRoots = 3;
383 } else {
384 T sqrtD = sqrt(D);
385 T u = cbrt(sqrtD + fabs(q));
386
387 if(q > T(0)) {
388 roots[0] = -u + p / u;
389 } else {
390 roots[0] = u - p / u;
391 }
392
393 numRoots = 1;
394 }
395 } else {
396 if(!approxEquals(q, T(0))) {
397 T u = cbrt(-q);
398 roots[0] = 2 * u;
399 roots[1] = -u;
400
401 numRoots = 2;
402 } else {
403 roots[0] = 0.0;
404 numRoots = 1;
405 }
406 }
407
408 T sub = THIRD * A;
409 for(int i = 0; i < numRoots; i++) {
410 roots[i] -= sub;
411 }
412
413 return numRoots;
414 }
415
428 template<typename T> inline int solveQuartic(T A, T B, T C, T D, T E, T* roots) {
429 T invA = 1 / A;
430 A = B * invA;
431 B = C * invA;
432 C = D * invA;
433 D = E * invA;
434
435 T sqA = A * A;
436 T p = -(3 / T(8)) * sqA + B;
437 T q = (1 / T(8)) * sqA * A - (T)0.5 * A * B + C;
438 T r = -(3 / T(256)) * sqA * sqA + (1 / (T)16) * sqA * B - (1 / (T)4) * A * C + D;
439
440 int numRoots = 0;
441 if(!approxEquals(r, T(0))) {
442 T cubicA = 1;
443 T cubicB = -T(0.5) * p;
444 T cubicC = -r;
445 T cubicD = T(0.5) * r * p - (1 / (T)8) * q * q;
446
448 T z = roots[0];
449
450 T u = z * z - r;
451 T v = 2 * z - p;
452
453 if(approxEquals(u, T(0))) {
454 u = 0;
455 } else if(u > 0) {
456 u = sqrt(u);
457 } else {
458 return 0;
459 }
460
461 if(approxEquals(v, T(0))) {
462 v = 0;
463 } else if(v > 0) {
464 v = sqrt(v);
465 } else {
466 return 0;
467 }
468
469 T quadraticA = 1;
470 T quadraticB = q < 0 ? -v : v;
471 T quadraticC = z - u;
472
474
475 quadraticA = 1;
476 quadraticB = q < 0 ? v : -v;
477 quadraticC = z + u;
478
480 } else {
481 numRoots = solveCubic(q, p, T(0), T(1), roots);
482 roots[numRoots++] = 0;
483 }
484
485 T sub = (1 / T(4)) * A;
486 for(int i = 0; i < numRoots; i++) {
487 roots[i] -= sub;
488 }
489
490 return numRoots;
491 }
492
493 // ---------------------------------------------------------------------------------------------
494
504 template<class T> inline T cubicHermite(const double t, const T& pointA, const T& pointB, const T& tangentA, const T& tangentB) {
505 const double t2 = t * t;
506 const double t3 = t2 * t;
507
508 double a = 2 * t3 - 3 * t2 + 1;
509 double b = t3 - 2 * t2 + t;
510 double c = -2 * t3 + 3 * t2;
511 double d = t3 - t2;
512
513 return T(a * pointA + b * tangentA + c * pointB + d * tangentB);
514 }
515
525 template<class T> inline T cubicHermiteD1(const double t, const T& pointA, const T& pointB, const T& tangentA, const T& tangentB) {
526 const double t2 = t * t;
527
528 double a = 6 * t2 - 6 * t;
529 double b = 3 * t2 - 4 * t + 1;
530 double c = -6 * t2 + 6 * t;
531 double d = 3 * t2 - 2 * t;
532
533 return T(a * pointA + b * tangentA + c * pointB + d * tangentB);
534 }
535
547 template<class T> inline Array<T, 4> cubicHermiteCoefficients(const T& pointA, const T& pointB, const T& tangentA, const T& tangentB) {
548 T diff = pointA - pointB;
549 return {2 * diff + tangentA + tangentB, -3 * diff - 2 * tangentA - tangentB, tangentA, pointA};
550 }
551
563 template<class T, typename L>
564 inline Array<T, 4> cubicHermiteCoefficients(const T& pointA, const T& pointB, const T& tangentA, const T& tangentB, L length) {
565 L length2 = length * length;
566 L invLength2 = 1.0 / length2;
567 L invLength3 = 1.0 / (length2 * length);
568
569 T scaledTangentA = T(tangentA * length);
570 T scaledTangentB = T(tangentB * length);
571
572 T diff = pointA - pointB;
573
574 return {T((2.0 * diff + scaledTangentA + scaledTangentB) * invLength3), T((-3.0 * diff - 2.0 * scaledTangentA - scaledTangentB) * invLength2), tangentA,
575 pointA};
576
577 // double length2 = length * length;
578 // double invLength2 = 1.0 / length2;
579 // double invLength3 = 1.0 / (length2 * length);
580
581 // double invLength2 = 1.0;
582 // double invLength3 = 1.0;
583 //
584 // T scaledTangentA = T(tangentA * length);
585 // T scaledTangentB = T(tangentB * length);
586 //
587 // T diff = pointA - pointB;
588 //
589 // return {
590 // T((2.0 * diff + scaledTangentA + scaledTangentB) *
591 // invLength3), T((-3.0 * diff - 2.0 * scaledTangentA -
592 // scaledTangentB) * invLength2), tangentA, pointA
593 // };
594 }
595
602 template<typename T, typename Integrand> inline T rombergIntegration(T a, T b, int order, Integrand&& integrand) {
603 T h[order + 1];
604 T r[order + 1][order + 1];
605
606 for(int i = 1; i < order + 1; ++i) {
607 h[i] = (b - a) / pow(2, i - 1);
608 }
609
610 r[1][1] = h[1] / 2 * (integrand(a) + integrand(b));
611
612 for(int i = 2; i < order + 1; ++i) {
613 T coeff = 0;
614 for(int k = 1; k <= pow(2, i - 2); ++k) {
615 coeff += integrand(a + (2 * k - 1) * h[i]);
616 }
617
618 r[i][1] = 0.5 * (r[i - 1][1] + h[i - 1] * coeff);
619 }
620
621 for(int i = 2; i < order + 1; ++i) {
622 for(int j = 2; j <= i; ++j) {
623 r[i][j] = r[i][j - 1] + (r[i][j - 1] - r[i - 1][j - 1]) / (pow(4, j - 1) - 1);
624 }
625 }
626
627 return r[order][order];
628 }
629
637 template<typename T, typename Integrand> inline T gaussianQuadrature(T a, T b, T* roots, T* coefficients, Integrand&& integrand) {
638 const T half = T(0.5);
639 const T radius = half * (b - a);
640 const T center = half * (b + a);
641 T res = T(0);
642
643 for(int i = 0; i < sizeof(roots) / sizeof(*roots); ++i) {
644 res += coefficients[i] * integrand(radius * roots[i] + center);
645 }
646
647 res *= radius;
648
649 return res;
650 }
651
656 template<typename T> inline T haltonSequence(int index, int base) {
657 T output = T(0.0);
658 T invBase = T(1.0) / base;
659 T frac = invBase;
660 while(index > 0) {
661 output += (index % base) * frac;
662 index /= base;
663 frac *= invBase;
664 }
665
666 return output;
667 }
668
669 // Function substitutes
670 template<typename T> T angle(const TVector2<T>& v1, const TVector2<T>& v2) {
671 using std::acos;
672 using std::numeric_limits;
673 using std::sqrt;
674
675 const T len = sqrt(dot(v1, v1) * dot(v2, v2));
676 if(len <= std::numeric_limits<T>::epsilon())
677 return T{0};
678 return acos(clamp(dot(v1, v2) / len, T{-1}, T{1}));
679 }
680
681 template<typename T> T angle(const TVector3<T>& v1, const TVector3<T>& v2) {
682 using std::acos;
683 using std::numeric_limits;
684 using std::sqrt;
685
686 const T len = sqrt(dot(v1, v1) * dot(v2, v2));
687 if(len <= std::numeric_limits<T>::epsilon())
688 return T{0};
689 return acos(clamp(dot(v1, v2) / len, T{-1}, T{1}));
690 }
691
692 template<typename T> TVector2<T> cross(const TVector2<T>& v) { return TVector2<T>(-v.y, v.x); }
693
694 template<typename T> TVector3<T> transform(const TQuaternion<T>& q, const TVector3<T>& v) {
695 const TVector3<T> temp = T{2.0} * cross(TVector3<T>(q.x, q.y, q.z), v);
696 return v + q.w * temp + cross(TVector3<T>(q.x, q.y, q.z), temp);
697 }
698
699 template<typename T> TQuaternion<T> qrotate(const T& angle, const TVector3<T>& axis) {
700 const T a = angle / T{2.0};
701 return TQuaternion<T>{cos(a), sin(a) * axis};
702 }
703
704 template<typename T> TVector3<T> normal(const TVector3<T>& p1, const TVector3<T>& p2, const TVector3<T>& p3) { return normalize(cross(p2 - p1, p3 - p1)); }
705
706 template<typename T, typename TI, typename TS>
708 TVector4<T> in = modelViewProj * TVector4<T>{v, static_cast<T>(1)};
709
710 in[0] /= in[3];
711 in[1] /= in[3];
712 in[2] /= in[3];
713
714 const T half = static_cast<T>(0.5);
715
716 in[0] = in[0] * half + half;
717 in[1] = in[1] * half + half;
718 in[2] = in[2] * half + half;
719
720 in[0] = in[0] * static_cast<T>(viewportSize[0]) + static_cast<T>(viewportOrigin[0]);
721 in[1] = in[1] * static_cast<T>(viewportSize[1]) + static_cast<T>(viewportOrigin[1]);
722
723 return TVector3<T>{in};
724 }
725
726 template<typename T> TMatrix4<T> ortho2D(const T& left, const T& right, const T& bottom, const T& top) {
727 return ortho(left, right, bottom, top, T{-1}, T{1});
728 }
729
730 template<typename T> TVector3<T> slerp(const TVector3<T>& v1, const TVector3<T>& v2, const T& a) {
731 using std::sin;
732 const T theta = angle(v1, v2);
733 const T sine = sin(theta);
734 return sin((T{1} - a) * theta) / sine * v1 + sin(a * theta) / sine * v2;
735 }
736
737 template<typename T> TMatrix4<T> rotate(const TVector3<T>& angle) {
738 const T sy = sin(angle[2]);
739 const T cy = cos(angle[2]);
740 const T sp = sin(angle[1]);
741 const T cp = cos(angle[1]);
742 const T sr = sin(angle[0]);
743 const T cr = cos(angle[0]);
744
745 const T data[16] = {cp * cy, sr * sp * cy + cr * -sy, cr * sp * cy + -sr * -sy, T{0}, cp * sy, sr * sp * sy + cr * cy, cr * sp * sy + -sr * cy, T{0},
746 -sp, sr * cp, cr * cp, T{0}, T{0}, T{0}, T{0}, T{1}};
747 return glm::rowMajor4(glm::make_mat4(data));
748 }
749
750 template<typename T> TMatrix3<T> rotate(const T& angle) {
751 const T s = sin(angle);
752 const T c = cos(angle);
753
754 const T data[9] = {c, -s, T{0}, s, c, T{0}, T{0}, T{0}, T{1}};
755
756 return glm::rowMajor3(glm::make_mat3(data));
757 }
758
759 template<typename T> TVector2<T> transform(const TMatrix3<T>& m, const TVector2<T>& v) { return TVector2<T>(m * TVector3<T>(v, 1.0)); }
760
761 namespace detail {
762
763 template<typename VecT, typename T> VecT bezierImpl(const VecT* p, const int n, T t1, T t2, int stride = 1) {
764 if(n == 1)
765 return *p;
766 if(n == 2)
767 return t1 * p[0] + t2 * p[stride];
768 return t1 * bezierImpl(p, n - 1, t1, t2, stride) + t2 * bezierImpl(p + stride, n - 1, t1, t2, stride);
769 }
770
771 } // namespace detail
772
773 template<int D, typename T> TVector2<T> bezier(const TVector2<T> (&p)[D], T t) {
774 static_assert(D > 0, "At least one control point needed.");
775 return detail::bezierImpl(&p[0], D, static_cast<T>(1) - t, t);
776 }
777
778 template<int D, typename T> TVector3<T> bezier(const TVector3<T> (&p)[D], T t) {
779 static_assert(D > 0, "At least one control point needed.");
780 return detail::bezierImpl(&p[0], D, static_cast<T>(1) - t, t);
781 }
782
783 template<int D0, int D1, typename T> TVector3<T> bezier2(const TVector3<T> (&p)[D1][D0], const TVector2<T>& t) {
784 static_assert(D0 > 0, "At least one control point needed.");
785 static_assert(D1 > 0, "At least one control point needed.");
786
788 for(int i = 0; i < D1; ++i) {
789 temp[i] = bezier(p[i], t[0]);
790 }
791 return bezier(temp, t[1]);
792 }
793
794 namespace detail {
795
796 template<int O, int D, typename VecT, typename T> struct bezierDerivativeImpl {
797 static VecT calc(const VecT (&p)[D], T t) {
798 VecT temp[D - 1];
799 for(int i = 0; i < D - 1; ++i) {
800 temp[i] = static_cast<T>(D - 1) * (p[i + 1] - p[i]);
801 }
803 }
804 };
805
806 template<int D, typename VecT, typename T> struct bezierDerivativeImpl<0, D, VecT, T> {
807 static VecT calc(const VecT (&p)[D], T t) { return bezier(p, t); }
808 };
809
810 template<typename VecT, typename T> struct bezierDerivativeImpl<0, 1, VecT, T> {
811 static VecT calc(const VecT (&p)[1], T t) { return bezier(p, t); }
812 };
813
814 template<int O, typename VecT, typename T> struct bezierDerivativeImpl<O, 1, VecT, T> {
815 static VecT calc(const VecT (&)[1], T) { return VecT{static_cast<T>(0)}; }
816 };
817
818 } // namespace detail
819
820 template<int O, int D, typename T> TVector2<T> bezierDerivative(const TVector2<T> (&p)[D], T t) {
821 static_assert(O > 0, "The derivative order must be at least one.");
822 static_assert(D > 0, "At least one control point needed.");
824 }
825
826 template<int O, int D, typename T> TVector3<T> bezierDerivative(const TVector3<T> (&p)[D], T t) {
827 static_assert(O > 0, "The derivative order must be at least one.");
828 static_assert(D > 0, "At least one control point needed.");
830 }
831
832 template<int O, int D0, int D1, typename T> TMatrix2x3<T> bezier2Jacobian(const TVector3<T> (&p)[D1][D0], const TVector2<T>& t) {
833 static_assert(O > 0, "Order of the Jacobian must be at least one.");
834 static_assert(D0 > 0, "At least one control point needed.");
835 static_assert(D1 > 0, "At least one control point needed.");
836
838 for(int i = 0; i < D0; ++i) {
839 temp0[i] = detail::bezierImpl(&p[0][i], D1, static_cast<T>(1) - t[1], t[1], D0);
840 }
841
843 for(int i = 0; i < D1; ++i) {
844 temp1[i] = bezier(p[i], t[0]);
845 }
846
848 }
849
850} // namespace CeresEngine::inline Math
851
852namespace CeresEngine::inline Math {
853
854 namespace Constant {
855
856#define IMPORT_GLM_CONSTANT_NAMED(Symbol, Name) template<typename T> inline const T Name = glm::Symbol<T>()
857#define IMPORT_GLM_CONSTANT(Symbol) IMPORT_GLM_CONSTANT_NAMED(Symbol, Symbol)
858
861
864
867
870
873
876
879
881 IMPORT_GLM_CONSTANT_NAMED(three_over_two_pi, _3pi_2);
882
884 IMPORT_GLM_CONSTANT_NAMED(quarter_pi, pi_4);
885
887 IMPORT_GLM_CONSTANT_NAMED(one_over_pi, _1_pi);
888
890 IMPORT_GLM_CONSTANT_NAMED(one_over_two_pi, _1_2pi);
891
893 IMPORT_GLM_CONSTANT_NAMED(two_over_pi, _2_pi);
894
896 IMPORT_GLM_CONSTANT_NAMED(four_over_pi, _4_pi);
897
899 IMPORT_GLM_CONSTANT_NAMED(two_over_root_pi, _2_sqrtpi);
900
902 IMPORT_GLM_CONSTANT_NAMED(one_over_root_two, _1_sqrt2);
903
905 IMPORT_GLM_CONSTANT_NAMED(root_half_pi, sqrt_pi_2);
906
908 IMPORT_GLM_CONSTANT_NAMED(root_two_pi, sqrt_2pi);
909
912
915
918
920 IMPORT_GLM_CONSTANT_NAMED(root_three, sqrt3);
921
923 IMPORT_GLM_CONSTANT_NAMED(root_five, sqrt5);
924
926 IMPORT_GLM_CONSTANT_NAMED(golden_ratio, goldenRatio);
927
928 } // namespace Constant
929
930 using Constant::pi;
931} // namespace CeresEngine::inline Math
#define CE_DISABLE_WARNING_DEPRECATED_DECLARATIONS
Definition Macros.hpp:498
#define CE_DISABLE_WARNING_DEPRECATED_VOLATILE
Definition Macros.hpp:497
#define CE_DISABLE_WARNING_POP
Definition Macros.hpp:485
#define CE_DISABLE_WARNING_PUSH
Definition Macros.hpp:484
#define IMPORT_GLM_CONSTANT_NAMED(Symbol, Name)
Definition Math.hpp:856
#define IMPORT_FROM_GLM(Symbol)
Definition Math.hpp:47
#define IMPORT_GLM_CONSTANT(Symbol)
Definition Math.hpp:857
Axis axis(const StringView &str) noexcept
Returns the Axis constant that is represented by str.
auto transform(Container &container, Transform &&transform)
Returns an iterable object that iterates over the values of the container and applies transform to ev...
Definition Iterator.hpp:436
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
VecT bezierImpl(const VecT *p, const int n, T t1, T t2, int stride=1)
Definition Math.hpp:763
Definition Angle.hpp:20
T invLerp(T val, T min, T max)
Determines the position of a value between two other values.
Definition Math.hpp:283
bool approxEquals(T a, T b, T tolerance=std::numeric_limits< T >::epsilon())
Compare two doubles, using tolerance for inaccuracies.
Definition FloatingPoint.hpp:17
T quintic(T val)
Performs quintic interpolation where val is the value to map onto a quintic S-curve.
Definition Math.hpp:241
TVector2< T > bezier(const TVector2< T >(&p)[D], T t)
Definition Math.hpp:773
glm::qua< T, glm::highp > TQuaternion
A quaternion type that uses a internal representation of type T
Definition Quaternion.hpp:23
constexpr FixedPoint< T, P > frac(const FixedPoint< T, P > &x)
Returns the fractional portion of a fixed-point value.
Definition FixedPoint.hpp:417
auto cubic(T val1, T val2, T val3, T val4, U f)
Performs cubic interpolation between two values bound between two other values where f is the alpha v...
Definition Math.hpp:246
T rombergIntegration(T a, T b, int order, Integrand &&integrand)
Calculates the Romberg Integration.
Definition Math.hpp:602
int solveQuadratic(T A, T B, T C, T *roots)
Solves the quadratic equation with the parameters A, B, C.
Definition Math.hpp:321
int solveLinear(T A, T B, T *roots)
Solves the linear equation with the parameters A, B.
Definition Math.hpp:301
constexpr TMatrix4< T > infinitePerspective(T fovy, T aspect, T zNear) noexcept
Creates a matrix for a symmetric perspective-view frustum with far plane at infinite with default han...
Definition Math.hpp:194
TVector3< T > project(const TVector3< T > &v, const TMatrix4< T > &modelViewProj, const TVector2< TI > &viewportOrigin, const TVector2< TS > &viewportSize)
Definition Math.hpp:707
TQuaternion< T > qrotate(const T &angle, const TVector3< T > &axis)
Definition Math.hpp:699
int solveQuartic(T A, T B, T C, T D, T E, T *roots)
Solves the quartic equation with the parameters A, B, C, D, E.
Definition Math.hpp:428
TMatrix4< T > ortho2D(const T &left, const T &right, const T &bottom, const T &top)
Definition Math.hpp:726
constexpr FixedPoint< T, P > cos(const FixedPoint< T, P > &x)
Returns cosine of a fixed-point value.
Definition FixedPoint.hpp:588
glm::vec< D, T, glm::highp > TVector
A D-dimensional vector type that uses a internal representation of type T
Definition Vector.hpp:39
TVector2< T > bezierDerivative(const TVector2< T >(&p)[D], T t)
Definition Math.hpp:820
TMatrix4< T > constexpr flipProjectionY(TMatrix4< T > proj) noexcept
Definition Math.hpp:146
TVector2< T > cross(const TVector2< T > &v)
Definition Math.hpp:692
TVector3< T > slerp(const TVector3< T > &v1, const TVector3< T > &v2, const T &a)
Definition Math.hpp:730
T cubicHermiteD1(const double t, const T &pointA, const T &pointB, const T &tangentA, const T &tangentB)
Evaluates the first derivative of a cubic Hermite curve at a specific point.
Definition Math.hpp:525
TMatrix< 3, 3, T > TMatrix3
A 3x3 type that uses a internal representation of type T
Definition Matrix.hpp:41
int solveCubic(T A, T B, T C, T D, T *roots)
Solves the cubic equation with the parameters A, B, C, D.
Definition Math.hpp:357
TMatrix< 4, 4, T > TMatrix4
A 4x4 type that uses a internal representation of type T
Definition Matrix.hpp:54
constexpr FixedPoint< T, P > sqrt(const FixedPoint< T, P > &x)
Returns square root of a fixed-point value.
Definition FixedPoint.hpp:458
FixedPoint< B, F > sin(FixedPoint< B, F > x) noexcept
Definition FixedPoint.hpp:554
TMatrix< 2, 3, T > TMatrix2x3
A 2x3 type that uses a internal representation of type T
Definition Matrix.hpp:67
T lerp(T t, T min, T max)
Linearly interpolates between the two values using t.
Definition Math.hpp:278
T angle(const TVector2< T > &v1, const TVector2< T > &v2)
Definition Math.hpp:670
Array< T, 4 > cubicHermiteCoefficients(const T &pointA, const T &pointB, const T &tangentA, const T &tangentB)
Calculates coefficients needed for evaluating a cubic curve in Hermite form.
Definition Math.hpp:547
TVector< 4, T > TVector4
A four dimensional vector type that uses a internal representation of type T
Definition Vector.hpp:115
T gaussianQuadrature(T a, T b, T *roots, T *coefficients, Integrand &&integrand)
Calculates the Gaussian Quadrature.
Definition Math.hpp:637
constexpr TMatrix4< T > ortho(T left, T right, T bottom, T top, T zNear, T zFar)
Creates a matrix for projecting two-dimensional coordinates onto the screen.
Definition Math.hpp:227
double smoothStep(T val1, T val2, T t)
Performs smooth Hermite interpolation between values.
Definition Math.hpp:234
constexpr TMatrix4< T > perspective(T fovy, T aspect, T zNear, T zFar) noexcept
Creates a matrix for a symetric perspective-view frustum based on the default handedness and default ...
Definition Math.hpp:170
TMatrix2x3< T > bezier2Jacobian(const TVector3< T >(&p)[D1][D0], const TVector2< T > &t)
Definition Math.hpp:832
std::common_type_t< A, B > lcm(const A &a, const B &b)
Return the least common multiple between two values.
Definition Math.hpp:289
std::common_type_t< A, B > gcd(const A &a, const B &b)
Return the greater common divisor between two values.
Definition Math.hpp:286
constexpr TMatrix4< T > frustum(T left, T right, T bottom, T top, T zNear, T zFar) noexcept
Creates a frustum matrix with default handedness, using the default handedness and default near and f...
Definition Math.hpp:157
TVector3< T > normal(const TVector3< T > &p1, const TVector3< T > &p2, const TVector3< T > &p3)
Definition Math.hpp:704
TVector< 2, T > TVector2
A two dimensional vector type that uses a internal representation of type T
Definition Vector.hpp:45
TVector< 3, T > TVector3
A three dimensional vector type that uses a internal representation of type T
Definition Vector.hpp:80
TMatrix4< T > rotate(const TVector3< T > &angle)
Definition Math.hpp:737
TVector3< T > bezier2(const TVector3< T >(&p)[D1][D0], const TVector2< T > &t)
Definition Math.hpp:783
constexpr TMatrix4< T > tweakedInfinitePerspective(T fovy, T aspect, T zNear) noexcept
Creates a matrix for a symmetric perspective-view frustum with far plane at infinite for graphics har...
Definition Math.hpp:205
T cubicHermite(const double t, const T &pointA, const T &pointB, const T &tangentA, const T &tangentB)
Evaluates a cubic Hermite curve at a specific point.
Definition Math.hpp:504
constexpr FixedPoint< T, P > acos(FixedPoint< T, P > x)
Returns arccosine of a fixed-point value.
Definition FixedPoint.hpp:475
T haltonSequence(int index, int base)
Generates numbers in a deterministic sequence suitable for Monte Carlo algorithms.
Definition Math.hpp:656
constexpr TMatrix4< T > perspectiveFov(T fov, T width, T height, T zNear, T zFar) noexcept
Builds a perspective projection matrix based on a field of view and the default handedness and defaul...
Definition Math.hpp:183
static VecT calc(const VecT(&p)[1], T t)
Definition Math.hpp:811
static VecT calc(const VecT(&p)[D], T t)
Definition Math.hpp:807
static VecT calc(const VecT(&)[1], T)
Definition Math.hpp:815
Definition Math.hpp:796
static VecT calc(const VecT(&p)[D], T t)
Definition Math.hpp:797