1#ifndef GENERATOR_MATH_HPP
2#define GENERATOR_MATH_HPP
4#define GENERATOR_USE_GLM
5#ifdef GENERATOR_USE_GLM
75using glm::perspective;
82T
angle(
const glm::tvec2<T>& v1,
const glm::tvec2<T>& v2)
85 using std::numeric_limits;
88 const T len = sqrt(dot(v1, v1) * dot(v2, v2));
89 if(len <= std::numeric_limits<T>::epsilon())
91 return acos(clamp(dot(v1, v2) / len, T{-1}, T{1}));
95T
angle(
const glm::tvec3<T>& v1,
const glm::tvec3<T>& v2)
98 using std::numeric_limits;
101 const T len = sqrt(dot(v1, v1) * dot(v2, v2));
102 if(len <= std::numeric_limits<T>::epsilon())
104 return acos(clamp(dot(v1, v2) / len, T{-1}, T{1}));
108glm::tvec2<T>
cross(
const glm::tvec2<T>& v)
110 return glm::tvec2<T>(-v.y, v.x);
114glm::tvec3<T>
transform(
const glm::tquat<T>& q,
const glm::tvec3<T>& v)
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);
126 const T
a =
angle / T{2.0};
127 return glm::tquat<T>{cos(
a), sin(
a) * axis};
131glm::tvec3<T>
normal(
const glm::tvec3<T>& p1,
const glm::tvec3<T>& p2,
const glm::tvec3<T>& p3)
133 return normalize(
cross(p2 - p1, p3 - p1));
136template<
typename T,
typename TI,
typename TS>
138 const glm::tmat4x4<T>& modelViewProj,
139 const glm::tvec2<TI>& viewportOrigin,
140 const glm::tvec2<TS>& viewportSize)
142 glm::tvec4<T> in = modelViewProj * glm::tvec4<T>{v,
static_cast<T
>(1)};
148 const auto half =
static_cast<T
>(0.5);
150 in[0] = in[0] * half + half;
151 in[1] = in[1] * half + half;
152 in[2] = in[2] * half + half;
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]);
157 return glm::tvec3<T>{in};
161glm::tmat4x4<T>
ortho2D(
const T& left,
const T& right,
const T& bottom,
const T& top)
163 return ortho(left, right, bottom, top, T{-1}, T{1});
167glm::tvec3<T>
slerp(
const glm::tvec3<T>& v1,
const glm::tvec3<T>& v2,
const T&
a)
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;
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]);
188 const T data[16] = {cp * cy,
189 sr * sp * cy + cr * -sy,
190 cr * sp * cy + -sr * -sy,
193 sr * sp * sy + cr * cy,
194 cr * sp * sy + -sr * cy,
204 return glm::rowMajor4(glm::make_mat4(data));
213 const T s = sin(
angle);
214 const T c = cos(
angle);
216 const T data[9] = {c, -s, T{0}, s, c, T{0}, T{0}, T{0}, T{1}};
218 return glm::rowMajor3(glm::make_mat3(data));
222glm::tvec2<T>
transform(
const glm::tmat3x3<T>& m,
const glm::tvec2<T>& v)
224 return glm::tvec2<T>(m * glm::tvec3<T>(v, 1.0));
230template<
typename VecT,
typename T>
231VecT
bezierImpl(
const VecT* p,
int n, T t1, T t2,
int stride = 1)
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);
242template<
int D,
typename T>
243glm::tvec2<T>
bezier(
const glm::tvec2<T> (&p)[D], T t)
245 static_assert(D > 0,
"At least one control point needed.");
249template<
int D,
typename T>
250glm::tvec3<T>
bezier(
const glm::tvec3<T> (&p)[D], T t)
252 static_assert(D > 0,
"At least one control point needed.");
256template<
int D0,
int D1,
typename T>
257glm::tvec3<T>
bezier2(
const glm::tvec3<T> (&p)[D1][D0],
const glm::tvec2<T>& t)
259 static_assert(D0 > 0,
"At least one control point needed.");
260 static_assert(D1 > 0,
"At least one control point needed.");
262 glm::tvec3<T> temp[D1];
263 for(
int i = 0; i < D1; ++i)
265 temp[i] =
bezier(p[i], t[0]);
267 return bezier(temp, t[1]);
273template<
int O,
int D,
typename VecT,
typename T>
276 static VecT
calc(
const VecT (&p)[D], T t)
279 for(
int i = 0; i < D - 1; ++i)
281 temp[i] =
static_cast<T
>(D - 1) * (p[i + 1] - p[i]);
287template<
int D,
typename VecT,
typename T>
290 static VecT
calc(
const VecT (&p)[D], T t)
296template<
typename VecT,
typename T>
299 static VecT
calc(
const VecT (&p)[1], T t)
305template<
int O,
typename VecT,
typename T>
308 static VecT
calc(
const VecT (&)[1], T)
310 return VecT{
static_cast<T
>(0)};
316template<
int O,
int D,
typename T>
319 static_assert(O > 0,
"The derivative order must be at least one.");
320 static_assert(D > 0,
"At least one control point needed.");
324template<
int O,
int D,
typename T>
327 static_assert(O > 0,
"The derivative order must be at least one.");
328 static_assert(D > 0,
"At least one control point needed.");
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)
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.");
339 glm::tvec3<T> temp0[D0];
340 for(
int i = 0; i < D0; ++i)
345 glm::tvec3<T> temp1[D1];
346 for(
int i = 0; i < D1; ++i)
348 temp1[i] =
bezier(p[i], t[0]);
357#include <gml/gml.hpp>
VecT bezierImpl(const VecT *p, int n, T t1, T t2, int stride=1)
glm::tvec2< T > cross(const glm::tvec2< T > &v)
glm::tvec3< T > transform(const glm::tquat< T > &q, const glm::tvec3< T > &v)
glm::tquat< T > qrotate(const T &angle, const glm::tvec3< T > &axis)
glm::tvec2< T > bezierDerivative(const glm::tvec2< T >(&p)[D], T t)
T angle(const glm::tvec2< T > &v1, const glm::tvec2< T > &v2)
glm::tvec2< T > bezier(const glm::tvec2< T >(&p)[D], T t)
glm::tvec3< T > bezier2(const glm::tvec3< T >(&p)[D1][D0], const glm::tvec2< T > &t)
glm::tmat4x4< T > rotate(const glm::tvec3< T > &angle)
glm::tmat4x4< T > ortho2D(const T &left, const T &right, const T &bottom, const T &top)
glm::tvec3< T > project(const glm::tvec3< T > &v, const glm::tmat4x4< T > &modelViewProj, const glm::tvec2< TI > &viewportOrigin, const glm::tvec2< TS > &viewportSize)
glm::tvec3< T > slerp(const glm::tvec3< T > &v1, const glm::tvec3< T > &v2, const T &a)
glm::tmat2x3< T > bezier2Jacobian(const glm::tvec3< T >(&p)[D1][D0], const glm::tvec2< T > &t)
static VecT calc(const VecT(&p)[1], T t)
static VecT calc(const VecT(&p)[D], T t)
static VecT calc(const VecT(&)[1], T)
static VecT calc(const VecT(&p)[D], T t)