X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Fpublic-api%2Fmath%2Fquaternion.cpp;h=853cb09aaa3019b5c4b40ae04f9cf8384401ef84;hb=646f736e77b085c86e982c0d1d4b895c2a431330;hp=167f51aea91a639a2fa52113dcebd9a2bda6f9cb;hpb=33a1cfeac36d2573f106567ba8a36ed5133b59f6;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/public-api/math/quaternion.cpp b/dali/public-api/math/quaternion.cpp index 167f51a..853cb09 100644 --- a/dali/public-api/math/quaternion.cpp +++ b/dali/public-api/math/quaternion.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2018 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,9 @@ // CLASS HEADER #include +// EXTERNAL INCLUDES +#include + // INTERNAL INCLUDES #include #include @@ -37,27 +40,27 @@ const Quaternion Quaternion::IDENTITY; * Default Constructor */ Quaternion::Quaternion() - : mVector(0.0f, 0.0f, 0.0f, 1.0f) +: mVector( 0.0f, 0.0f, 0.0f, 1.0f ) { } -Quaternion::Quaternion(float cosThetaBy2, float iBySineTheta, float jBySineTheta, float kBySineTheta) : - mVector(iBySineTheta, jBySineTheta, kBySineTheta, cosThetaBy2) +Quaternion::Quaternion( float cosThetaBy2, float iBySineTheta, float jBySineTheta, float kBySineTheta ) +: mVector( iBySineTheta, jBySineTheta, kBySineTheta, cosThetaBy2 ) { } -Quaternion::Quaternion(const Vector4& vector) +Quaternion::Quaternion( const Vector4& vector ) +: mVector( vector ) { - mVector = vector; } -Quaternion::Quaternion(float angle, const Vector3 &axis) +Quaternion::Quaternion( Radian angle, const Vector3& axis ) { MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,4); Vector3 tmpAxis = axis; tmpAxis.Normalize(); - const float halfAngle = angle * 0.5f; + const float halfAngle = angle.radian * 0.5f; const float sinThetaByTwo = sinf(halfAngle); const float cosThetaByTwo = cosf(halfAngle); mVector.x = tmpAxis.x * sinThetaByTwo; @@ -66,27 +69,12 @@ Quaternion::Quaternion(float angle, const Vector3 &axis) mVector.w = cosThetaByTwo; } -Quaternion::Quaternion(float theta, const Vector4 &axis) -{ - MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,4); - - Vector4 tmpAxis = axis; - tmpAxis.Normalize(); - const float halfTheta = theta * 0.5f; - const float sinThetaByTwo = sinf(halfTheta); - const float cosThetaByTwo = cosf(halfTheta); - mVector.x = tmpAxis.x * sinThetaByTwo; - mVector.y = tmpAxis.y * sinThetaByTwo; - mVector.z = tmpAxis.z * sinThetaByTwo; - mVector.w = cosThetaByTwo; -} - -Quaternion::Quaternion(float x, float y, float z) +Quaternion::Quaternion( Radian pitch, Radian yaw, Radian roll ) { - SetEuler(x,y,z); + SetEuler( pitch, yaw, roll ); } -Quaternion::Quaternion(const Matrix& matrix) +Quaternion::Quaternion( const Matrix& matrix ) { Vector3 xAxis( matrix.GetXAxis() ); Vector3 yAxis( matrix.GetYAxis() ); @@ -126,21 +114,26 @@ Quaternion::Quaternion( const Vector3& v0, const Vector3& v1 ) } } -Quaternion Quaternion::FromAxisAngle(const Vector4 &axis, float angle) +Quaternion::~Quaternion() { - return Quaternion(angle, axis); } -Quaternion::~Quaternion() +bool Quaternion::IsIdentity() const { + // start from w as its unlikely that any real rotation has w == 1 + // Uses a relaxed epsilon, as composition of rotation introduces error + return ( ( fabsf( mVector.w - 1.0f ) < Math::MACHINE_EPSILON_10 )&& + ( fabsf( mVector.x ) < Math::MACHINE_EPSILON_10 )&& + ( fabsf( mVector.y ) < Math::MACHINE_EPSILON_10 )&& + ( fabsf( mVector.z ) < Math::MACHINE_EPSILON_10 ) ); } -bool Quaternion::ToAxisAngle(Vector3 &axis, float &angle) const +bool Quaternion::ToAxisAngle(Vector3& axis, Radian& angle) const { angle = acosf(mVector.w); bool converted = false; // pre-compute to save time - const float sine = sinf( angle ); + const float sine = sinf( angle.radian ); // If sine(angle) is zero, conversion is not possible @@ -153,38 +146,24 @@ bool Quaternion::ToAxisAngle(Vector3 &axis, float &angle) const axis.x = mVector.x*sinf_theta_inv; axis.y = mVector.y*sinf_theta_inv; axis.z = mVector.z*sinf_theta_inv; - angle*=2.0f; + angle.radian *= 2.0f; converted = true; } return converted; } -bool Quaternion::ToAxisAngle(Vector4 &axis, float &angle) const -{ - Vector3 axis3; - bool converted = ToAxisAngle(axis3, angle); - if(converted) - { - axis.x = axis3.x; - axis.y = axis3.y; - axis.z = axis3.z; - axis.w = 0; - } - return converted; -} - const Vector4& Quaternion::AsVector() const { return mVector; } -void Quaternion::SetEuler(float x, float y, float z) +void Quaternion::SetEuler( Radian pitch, Radian yaw, Radian roll ) { MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,19); - const float halfX = 0.5f * x; - const float halfY = 0.5f * y; - const float halfZ = 0.5f * z; + const float halfX = 0.5f * pitch.radian; + const float halfY = 0.5f * yaw.radian; + const float halfZ = 0.5f * roll.radian; float cosX2 = cosf(halfX); float cosY2 = cosf(halfY); @@ -216,17 +195,17 @@ Vector4 Quaternion::EulerAngles() const return euler; } -const Quaternion Quaternion::operator +(const Quaternion &other) const +const Quaternion Quaternion::operator+( const Quaternion& other ) const { return Quaternion(mVector + other.mVector); } -const Quaternion Quaternion::operator -(const Quaternion &other) const +const Quaternion Quaternion::operator-( const Quaternion& other ) const { return Quaternion(mVector - other.mVector); } -const Quaternion Quaternion::operator *(const Quaternion &other) const +const Quaternion Quaternion::operator*( const Quaternion& other ) const { MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,12); @@ -236,52 +215,50 @@ const Quaternion Quaternion::operator *(const Quaternion &other) const mVector.x * other.mVector.y - mVector.y * other.mVector.x + mVector.w * other.mVector.z + mVector.z * other.mVector.w); } -Vector3 Quaternion::operator *(const Vector3& v) const +Vector3 Quaternion::operator*( const Vector3& other ) const { - // nVidia SDK implementation - Vector3 uv, uuv; Vector3 qvec(mVector.x, mVector.y, mVector.z); - uv = qvec.Cross(v); - uuv = qvec.Cross(uv); + Vector3 uv = qvec.Cross( other ); + Vector3 uuv = qvec.Cross(uv); uv *= (2.0f * mVector.w); uuv *= 2.0f; - return v + uv + uuv; + return other + uv + uuv; } -const Quaternion Quaternion::operator /(const Quaternion &q) const +const Quaternion Quaternion::operator/( const Quaternion& q ) const { Quaternion p(q); p.Invert(); return *this * p; } -const Quaternion Quaternion::operator *(float scale) const +const Quaternion Quaternion::operator*( float scale ) const { return Quaternion(mVector*scale); } -const Quaternion Quaternion::operator /(float scale) const +const Quaternion Quaternion::operator/( float scale ) const { return Quaternion(mVector/scale); } -Quaternion Quaternion::operator -() const +Quaternion Quaternion::operator-() const { return Quaternion(-mVector.w, -mVector.x, -mVector.y, -mVector.z); } -const Quaternion& Quaternion::operator +=(const Quaternion &q) +const Quaternion& Quaternion::operator+=( const Quaternion& q ) { mVector += q.mVector; return *this; } -const Quaternion& Quaternion::operator -=(const Quaternion &q) +const Quaternion& Quaternion::operator-=( const Quaternion& q ) { mVector -= q.mVector; return *this; } -const Quaternion& Quaternion::operator *=(const Quaternion &q) +const Quaternion& Quaternion::operator*=( const Quaternion& q ) { MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,12); @@ -294,17 +271,17 @@ const Quaternion& Quaternion::operator *=(const Quaternion &q) return *this; } -const Quaternion& Quaternion::operator *= (float scale) +const Quaternion& Quaternion::operator*=( float scale ) { mVector*=scale; return *this; } -const Quaternion& Quaternion::operator /= (float scale) +const Quaternion& Quaternion::operator/=( float scale ) { mVector/=scale; return *this; } -bool Quaternion::operator== (const Quaternion& rhs) const +bool Quaternion::operator==( const Quaternion& rhs ) const { return ( ( fabsf(mVector.x - rhs.mVector.x) < Math::MACHINE_EPSILON_1 && fabsf(mVector.y - rhs.mVector.y) < Math::MACHINE_EPSILON_1 && @@ -318,19 +295,19 @@ bool Quaternion::operator== (const Quaternion& rhs) const ); } -bool Quaternion::operator!= (const Quaternion& rhs) const +bool Quaternion::operator!=( const Quaternion& rhs ) const { return !operator==(rhs); } float Quaternion::Length() const { - return (float)sqrt(mVector.w * mVector.w + mVector.Dot(mVector)); + return static_cast< float >( sqrt(mVector.w * mVector.w + mVector.Dot(mVector) ) ); } float Quaternion::LengthSquared() const { - return (float)(mVector.w * mVector.w + mVector.Dot(mVector)); + return static_cast< float >( mVector.w * mVector.w + mVector.Dot(mVector) ); } void Quaternion::Normalize() @@ -405,17 +382,17 @@ Quaternion Quaternion::Exp() const return ret; } -float Quaternion::Dot(const Quaternion &q1, const Quaternion &q2) +float Quaternion::Dot( const Quaternion& q1, const Quaternion& q2 ) { return q1.mVector.Dot4(q2.mVector); } -Quaternion Quaternion::Lerp(const Quaternion &q1, const Quaternion &q2, float t) +Quaternion Quaternion::Lerp(const Quaternion& q1, const Quaternion& q2, float t ) { return (q1*(1.0f-t) + q2*t).Normalized(); } -Quaternion Quaternion::Slerp(const Quaternion &q1, const Quaternion &q2, float progress) +Quaternion Quaternion::Slerp( const Quaternion& q1, const Quaternion& q2, float progress ) { Quaternion q3; float cosTheta = Quaternion::Dot(q1, q2); @@ -456,7 +433,7 @@ Quaternion Quaternion::Slerp(const Quaternion &q1, const Quaternion &q2, float p } } -Quaternion Quaternion::SlerpNoInvert(const Quaternion &q1, const Quaternion &q2, float t) +Quaternion Quaternion::SlerpNoInvert( const Quaternion& q1, const Quaternion& q2, float t ) { float cosTheta = Quaternion::Dot(q1, q2); @@ -473,21 +450,16 @@ Quaternion Quaternion::SlerpNoInvert(const Quaternion &q1, const Quaternion &q2, } } -Quaternion Quaternion::Squad( - const Quaternion &q1, // start - const Quaternion &q2, // end - const Quaternion &a, // ctrl pt for q1 - const Quaternion &b, // ctrl pt for q2 - float t) +Quaternion Quaternion::Squad( const Quaternion& start, const Quaternion& end, const Quaternion& ctrl1, const Quaternion& ctrl2, float t ) { MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,2); - Quaternion c = SlerpNoInvert(q1, q2, t); - Quaternion d = SlerpNoInvert(a, b, t); - return SlerpNoInvert(c, d, 2*t*(1-t)); + Quaternion c = SlerpNoInvert( start, end, t ); + Quaternion d = SlerpNoInvert( ctrl1, ctrl2, t ); + return SlerpNoInvert( c, d, 2*t*(1-t) ); } -float Quaternion::AngleBetween(const Quaternion &q1, const Quaternion &q2) +float Quaternion::AngleBetween( const Quaternion& q1, const Quaternion& q2 ) { Quaternion from(q1); Quaternion to(q2); @@ -498,22 +470,22 @@ float Quaternion::AngleBetween(const Quaternion &q1, const Quaternion &q2) //Formula for angle θ between two quaternion is: //θ = cos^−1 (2⟨q1,q2⟩^2 − 1), Where (q1,q2) is inner product of the quaternions. float X = from.mVector.Dot4(to.mVector); - float theta = acos( (2 * X * X) - 1); + float theta = acosf( (2 * X * X) - 1); // float arc cosine return theta; } -Vector4 Quaternion::Rotate(const Vector4 &v) const +Vector4 Quaternion::Rotate( const Vector4& vector ) const { - Quaternion V(0.0f, v.x, v.y, v.z); + Quaternion V(0.0f, vector.x, vector.y, vector.z); Quaternion conjugate(*this); conjugate.Conjugate(); return (*this * V * conjugate).mVector; } -Vector3 Quaternion::Rotate(const Vector3 &v) const +Vector3 Quaternion::Rotate( const Vector3& vector ) const { - Quaternion V(0.0f, v.x, v.y, v.z); + Quaternion V(0.0f, vector.x, vector.y, vector.z); Quaternion conjugate(*this); conjugate.Conjugate(); return Vector3((*this * V * conjugate).mVector); @@ -565,16 +537,15 @@ void Quaternion::SetFromAxes( const Vector3& xAxis, const Vector3& yAxis, const Normalize(); } -std::ostream& operator<< (std::ostream& o, const Quaternion& quaternion) +std::ostream& operator<<( std::ostream& o, const Quaternion& quaternion ) { Vector3 axis; - float angleRadians; + Radian angleRadians; quaternion.ToAxisAngle( axis, angleRadians ); - Degree degrees = Radian(angleRadians); + Degree degrees( angleRadians ); - return o << "[ Axis: [" << axis.x << ", " << axis.y << ", " << axis.z << "], Angle: " << degrees << " degrees ]"; + return o << "[ Axis: [" << axis.x << ", " << axis.y << ", " << axis.z << "], Angle: " << degrees.degree << " degrees ]"; } } // namespace Dali -