Home | History | Annotate | Download | only in gtx
      1 ///////////////////////////////////////////////////////////////////////////////////////////////////
      2 // OpenGL Mathematics Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net)
      3 ///////////////////////////////////////////////////////////////////////////////////////////////////
      4 // Created : 2005-12-21
      5 // Updated : 2008-11-27
      6 // Licence : This source is under MIT License
      7 // File    : glm/gtx/quaternion.inl
      8 ///////////////////////////////////////////////////////////////////////////////////////////////////
      9 
     10 #include <limits>
     11 
     12 namespace glm
     13 {
     14 	template <typename T, precision P>
     15 	GLM_FUNC_QUALIFIER detail::tvec3<T, P> cross
     16 	(
     17 		detail::tvec3<T, P> const & v,
     18 		detail::tquat<T, P> const & q
     19 	)
     20 	{
     21 		return inverse(q) * v;
     22 	}
     23 
     24 	template <typename T, precision P>
     25 	GLM_FUNC_QUALIFIER detail::tvec3<T, P> cross
     26 	(
     27 		detail::tquat<T, P> const & q,
     28 		detail::tvec3<T, P> const & v
     29 	)
     30 	{
     31 		return q * v;
     32 	}
     33 
     34 	template <typename T, precision P>
     35 	GLM_FUNC_QUALIFIER detail::tquat<T, P> squad
     36 	(
     37 		detail::tquat<T, P> const & q1,
     38 		detail::tquat<T, P> const & q2,
     39 		detail::tquat<T, P> const & s1,
     40 		detail::tquat<T, P> const & s2,
     41 		T const & h)
     42 	{
     43 		return mix(mix(q1, q2, h), mix(s1, s2, h), T(2) * (T(1) - h) * h);
     44 	}
     45 
     46 	template <typename T, precision P>
     47 	GLM_FUNC_QUALIFIER detail::tquat<T, P> intermediate
     48 	(
     49 		detail::tquat<T, P> const & prev,
     50 		detail::tquat<T, P> const & curr,
     51 		detail::tquat<T, P> const & next
     52 	)
     53 	{
     54 		detail::tquat<T, P> invQuat = inverse(curr);
     55 		return exp((log(next + invQuat) + log(prev + invQuat)) / T(-4)) * curr;
     56 	}
     57 
     58 	template <typename T, precision P>
     59 	GLM_FUNC_QUALIFIER detail::tquat<T, P> exp
     60 	(
     61 		detail::tquat<T, P> const & q
     62 	)
     63 	{
     64 		detail::tvec3<T, P> u(q.x, q.y, q.z);
     65 		float Angle = glm::length(u);
     66 		detail::tvec3<T, P> v(u / Angle);
     67 		return detail::tquat<T, P>(cos(Angle), sin(Angle) * v);
     68 	}
     69 
     70 	template <typename T, precision P>
     71 	GLM_FUNC_QUALIFIER detail::tquat<T, P> log
     72 	(
     73 		detail::tquat<T, P> const & q
     74 	)
     75 	{
     76 		if((q.x == static_cast<T>(0)) && (q.y == static_cast<T>(0)) && (q.z == static_cast<T>(0)))
     77 		{
     78 			if(q.w > T(0))
     79 				return detail::tquat<T, P>(log(q.w), T(0), T(0), T(0));
     80 			else if(q.w < T(0))
     81 				return detail::tquat<T, P>(log(-q.w), T(3.1415926535897932384626433832795), T(0),T(0));
     82 			else
     83 				return detail::tquat<T, P>(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity());
     84 		}
     85 		else
     86 		{
     87 			T Vec3Len = sqrt(q.x * q.x + q.y * q.y + q.z * q.z);
     88 			T QuatLen = sqrt(Vec3Len * Vec3Len + q.w * q.w);
     89 			T t = atan(Vec3Len, T(q.w)) / Vec3Len;
     90 			return detail::tquat<T, P>(t * q.x, t * q.y, t * q.z, log(QuatLen));
     91 		}
     92 	}
     93 
     94 	template <typename T, precision P>
     95 	GLM_FUNC_QUALIFIER detail::tquat<T, P> pow
     96 	(
     97 		detail::tquat<T, P> const & x,
     98 		T const & y
     99 	)
    100 	{
    101 		if(abs(x.w) > T(0.9999))
    102 			return x;
    103 		float Angle = acos(y);
    104 		float NewAngle = Angle * y;
    105 		float Div = sin(NewAngle) / sin(Angle);
    106 		return detail::tquat<T, P>(
    107 			cos(NewAngle),
    108 			x.x * Div,
    109 			x.y * Div,
    110 			x.z * Div);
    111 	}
    112 
    113 	//template <typename T, precision P>
    114 	//GLM_FUNC_QUALIFIER detail::tquat<T, P> sqrt
    115 	//(
    116 	//	detail::tquat<T, P> const & q
    117 	//)
    118 	//{
    119 	//	T q0 = static_cast<T>(1) - dot(q, q);
    120 	//	return T(2) * (T(1) + q0) * q;
    121 	//}
    122 
    123 	template <typename T, precision P>
    124 	GLM_FUNC_QUALIFIER detail::tvec3<T, P> rotate
    125 	(
    126 		detail::tquat<T, P> const & q,
    127 		detail::tvec3<T, P> const & v
    128 	)
    129 	{
    130 		return q * v;
    131 	}
    132 
    133 	template <typename T, precision P>
    134 	GLM_FUNC_QUALIFIER detail::tvec4<T, P> rotate
    135 	(
    136 		detail::tquat<T, P> const & q,
    137 		detail::tvec4<T, P> const & v
    138 	)
    139 	{
    140 		return q * v;
    141 	}
    142 
    143 	template <typename T, precision P>
    144 	GLM_FUNC_QUALIFIER T extractRealComponent
    145 	(
    146 		detail::tquat<T, P> const & q
    147 	)
    148 	{
    149 		T w = static_cast<T>(1.0) - q.x * q.x - q.y * q.y - q.z * q.z;
    150 		if(w < T(0))
    151 			return T(0);
    152 		else
    153 			return -sqrt(w);
    154 	}
    155 
    156 	template <typename T, precision P>
    157 	GLM_FUNC_QUALIFIER T length2
    158 	(
    159 		detail::tquat<T, P> const & q
    160 	)
    161 	{
    162 		return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w;
    163 	}
    164 
    165 	template <typename T, precision P>
    166 	GLM_FUNC_QUALIFIER detail::tquat<T, P> shortMix
    167 	(
    168 		detail::tquat<T, P> const & x,
    169 		detail::tquat<T, P> const & y,
    170 		T const & a
    171 	)
    172 	{
    173 		if(a <= T(0)) return x;
    174 		if(a >= T(1)) return y;
    175 
    176 		T fCos = dot(x, y);
    177 		detail::tquat<T, P> y2(y); //BUG!!! tquat<T> y2;
    178 		if(fCos < T(0))
    179 		{
    180 			y2 = -y;
    181 			fCos = -fCos;
    182 		}
    183 
    184 		//if(fCos > 1.0f) // problem
    185 		T k0, k1;
    186 		if(fCos > T(0.9999))
    187 		{
    188 			k0 = static_cast<T>(1) - a;
    189 			k1 = static_cast<T>(0) + a; //BUG!!! 1.0f + a;
    190 		}
    191 		else
    192 		{
    193 			T fSin = sqrt(T(1) - fCos * fCos);
    194 			T fAngle = atan(fSin, fCos);
    195 			T fOneOverSin = static_cast<T>(1) / fSin;
    196 			k0 = sin((T(1) - a) * fAngle) * fOneOverSin;
    197 			k1 = sin((T(0) + a) * fAngle) * fOneOverSin;
    198 		}
    199 
    200 		return detail::tquat<T, P>(
    201 			k0 * x.w + k1 * y2.w,
    202 			k0 * x.x + k1 * y2.x,
    203 			k0 * x.y + k1 * y2.y,
    204 			k0 * x.z + k1 * y2.z);
    205 	}
    206 
    207 	template <typename T, precision P>
    208 	GLM_FUNC_QUALIFIER detail::tquat<T, P> fastMix
    209 	(
    210 		detail::tquat<T, P> const & x,
    211 		detail::tquat<T, P> const & y,
    212 		T const & a
    213 	)
    214 	{
    215 		return glm::normalize(x * (T(1) - a) + (y * a));
    216 	}
    217 
    218 	template <typename T, precision P>
    219 	GLM_FUNC_QUALIFIER detail::tquat<T, P> rotation
    220 	(
    221 		detail::tvec3<T, P> const & orig,
    222 		detail::tvec3<T, P> const & dest
    223 	)
    224 	{
    225 		T cosTheta = dot(orig, dest);
    226 		detail::tvec3<T, P> rotationAxis;
    227 
    228 		if(cosTheta < T(-1) + epsilon<T>())
    229 		{
    230 			// special case when vectors in opposite directions :
    231 			// there is no "ideal" rotation axis
    232 			// So guess one; any will do as long as it's perpendicular to start
    233 			// This implementation favors a rotation around the Up axis (Y),
    234 			// since it's often what you want to do.
    235 			rotationAxis = cross(detail::tvec3<T, P>(0, 0, 1), orig);
    236 			if(length2(rotationAxis) < epsilon<T>()) // bad luck, they were parallel, try again!
    237 				rotationAxis = cross(detail::tvec3<T, P>(1, 0, 0), orig);
    238 
    239 			rotationAxis = normalize(rotationAxis);
    240 			return angleAxis(pi<T>(), rotationAxis);
    241 		}
    242 
    243 		// Implementation from Stan Melax's Game Programming Gems 1 article
    244 		rotationAxis = cross(orig, dest);
    245 
    246 		T s = sqrt((T(1) + cosTheta) * T(2));
    247 		T invs = static_cast<T>(1) / s;
    248 
    249 		return detail::tquat<T, P>(
    250 			s * T(0.5f), 
    251 			rotationAxis.x * invs,
    252 			rotationAxis.y * invs,
    253 			rotationAxis.z * invs);
    254 	}
    255 
    256 }//namespace glm
    257