1 /////////////////////////////////////////////////////////////////////////////////// 2 /// OpenGL Mathematics (glm.g-truc.net) 3 /// 4 /// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) 5 /// Permission is hereby granted, free of charge, to any person obtaining a copy 6 /// of this software and associated documentation files (the "Software"), to deal 7 /// in the Software without restriction, including without limitation the rights 8 /// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 /// copies of the Software, and to permit persons to whom the Software is 10 /// furnished to do so, subject to the following conditions: 11 /// 12 /// The above copyright notice and this permission notice shall be included in 13 /// all copies or substantial portions of the Software. 14 /// 15 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 /// THE SOFTWARE. 22 /// 23 /// @ref gtx_simd_quat 24 /// @file glm/gtx/simd_quat.hpp 25 /// @date 2009-05-07 / 2011-06-07 26 /// @author Christophe Riccio 27 /// 28 /// @see core (dependence) 29 /// 30 /// @defgroup gtx_simd_vec4 GLM_GTX_simd_quat 31 /// @ingroup gtx 32 /// 33 /// @brief SIMD implementation of quat type. 34 /// 35 /// <glm/gtx/simd_quat.hpp> need to be included to use these functionalities. 36 /////////////////////////////////////////////////////////////////////////////////// 37 38 #ifndef GLM_GTX_simd_quat 39 #define GLM_GTX_simd_quat 40 41 // Dependency: 42 #include "../glm.hpp" 43 #include "../gtc/quaternion.hpp" 44 #include "../gtx/fast_trigonometry.hpp" 45 46 #if(GLM_ARCH != GLM_ARCH_PURE) 47 48 #if(GLM_ARCH & GLM_ARCH_SSE2) 49 # include "../gtx/simd_mat4.hpp" 50 #else 51 # error "GLM: GLM_GTX_simd_quat requires compiler support of SSE2 through intrinsics" 52 #endif 53 54 #if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) 55 # pragma message("GLM: GLM_GTX_simd_quat extension included") 56 #endif 57 58 59 // Warning silencer for nameless struct/union. 60 #if (GLM_COMPILER & GLM_COMPILER_VC) 61 # pragma warning(push) 62 # pragma warning(disable:4201) // warning C4201: nonstandard extension used : nameless struct/union 63 #endif 64 65 66 namespace glm{ 67 namespace detail 68 { 69 /// Quaternion implemented using SIMD SEE intrinsics. 70 /// \ingroup gtx_simd_vec4 71 GLM_ALIGNED_STRUCT(16) fquatSIMD 72 { 73 enum ctor{null}; 74 typedef __m128 value_type; 75 typedef std::size_t size_type; 76 static size_type value_size(); 77 78 typedef fquatSIMD type; 79 typedef tquat<bool, defaultp> bool_type; 80 81 #ifdef GLM_SIMD_ENABLE_XYZW_UNION 82 union 83 { 84 __m128 Data; 85 struct {float x, y, z, w;}; 86 }; 87 #else 88 __m128 Data; 89 #endif 90 91 ////////////////////////////////////// 92 // Implicit basic constructors 93 94 fquatSIMD(); 95 fquatSIMD(__m128 const & Data); 96 fquatSIMD(fquatSIMD const & q); 97 98 ////////////////////////////////////// 99 // Explicit basic constructors 100 101 explicit fquatSIMD( 102 ctor); 103 explicit fquatSIMD( 104 float const & w, 105 float const & x, 106 float const & y, 107 float const & z); 108 explicit fquatSIMD( 109 quat const & v); 110 explicit fquatSIMD( 111 vec3 const & eulerAngles); 112 113 114 ////////////////////////////////////// 115 // Unary arithmetic operators 116 117 fquatSIMD& operator =(fquatSIMD const & q); 118 fquatSIMD& operator*=(float const & s); 119 fquatSIMD& operator/=(float const & s); 120 }; 121 122 123 ////////////////////////////////////// 124 // Arithmetic operators 125 126 detail::fquatSIMD operator- ( 127 detail::fquatSIMD const & q); 128 129 detail::fquatSIMD operator+ ( 130 detail::fquatSIMD const & q, 131 detail::fquatSIMD const & p); 132 133 detail::fquatSIMD operator* ( 134 detail::fquatSIMD const & q, 135 detail::fquatSIMD const & p); 136 137 detail::fvec4SIMD operator* ( 138 detail::fquatSIMD const & q, 139 detail::fvec4SIMD const & v); 140 141 detail::fvec4SIMD operator* ( 142 detail::fvec4SIMD const & v, 143 detail::fquatSIMD const & q); 144 145 detail::fquatSIMD operator* ( 146 detail::fquatSIMD const & q, 147 float s); 148 149 detail::fquatSIMD operator* ( 150 float s, 151 detail::fquatSIMD const & q); 152 153 detail::fquatSIMD operator/ ( 154 detail::fquatSIMD const & q, 155 float s); 156 157 }//namespace detail 158 159 typedef glm::detail::fquatSIMD simdQuat; 160 161 /// @addtogroup gtx_simd_quat 162 /// @{ 163 164 //! Convert a simdQuat to a quat. 165 //! (From GLM_GTX_simd_quat extension) 166 quat quat_cast( 167 detail::fquatSIMD const & x); 168 169 //! Convert a simdMat4 to a simdQuat. 170 //! (From GLM_GTX_simd_quat extension) 171 detail::fquatSIMD quatSIMD_cast( 172 detail::fmat4x4SIMD const & m); 173 174 //! Converts a mat4 to a simdQuat. 175 //! (From GLM_GTX_simd_quat extension) 176 template <typename T, precision P> 177 detail::fquatSIMD quatSIMD_cast( 178 detail::tmat4x4<T, P> const & m); 179 180 //! Converts a mat3 to a simdQuat. 181 //! (From GLM_GTX_simd_quat extension) 182 template <typename T, precision P> 183 detail::fquatSIMD quatSIMD_cast( 184 detail::tmat3x3<T, P> const & m); 185 186 //! Convert a simdQuat to a simdMat4 187 //! (From GLM_GTX_simd_quat extension) 188 detail::fmat4x4SIMD mat4SIMD_cast( 189 detail::fquatSIMD const & q); 190 191 //! Converts a simdQuat to a standard mat4. 192 //! (From GLM_GTX_simd_quat extension) 193 mat4 mat4_cast( 194 detail::fquatSIMD const & q); 195 196 197 /// Returns the length of the quaternion. 198 /// 199 /// @see gtc_quaternion 200 float length( 201 detail::fquatSIMD const & x); 202 203 /// Returns the normalized quaternion. 204 /// 205 /// @see gtc_quaternion 206 detail::fquatSIMD normalize( 207 detail::fquatSIMD const & x); 208 209 /// Returns dot product of q1 and q2, i.e., q1[0] * q2[0] + q1[1] * q2[1] + ... 210 /// 211 /// @see gtc_quaternion 212 float dot( 213 detail::fquatSIMD const & q1, 214 detail::fquatSIMD const & q2); 215 216 /// Spherical linear interpolation of two quaternions. 217 /// The interpolation is oriented and the rotation is performed at constant speed. 218 /// For short path spherical linear interpolation, use the slerp function. 219 /// 220 /// @param x A quaternion 221 /// @param y A quaternion 222 /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. 223 /// @tparam T Value type used to build the quaternion. Supported: half, float or double. 224 /// @see gtc_quaternion 225 /// @see - slerp(detail::fquatSIMD const & x, detail::fquatSIMD const & y, T const & a) 226 detail::fquatSIMD mix( 227 detail::fquatSIMD const & x, 228 detail::fquatSIMD const & y, 229 float const & a); 230 231 /// Linear interpolation of two quaternions. 232 /// The interpolation is oriented. 233 /// 234 /// @param x A quaternion 235 /// @param y A quaternion 236 /// @param a Interpolation factor. The interpolation is defined in the range [0, 1]. 237 /// @tparam T Value type used to build the quaternion. Supported: half, float or double. 238 /// @see gtc_quaternion 239 detail::fquatSIMD lerp( 240 detail::fquatSIMD const & x, 241 detail::fquatSIMD const & y, 242 float const & a); 243 244 /// Spherical linear interpolation of two quaternions. 245 /// The interpolation always take the short path and the rotation is performed at constant speed. 246 /// 247 /// @param x A quaternion 248 /// @param y A quaternion 249 /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. 250 /// @tparam T Value type used to build the quaternion. Supported: half, float or double. 251 /// @see gtc_quaternion 252 detail::fquatSIMD slerp( 253 detail::fquatSIMD const & x, 254 detail::fquatSIMD const & y, 255 float const & a); 256 257 258 /// Faster spherical linear interpolation of two unit length quaternions. 259 /// 260 /// This is the same as mix(), except for two rules: 261 /// 1) The two quaternions must be unit length. 262 /// 2) The interpolation factor (a) must be in the range [0, 1]. 263 /// 264 /// This will use the equivalent to fastAcos() and fastSin(). 265 /// 266 /// @see gtc_quaternion 267 /// @see - mix(detail::fquatSIMD const & x, detail::fquatSIMD const & y, T const & a) 268 detail::fquatSIMD fastMix( 269 detail::fquatSIMD const & x, 270 detail::fquatSIMD const & y, 271 float const & a); 272 273 /// Identical to fastMix() except takes the shortest path. 274 /// 275 /// The same rules apply here as those in fastMix(). Both quaternions must be unit length and 'a' must be 276 /// in the range [0, 1]. 277 /// 278 /// @see - fastMix(detail::fquatSIMD const & x, detail::fquatSIMD const & y, T const & a) 279 /// @see - slerp(detail::fquatSIMD const & x, detail::fquatSIMD const & y, T const & a) 280 detail::fquatSIMD fastSlerp( 281 detail::fquatSIMD const & x, 282 detail::fquatSIMD const & y, 283 float const & a); 284 285 286 /// Returns the q conjugate. 287 /// 288 /// @see gtc_quaternion 289 detail::fquatSIMD conjugate( 290 detail::fquatSIMD const & q); 291 292 /// Returns the q inverse. 293 /// 294 /// @see gtc_quaternion 295 detail::fquatSIMD inverse( 296 detail::fquatSIMD const & q); 297 298 /// Build a quaternion from an angle and a normalized axis. 299 /// 300 /// @param angle Angle expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise. 301 /// @param axis Axis of the quaternion, must be normalized. 302 /// 303 /// @see gtc_quaternion 304 detail::fquatSIMD angleAxisSIMD( 305 float const & angle, 306 vec3 const & axis); 307 308 /// Build a quaternion from an angle and a normalized axis. 309 /// 310 /// @param angle Angle expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise. 311 /// @param x x component of the x-axis, x, y, z must be a normalized axis 312 /// @param y y component of the y-axis, x, y, z must be a normalized axis 313 /// @param z z component of the z-axis, x, y, z must be a normalized axis 314 /// 315 /// @see gtc_quaternion 316 detail::fquatSIMD angleAxisSIMD( 317 float const & angle, 318 float const & x, 319 float const & y, 320 float const & z); 321 322 323 // TODO: Move this to somewhere more appropriate. Used with fastMix() and fastSlerp(). 324 /// Performs the equivalent of glm::fastSin() on each component of the given __m128. 325 __m128 fastSin(__m128 x); 326 327 328 /// @} 329 }//namespace glm 330 331 #include "simd_quat.inl" 332 333 334 #if (GLM_COMPILER & GLM_COMPILER_VC) 335 # pragma warning(pop) 336 #endif 337 338 339 #endif//(GLM_ARCH != GLM_ARCH_PURE) 340 341 #endif//GLM_GTX_simd_quat 342