3#include <Core/Math/Math.hpp>
4#include <Core/RaCore.hpp>
8#include <Eigen/Geometry>
10#include <unsupported/Eigen/AlignedVector3>
22inline void print(
const MatrixN& matrix );
35template <
typename Vector>
36inline Vector
floor(
const Vector& v );
39template <
typename Vector>
40inline Vector
ceil(
const Vector& v );
43template <
typename Vector>
44inline Vector
trunc(
const Vector& v );
48template <
typename Derived,
typename DerivedA,
typename DerivedB>
49inline typename Derived::PlainMatrix
clamp(
const Eigen::MatrixBase<Derived>& v,
50 const Eigen::MatrixBase<DerivedA>& min,
51 const Eigen::MatrixBase<DerivedB>& max );
53template <
typename Derived>
54inline typename Derived::PlainMatrix
55clamp(
const Eigen::MatrixBase<Derived>& v,
const Scalar& min,
const Scalar& max );
60 const bool FAIL_ON_ASSERT =
false ) {
66template <
typename Matrix_>
68 const bool FAIL_ON_ASSERT =
false );
77template <
typename Vector_>
78inline Scalar
angle(
const Vector_& v1,
const Vector_& v2 );
82template <
typename Vector_>
83inline Vector_
slerp(
const Vector_& v1,
const Vector_& v2, Scalar t );
87projectOnPlane(
const Vector3& planePos,
const Vector3& planeNormal,
const Vector3& point );
91template <
typename Vector_>
92inline Scalar
cotan(
const Vector_& v1,
const Vector_& v2 );
96template <
typename Vector_>
97inline Scalar
cos(
const Vector_& v1,
const Vector_& v2 );
101template <
typename Vector_>
106template <
typename Vector_>
116template <
typename Scalar>
117inline Eigen::ParametrizedLine<Scalar, 3>
118transformRay(
const Eigen::Transform<Scalar, 3, Eigen::Affine>& t,
119 const Eigen::ParametrizedLine<Scalar, 3>& r );
121inline Matrix4 lookAt(
const Vector3& position,
const Vector3& target,
const Vector3& up );
122inline Matrix4 perspective( Scalar fovy, Scalar aspect, Scalar near, Scalar zfar );
124orthographic( Scalar left, Scalar right, Scalar bottom, Scalar top, Scalar near, Scalar zfar );
136inline Quaternion
scale(
const Quaternion& q,
const Scalar k );
139inline Quaternion
add(
const Quaternion& q1,
const Quaternion& q2 );
145inline Quaternion
addQlerp(
const Quaternion& q1,
const Quaternion& q2 );
155inline void getSwingTwist(
const Quaternion& in, Quaternion& swingOut, Quaternion& twistOut );
157inline void print(
const MatrixN& matrix ) {
163 Eigen::IOFormat cleanFormat( 4, 0,
", ",
"\n",
"[",
"]" );
171template <
typename Vector_>
172inline Vector_
floor(
const Vector_& v ) {
173 using Scalar_ =
typename Vector_::Scalar;
178template <
typename Vector_>
179inline Vector_
ceil(
const Vector_& v ) {
180 using Scalar_ =
typename Vector_::Scalar;
185template <
typename Vector_>
186inline Vector_
trunc(
const Vector_& v ) {
187 using Scalar_ =
typename Vector_::Scalar;
192template <
typename Derived,
typename DerivedA,
typename DerivedB>
193inline 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 );
199template <
typename Derived>
200inline typename Derived::PlainMatrix
201clamp(
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 ); } );
205template <
typename Vector_>
206inline Scalar
angle(
const Vector_& v1,
const Vector_& v2 ) {
207 return std::atan2( v1.cross( v2 ).norm(), v1.dot( v2 ) );
210template <
typename Vector_>
211Scalar
cotan(
const Vector_& v1,
const Vector_& v2 ) {
212 return v1.dot( v2 ) / v1.cross( v2 ).norm();
215template <
typename Vector_>
216Scalar
cos(
const Vector_& v1,
const Vector_& v2 ) {
217 return ( v1.dot( v2 ) ) /
std::sqrt( v1.normSquared() * v2.normSquared() );
220template <
typename Vector_>
222 const Scalar norm = v.norm();
227template <
typename Vector_>
229 const Scalar norm = v.norm();
230 if ( norm > 0 ) { v /= norm; }
234template <
typename Scalar>
235Eigen::ParametrizedLine<Scalar, 3>
237 const Eigen::ParametrizedLine<Scalar, 3>& r ) {
238 return { t * r.origin(), t.linear() * r.direction() };
245inline Quaternion
add(
const Quaternion& q1,
const Quaternion& q2 ) {
246 return Quaternion( q1.coeffs() + q2.coeffs() );
249inline Quaternion
addQlerp(
const Quaternion& q1,
const Quaternion& q2 ) {
251 return Quaternion( q1.coeffs() + (
sign * q2.coeffs() ) );
254inline Quaternion
scale(
const Quaternion& q, Scalar k ) {
255 return Quaternion( k * q.coeffs() );
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 ) );
270projectOnPlane(
const Vector3& planePos,
const Vector3& planeNormal,
const Vector3& point ) {
271 return point + planeNormal * ( planePos - point ).dot( planeNormal );
274template <
typename Vector_>
275Vector_
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 ) ) );
285inline 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 );
316inline 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;
330inline 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;
346inline 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 );
361template <
typename Matrix_>
363 bool invalid =
false;
365 .unaryExpr( [&invalid, FAIL_ON_ASSERT]( Scalar x ) {
368 if ( FAIL_ON_ASSERT ) { CORE_ASSERT(
false,
"At least an element is nan" ); }
391template <
typename DerivedA,
typename DerivedB>
393 const Eigen::DenseBase<DerivedB>& b,
394 const typename DerivedA::RealScalar& rtol =
395 Eigen::NumTraits<typename DerivedA::RealScalar>::dummy_precision(),
396 const typename DerivedA::RealScalar& atol =
397 Eigen::NumTraits<typename DerivedA::RealScalar>::epsilon() ) {
399 return ( ( a.derived() - b.derived() ).array().abs() <=
400 ( atol + rtol * a.derived().array().abs().max( b.derived().array().abs() ) ) )
415inline Quaternion<Scalar>
operator*( Scalar k,
const Quaternion<Scalar>& q ) {
419inline Quaternion<Scalar>
operator*(
const Quaternion<Scalar>& q, Scalar k ) {
423inline Quaternion<Scalar> operator+(
const Quaternion<Scalar>& q1,
const Quaternion<Scalar>& q2 ) {
427inline 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.
bool checkInvalidNumbers(Eigen::Ref< Eigen::Quaternion< S > > q, const bool FAIL_ON_ASSERT=false)
Call std::isfinite on quaternion entries.
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)
bool allClose(const Eigen::DenseBase< DerivedA > &a, const Eigen::DenseBase< DerivedB > &b, const typename DerivedA::RealScalar &rtol=Eigen::NumTraits< typename DerivedA::RealScalar >::dummy_precision(), const typename DerivedA::RealScalar &atol=Eigen::NumTraits< typename DerivedA::RealScalar >::epsilon())
Returns True if two arrays are element-wise equal within a tolerance.
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)
DualQuaternion operator*(Scalar scalar, const DualQuaternion &dq)
Pre-multiplication of dual quaternion.
hepler function to manage enum as underlying types in VariableSet