Unravel Engine C++ Reference
Loading...
Searching...
No Matches
math.hpp
Go to the documentation of this file.
1#ifndef GENERATOR_MATH_HPP
2#define GENERATOR_MATH_HPP
3
4#define GENERATOR_USE_GLM
5#ifdef GENERATOR_USE_GLM
6
7#include <limits>
8#include <stdexcept>
9
10#include <math/math.h>
11
12namespace gml
13{
14
15// Vectors
16using glm::bvec2;
17using glm::dvec2;
18using glm::ivec2;
19using glm::uvec2;
20using glm::vec2;
21
22using glm::bvec3;
23using glm::dvec3;
24using glm::ivec3;
25using glm::uvec3;
26using glm::vec3;
27
28using glm::bvec4;
29using glm::dvec4;
30using glm::ivec4;
31using glm::uvec4;
32using glm::vec4;
33
34// Matrices
35using glm::mat2;
36using glm::mat2x2;
37using glm::mat2x3;
38using glm::mat2x4;
39using glm::mat3;
40using glm::mat3x2;
41using glm::mat3x3;
42using glm::mat3x4;
43using glm::mat4;
44using glm::mat4x2;
45using glm::mat4x3;
46using glm::mat4x4;
47
48using glm::dmat2;
49using glm::dmat2x2;
50using glm::dmat2x3;
51using glm::dmat2x4;
52using glm::dmat3;
53using glm::dmat3x2;
54using glm::dmat3x3;
55using glm::dmat3x4;
56using glm::dmat4;
57using glm::dmat4x2;
58using glm::dmat4x3;
59using glm::dmat4x4;
60
61// Quaternions
62using glm::dquat;
63using glm::quat;
64
65// Functions
66using glm::clamp;
67using glm::cross;
68using glm::degrees;
69using glm::dot;
70using glm::max;
71using glm::min;
72using glm::mix;
73using glm::normalize;
74using glm::ortho;
75using glm::perspective;
76using glm::radians;
77using glm::rotate;
78using glm::translate;
79
80// Function substitutes
81template<typename T>
82T angle(const glm::tvec2<T>& v1, const glm::tvec2<T>& v2)
83{
84 using std::acos;
85 using std::numeric_limits;
86 using std::sqrt;
87
88 const T len = sqrt(dot(v1, v1) * dot(v2, v2));
89 if(len <= std::numeric_limits<T>::epsilon())
90 return T{0};
91 return acos(clamp(dot(v1, v2) / len, T{-1}, T{1}));
92}
93
94template<typename T>
95T angle(const glm::tvec3<T>& v1, const glm::tvec3<T>& v2)
96{
97 using std::acos;
98 using std::numeric_limits;
99 using std::sqrt;
100
101 const T len = sqrt(dot(v1, v1) * dot(v2, v2));
102 if(len <= std::numeric_limits<T>::epsilon())
103 return T{0};
104 return acos(clamp(dot(v1, v2) / len, T{-1}, T{1}));
105}
106
107template<typename T>
108glm::tvec2<T> cross(const glm::tvec2<T>& v)
109{
110 return glm::tvec2<T>(-v.y, v.x);
111}
112
113template<typename T>
114glm::tvec3<T> transform(const glm::tquat<T>& q, const glm::tvec3<T>& v)
115{
116 const glm::tvec3<T> temp = T{2.0} * cross(glm::tvec3<T>(q.x, q.y, q.z), v);
117 return v + q.w * temp + cross(glm::tvec3<T>(q.x, q.y, q.z), temp);
118}
119
120template<typename T>
121glm::tquat<T> qrotate(const T& angle, const glm::tvec3<T>& axis)
122{
123 using std::cos;
124 using std::sin;
125
126 const T a = angle / T{2.0};
127 return glm::tquat<T>{cos(a), sin(a) * axis};
128}
129
130template<typename T>
131glm::tvec3<T> normal(const glm::tvec3<T>& p1, const glm::tvec3<T>& p2, const glm::tvec3<T>& p3)
132{
133 return normalize(cross(p2 - p1, p3 - p1));
134}
135
136template<typename T, typename TI, typename TS>
137glm::tvec3<T> project(const glm::tvec3<T>& v,
138 const glm::tmat4x4<T>& modelViewProj,
139 const glm::tvec2<TI>& viewportOrigin,
140 const glm::tvec2<TS>& viewportSize)
141{
142 glm::tvec4<T> in = modelViewProj * glm::tvec4<T>{v, static_cast<T>(1)};
143
144 in[0] /= in[3];
145 in[1] /= in[3];
146 in[2] /= in[3];
147
148 const auto half = static_cast<T>(0.5);
149
150 in[0] = in[0] * half + half;
151 in[1] = in[1] * half + half;
152 in[2] = in[2] * half + half;
153
154 in[0] = in[0] * static_cast<T>(viewportSize[0]) + static_cast<T>(viewportOrigin[0]);
155 in[1] = in[1] * static_cast<T>(viewportSize[1]) + static_cast<T>(viewportOrigin[1]);
156
157 return glm::tvec3<T>{in};
158}
159
160template<typename T>
161glm::tmat4x4<T> ortho2D(const T& left, const T& right, const T& bottom, const T& top)
162{
163 return ortho(left, right, bottom, top, T{-1}, T{1});
164}
165
166template<typename T>
167glm::tvec3<T> slerp(const glm::tvec3<T>& v1, const glm::tvec3<T>& v2, const T& a)
168{
169 using std::sin;
170 const T theta = angle(v1, v2);
171 const T sine = sin(theta);
172 return sin((T{1} - a) * theta) / sine * v1 + sin(a * theta) / sine * v2;
173}
174
175template<typename T>
176glm::tmat4x4<T> rotate(const glm::tvec3<T>& angle)
177{
178 using std::cos;
179 using std::sin;
180
181 const T sy = sin(angle[2]);
182 const T cy = cos(angle[2]);
183 const T sp = sin(angle[1]);
184 const T cp = cos(angle[1]);
185 const T sr = sin(angle[0]);
186 const T cr = cos(angle[0]);
187
188 const T data[16] = {cp * cy,
189 sr * sp * cy + cr * -sy,
190 cr * sp * cy + -sr * -sy,
191 T{0},
192 cp * sy,
193 sr * sp * sy + cr * cy,
194 cr * sp * sy + -sr * cy,
195 T{0},
196 -sp,
197 sr * cp,
198 cr * cp,
199 T{0},
200 T{0},
201 T{0},
202 T{0},
203 T{1}};
204 return glm::rowMajor4(glm::make_mat4(data));
205}
206
207template<typename T>
208glm::tmat3x3<T> rotate(const T& angle)
209{
210 using std::cos;
211 using std::sin;
212
213 const T s = sin(angle);
214 const T c = cos(angle);
215
216 const T data[9] = {c, -s, T{0}, s, c, T{0}, T{0}, T{0}, T{1}};
217
218 return glm::rowMajor3(glm::make_mat3(data));
219}
220
221template<typename T>
222glm::tvec2<T> transform(const glm::tmat3x3<T>& m, const glm::tvec2<T>& v)
223{
224 return glm::tvec2<T>(m * glm::tvec3<T>(v, 1.0));
225}
226
227namespace detail
228{
229
230template<typename VecT, typename T>
231VecT bezierImpl(const VecT* p, int n, T t1, T t2, int stride = 1)
232{
233 if(n == 1)
234 return *p;
235 if(n == 2)
236 return t1 * p[0] + t2 * p[stride];
237 return t1 * bezierImpl(p, n - 1, t1, t2, stride) + t2 * bezierImpl(p + stride, n - 1, t1, t2, stride);
238}
239
240} // namespace detail
241
242template<int D, typename T>
243glm::tvec2<T> bezier(const glm::tvec2<T> (&p)[D], T t)
244{
245 static_assert(D > 0, "At least one control point needed.");
246 return detail::bezierImpl(&p[0], D, static_cast<T>(1) - t, t);
247}
248
249template<int D, typename T>
250glm::tvec3<T> bezier(const glm::tvec3<T> (&p)[D], T t)
251{
252 static_assert(D > 0, "At least one control point needed.");
253 return detail::bezierImpl(&p[0], D, static_cast<T>(1) - t, t);
254}
255
256template<int D0, int D1, typename T>
257glm::tvec3<T> bezier2(const glm::tvec3<T> (&p)[D1][D0], const glm::tvec2<T>& t)
258{
259 static_assert(D0 > 0, "At least one control point needed.");
260 static_assert(D1 > 0, "At least one control point needed.");
261
262 glm::tvec3<T> temp[D1];
263 for(int i = 0; i < D1; ++i)
264 {
265 temp[i] = bezier(p[i], t[0]);
266 }
267 return bezier(temp, t[1]);
268}
269
270namespace detail
271{
272
273template<int O, int D, typename VecT, typename T>
275{
276 static VecT calc(const VecT (&p)[D], T t)
277 {
278 VecT temp[D - 1];
279 for(int i = 0; i < D - 1; ++i)
280 {
281 temp[i] = static_cast<T>(D - 1) * (p[i + 1] - p[i]);
282 }
284 }
285};
286
287template<int D, typename VecT, typename T>
288struct bezierDerivativeImpl<0, D, VecT, T>
289{
290 static VecT calc(const VecT (&p)[D], T t)
291 {
292 return bezier(p, t);
293 }
294};
295
296template<typename VecT, typename T>
297struct bezierDerivativeImpl<0, 1, VecT, T>
298{
299 static VecT calc(const VecT (&p)[1], T t)
300 {
301 return bezier(p, t);
302 }
303};
304
305template<int O, typename VecT, typename T>
306struct bezierDerivativeImpl<O, 1, VecT, T>
307{
308 static VecT calc(const VecT (&)[1], T)
309 {
310 return VecT{static_cast<T>(0)};
311 }
312};
313
314} // namespace detail
315
316template<int O, int D, typename T>
317glm::tvec2<T> bezierDerivative(const glm::tvec2<T> (&p)[D], T t)
318{
319 static_assert(O > 0, "The derivative order must be at least one.");
320 static_assert(D > 0, "At least one control point needed.");
322}
323
324template<int O, int D, typename T>
325glm::tvec3<T> bezierDerivative(const glm::tvec3<T> (&p)[D], T t)
326{
327 static_assert(O > 0, "The derivative order must be at least one.");
328 static_assert(D > 0, "At least one control point needed.");
330}
331
332template<int O, int D0, int D1, typename T>
333glm::tmat2x3<T> bezier2Jacobian(const glm::tvec3<T> (&p)[D1][D0], const glm::tvec2<T>& t)
334{
335 static_assert(O > 0, "Order of the Jacobian must be at least one.");
336 static_assert(D0 > 0, "At least one control point needed.");
337 static_assert(D1 > 0, "At least one control point needed.");
338
339 glm::tvec3<T> temp0[D0];
340 for(int i = 0; i < D0; ++i)
341 {
342 temp0[i] = detail::bezierImpl(&p[0][i], D1, static_cast<T>(1) - t[1], t[1], D0);
343 }
344
345 glm::tvec3<T> temp1[D1];
346 for(int i = 0; i < D1; ++i)
347 {
348 temp1[i] = bezier(p[i], t[0]);
349 }
350
351 return glm::tmat2x3<T>{bezierDerivative<O>(temp0, t[0]), bezierDerivative<O>(temp1, t[1])};
352}
353} // namespace gml
354
355#else
356
357#include <gml/gml.hpp>
358
359#endif
360
361#endif
btVector3 normal
entt::handle a
VecT bezierImpl(const VecT *p, int n, T t1, T t2, int stride=1)
Definition math.hpp:231
Definition math.hpp:13
glm::tvec2< T > cross(const glm::tvec2< T > &v)
Definition math.hpp:108
glm::tvec3< T > transform(const glm::tquat< T > &q, const glm::tvec3< T > &v)
Definition math.hpp:114
glm::tquat< T > qrotate(const T &angle, const glm::tvec3< T > &axis)
Definition math.hpp:121
glm::tvec2< T > bezierDerivative(const glm::tvec2< T >(&p)[D], T t)
Definition math.hpp:317
T angle(const glm::tvec2< T > &v1, const glm::tvec2< T > &v2)
Definition math.hpp:82
glm::tvec2< T > bezier(const glm::tvec2< T >(&p)[D], T t)
Definition math.hpp:243
glm::tvec3< T > bezier2(const glm::tvec3< T >(&p)[D1][D0], const glm::tvec2< T > &t)
Definition math.hpp:257
glm::tmat4x4< T > rotate(const glm::tvec3< T > &angle)
Definition math.hpp:176
glm::tmat4x4< T > ortho2D(const T &left, const T &right, const T &bottom, const T &top)
Definition math.hpp:161
glm::tvec3< T > project(const glm::tvec3< T > &v, const glm::tmat4x4< T > &modelViewProj, const glm::tvec2< TI > &viewportOrigin, const glm::tvec2< TS > &viewportSize)
Definition math.hpp:137
glm::tvec3< T > slerp(const glm::tvec3< T > &v1, const glm::tvec3< T > &v2, const T &a)
Definition math.hpp:167
glm::tmat2x3< T > bezier2Jacobian(const glm::tvec3< T >(&p)[D1][D0], const glm::tvec2< T > &t)
Definition math.hpp:333
static VecT calc(const VecT(&p)[1], T t)
Definition math.hpp:299
static VecT calc(const VecT(&p)[D], T t)
Definition math.hpp:290
static VecT calc(const VecT(&)[1], T)
Definition math.hpp:308
static VecT calc(const VecT(&p)[D], T t)
Definition math.hpp:276