3 #include <Core/Math/Math.hpp>
4 #include <Core/RaCore.hpp>
8 #include <Eigen/Geometry>
9 #include <Eigen/Sparse>
10 #include <unsupported/Eigen/AlignedVector3>
22 inline void print(
const MatrixN& matrix );
35 template <
typename Vector>
36 inline Vector
floor(
const Vector& v );
39 template <
typename Vector>
40 inline Vector
ceil(
const Vector& v );
43 template <
typename Vector>
44 inline Vector
trunc(
const Vector& v );
48 template <
typename Derived,
typename DerivedA,
typename DerivedB>
49 inline typename Derived::PlainMatrix
clamp(
const Eigen::MatrixBase<Derived>& v,
50 const Eigen::MatrixBase<DerivedA>& min,
51 const Eigen::MatrixBase<DerivedB>& max );
53 template <
typename Derived>
54 inline typename Derived::PlainMatrix
55 clamp(
const Eigen::MatrixBase<Derived>& v,
const Scalar& min,
const Scalar& max );
60 const bool FAIL_ON_ASSERT =
false ) {
66 template <
typename Matrix_>
68 const bool FAIL_ON_ASSERT =
false );
77 template <
typename Vector_>
78 inline Scalar
angle(
const Vector_& v1,
const Vector_& v2 );
82 template <
typename Vector_>
83 inline Vector_
slerp(
const Vector_& v1,
const Vector_& v2, Scalar t );
87 projectOnPlane(
const Vector3& planePos,
const Vector3& planeNormal,
const Vector3& point );
91 template <
typename Vector_>
92 inline Scalar
cotan(
const Vector_& v1,
const Vector_& v2 );
96 template <
typename Vector_>
97 inline Scalar
cos(
const Vector_& v1,
const Vector_& v2 );
101 template <
typename Vector_>
106 template <
typename Vector_>
116 template <
typename Scalar>
117 inline Eigen::ParametrizedLine<Scalar, 3>
118 transformRay(
const Eigen::Transform<Scalar, 3, Eigen::Affine>& t,
119 const Eigen::ParametrizedLine<Scalar, 3>& r );
121 inline Matrix4 lookAt(
const Vector3& position,
const Vector3& target,
const Vector3& up );
122 inline Matrix4 perspective( Scalar fovy, Scalar aspect, Scalar near, Scalar zfar );
124 orthographic( Scalar left, Scalar right, Scalar bottom, Scalar top, Scalar near, Scalar zfar );
136 inline Quaternion
scale(
const Quaternion& q,
const Scalar k );
139 inline Quaternion
add(
const Quaternion& q1,
const Quaternion& q2 );
145 inline Quaternion
addQlerp(
const Quaternion& q1,
const Quaternion& q2 );
155 inline void getSwingTwist(
const Quaternion& in, Quaternion& swingOut, Quaternion& twistOut );
157 inline void print(
const MatrixN& matrix ) {
161 std::cout <<
"Matrix rows : " << matrix.rows() << std::endl;
162 std::cout <<
"Matrix cols : " << matrix.cols() << std::endl;
163 Eigen::IOFormat cleanFormat( 4, 0,
", ",
"\n",
"[",
"]" );
164 std::cout << matrix.format( cleanFormat ) << std::endl;
171 template <
typename Vector_>
172 inline Vector_
floor(
const Vector_& v ) {
173 using Scalar_ =
typename Vector_::Scalar;
175 std::function<Scalar_( Scalar_ )>(
static_cast<Scalar_ ( & )( Scalar_ )
>( std::floor ) ) );
178 template <
typename Vector_>
179 inline Vector_
ceil(
const Vector_& v ) {
180 using Scalar_ =
typename Vector_::Scalar;
182 std::function<Scalar_( Scalar_ )>(
static_cast<Scalar_ ( & )( Scalar_ )
>( std::ceil ) ) );
185 template <
typename Vector_>
186 inline Vector_
trunc(
const Vector_& v ) {
187 using Scalar_ =
typename Vector_::Scalar;
189 std::function<Scalar_( Scalar_ )>(
static_cast<Scalar_ ( & )( Scalar_ )
>( std::trunc ) ) );
192 template <
typename Derived,
typename DerivedA,
typename DerivedB>
193 inline typename Derived::PlainMatrix
clamp(
const Eigen::MatrixBase<Derived>& v,
194 const Eigen::MatrixBase<DerivedA>& min,
195 const Eigen::MatrixBase<DerivedB>& max ) {
196 return v.cwiseMin( max ).cwiseMax( min );
199 template <
typename Derived>
200 inline typename Derived::PlainMatrix
201 clamp(
const Eigen::MatrixBase<Derived>& v,
const Scalar& min,
const Scalar& max ) {
202 return v.unaryExpr( [min, max]( Scalar x ) {
return std::clamp( x, min, max ); } );
205 template <
typename Vector_>
206 inline Scalar
angle(
const Vector_& v1,
const Vector_& v2 ) {
207 return std::atan2( v1.cross( v2 ).norm(), v1.dot( v2 ) );
210 template <
typename Vector_>
211 Scalar
cotan(
const Vector_& v1,
const Vector_& v2 ) {
212 return v1.dot( v2 ) / v1.cross( v2 ).norm();
215 template <
typename Vector_>
216 Scalar
cos(
const Vector_& v1,
const Vector_& v2 ) {
217 return ( v1.dot( v2 ) ) / std::sqrt( v1.normSquared() * v2.normSquared() );
220 template <
typename Vector_>
222 const Scalar norm = v.norm();
227 template <
typename Vector_>
229 const Scalar norm = v.norm();
230 if ( norm > 0 ) { v /= norm; }
234 template <
typename Scalar>
235 Eigen::ParametrizedLine<Scalar, 3>
237 const Eigen::ParametrizedLine<Scalar, 3>& r ) {
238 return { t * r.origin(), t.linear() * r.direction() };
245 inline Quaternion
add(
const Quaternion& q1,
const Quaternion& q2 ) {
246 return Quaternion( q1.coeffs() + q2.coeffs() );
249 inline Quaternion
addQlerp(
const Quaternion& q1,
const Quaternion& q2 ) {
251 return Quaternion( q1.coeffs() + (
sign * q2.coeffs() ) );
254 inline Quaternion
scale(
const Quaternion& q, Scalar k ) {
255 return Quaternion( k * q.coeffs() );
261 Scalar
sign = std::copysign( Scalar( 1.0 ), fx( 2 ) );
262 const Scalar a = Scalar( -1.0 ) / (
sign + fx( 2 ) );
263 const Scalar b = fx( 0 ) * fx( 1 ) * a;
264 fy = Ra::Core::Vector3(
265 Scalar( 1.0 ) +
sign * fx( 0 ) * fx( 0 ) * a,
sign * b, -
sign * fx( 0 ) );
266 fz = Ra::Core::Vector3( b,
sign + fx( 1 ) * fx( 1 ) * a, -fx( 1 ) );
270 projectOnPlane(
const Vector3& planePos,
const Vector3& planeNormal,
const Vector3& point ) {
271 return point + planeNormal * ( planePos - point ).dot( planeNormal );
274 template <
typename Vector_>
275 Vector_
slerp(
const Vector_& v1,
const Vector_& v2, Scalar t ) {
276 const Scalar dot = v1.dot( v2 );
277 const Scalar theta = t *
angle( v1, v2 );
278 const Vector_ relativeVec = ( v2 - v1 * dot ).normalized();
279 return ( ( v1 * std::cos( theta ) ) + ( relativeVec * std::sin( theta ) ) );
285 inline void getSwingTwist(
const Quaternion& in, Quaternion& swingOut, Quaternion& twistOut ) {
287 if ( UNLIKELY( in.z() == 0 && in.w() == 0 ) ) {
289 swingOut.setIdentity();
292 const Scalar gamma = std::atan2( in.z(), in.w() );
295 std::atan2( in.coeffs().head<2>().norm(), in.coeffs().tail<2>().norm() );
298 const Scalar k = 2.f * beta / std::sin( beta );
302 const Vector2 sxy = k * ( Eigen::Rotation2D<Scalar>( gamma ) * in.coeffs().head<2>() );
304 AngleAxis twist( 2 * gamma, Vector3::UnitZ() );
307 Vector3 swingAxis( Vector3::Zero() );
308 swingAxis.head<2>() = sxy.normalized();
310 AngleAxis swing( sxy.norm(), swingAxis );
316 inline Matrix4 lookAt(
const Vector3& position,
const Vector3& target,
const Vector3& up ) {
318 R.col( 2 ) = ( position - target ).normalized();
319 R.col( 0 ) = up.cross( R.col( 2 ) ).normalized();
320 R.col( 1 ) = R.col( 2 ).cross( R.col( 0 ) );
322 Matrix4 result = Matrix4::Zero();
323 result.topLeftCorner<3, 3>() = R.transpose();
324 result.topRightCorner<3, 1>() = -R.transpose() * position;
325 result( 3, 3 ) = 1.0;
330 inline Matrix4 perspective( Scalar fovy, Scalar aspect, Scalar znear, Scalar zfar ) {
331 Scalar theta = fovy * 0.5f;
332 Scalar range = zfar - znear;
333 Scalar invtan = 1.f / std::tan( theta );
335 Matrix4 result = Matrix4::Zero();
336 result( 0, 0 ) = invtan / aspect;
337 result( 1, 1 ) = invtan;
338 result( 2, 2 ) = -( znear + zfar ) / range;
339 result( 3, 2 ) = -1.f;
340 result( 2, 3 ) = -2 * znear * zfar / range;
341 result( 3, 3 ) = 0.0;
346 inline Matrix4 orthographic( Scalar l, Scalar r, Scalar b, Scalar t, Scalar n, Scalar f ) {
347 Matrix4 result = Matrix4::Zero();
349 result( 0, 0 ) = 2.f / ( r - l );
350 result( 1, 1 ) = 2.f / ( t - b );
351 result( 2, 2 ) = -2.f / ( f - n );
352 result( 3, 3 ) = 1.f;
354 result( 0, 3 ) = -( r + l ) / ( r - l );
355 result( 1, 3 ) = -( t + b ) / ( t - b );
356 result( 2, 3 ) = -( f + b ) / ( f - n );
361 template <
typename Matrix_>
363 bool invalid =
false;
365 .unaryExpr( [&invalid, FAIL_ON_ASSERT]( Scalar x ) {
366 invalid |= !std::isfinite( x );
368 if ( FAIL_ON_ASSERT ) { CORE_ASSERT(
false,
"At least an element is nan" ); }
388 inline Quaternion<Scalar> operator*( Scalar k,
const Quaternion<Scalar>& q ) {
392 inline Quaternion<Scalar> operator*(
const Quaternion<Scalar>& q, Scalar k ) {
396 inline Quaternion<Scalar> operator+(
const Quaternion<Scalar>& q1,
const Quaternion<Scalar>& q2 ) {
400 inline Quaternion<Scalar> operator/(
const Quaternion<Scalar>& q, Scalar k ) {
Quaternion add(const Quaternion &q1, const Quaternion &q2)
Returns the sum of two quaternions.
Eigen::ParametrizedLine< Scalar, 3 > transformRay(const Eigen::Transform< Scalar, 3, Eigen::Affine > &t, const Eigen::ParametrizedLine< Scalar, 3 > &r)
Scalar getNormAndNormalize(Vector_ &v)
Vector floor(const Vector &v)
Component-wise floor() function on a floating-point vector.
Scalar cos(const Vector_ &v1, const Vector_ &v2)
Vector_ slerp(const Vector_ &v1, const Vector_ &v2, Scalar t)
Scalar angle(const Vector_ &v1, const Vector_ &v2)
void getOrthogonalVectors(const Vector3 &fx, Eigen::Ref< Vector3 > fy, Eigen::Ref< Vector3 > fz)
constexpr T signNZ(const T &val)
Scalar cotan(const Vector_ &v1, const Vector_ &v2)
constexpr int sign(const T &val)
Returns the sign of any numeric type as { -1, 0, 1}.
Quaternion scale(const Quaternion &q, const Scalar k)
Returns the quaternion q multipled by a scalar factor of k.
Vector trunc(const Vector &v)
Component-wise trunc() function on a floating-point vector.
void getSwingTwist(const Quaternion &in, Quaternion &swingOut, Quaternion &twistOut)
Quaternion addQlerp(const Quaternion &q1, const Quaternion &q2)
Vector3 projectOnPlane(const Vector3 &planePos, const Vector3 &planeNormal, const Vector3 &point)
Derived::PlainMatrix clamp(const Eigen::MatrixBase< Derived > &v, const Eigen::MatrixBase< DerivedA > &min, const Eigen::MatrixBase< DerivedB > &max)
Component-wise clamp() function on a floating-point vector.
Vector ceil(const Vector &v)
Component-wise ceil() function on a floating-point vector.
Scalar getNormAndNormalizeSafe(Vector_ &v)
bool checkInvalidNumbers(Eigen::Ref< Eigen::Quaternion< S >> q, const bool FAIL_ON_ASSERT=false)
Call std::isfinite on quaternion entries.