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 gtc_quaternion 24/// @file glm/gtc/quaternion.inl 25/// @date 2009-05-21 / 2011-06-15 26/// @author Christophe Riccio 27/////////////////////////////////////////////////////////////////////////////////// 28 29#include "../trigonometric.hpp" 30#include "../geometric.hpp" 31#include "../exponential.hpp" 32#include <limits> 33 34namespace glm{ 35namespace detail 36{ 37 template <typename T, precision P> 38 GLM_FUNC_QUALIFIER GLM_CONSTEXPR length_t tquat<T, P>::length() const 39 { 40 return 4; 41 } 42 43 template <typename T, precision P> 44 GLM_FUNC_QUALIFIER tquat<T, P>::tquat() : 45 x(0), 46 y(0), 47 z(0), 48 w(1) 49 {} 50 51 template <typename T, precision P> 52 template <typename U, precision Q> 53 GLM_FUNC_QUALIFIER tquat<T, P>::tquat 54 ( 55 tquat<U, Q> const & q 56 ) : 57 x(q.x), 58 y(q.y), 59 z(q.z), 60 w(q.w) 61 {} 62 63 template <typename T, precision P> 64 GLM_FUNC_QUALIFIER tquat<T, P>::tquat 65 ( 66 T const & s, 67 tvec3<T, P> const & v 68 ) : 69 x(v.x), 70 y(v.y), 71 z(v.z), 72 w(s) 73 {} 74 75 template <typename T, precision P> 76 GLM_FUNC_QUALIFIER tquat<T, P>::tquat 77 ( 78 T const & w, 79 T const & x, 80 T const & y, 81 T const & z 82 ) : 83 x(x), 84 y(y), 85 z(z), 86 w(w) 87 {} 88 89 ////////////////////////////////////////////////////////////// 90 // tquat conversions 91 92 //template <typename valType> 93 //GLM_FUNC_QUALIFIER tquat<valType>::tquat 94 //( 95 // valType const & pitch, 96 // valType const & yaw, 97 // valType const & roll 98 //) 99 //{ 100 // tvec3<valType> eulerAngle(pitch * valType(0.5), yaw * valType(0.5), roll * valType(0.5)); 101 // tvec3<valType> c = glm::cos(eulerAngle * valType(0.5)); 102 // tvec3<valType> s = glm::sin(eulerAngle * valType(0.5)); 103 // 104 // this->w = c.x * c.y * c.z + s.x * s.y * s.z; 105 // this->x = s.x * c.y * c.z - c.x * s.y * s.z; 106 // this->y = c.x * s.y * c.z + s.x * c.y * s.z; 107 // this->z = c.x * c.y * s.z - s.x * s.y * c.z; 108 //} 109 110 template <typename T, precision P> 111 GLM_FUNC_QUALIFIER tquat<T, P>::tquat 112 ( 113 detail::tvec3<T, P> const & u, 114 detail::tvec3<T, P> const & v 115 ) 116 { 117 detail::tvec3<T, P> w = cross(u, v); 118 T Dot = detail::compute_dot<detail::tvec3, T, P>::call(u, v); 119 detail::tquat<T, P> q(T(1) + Dot, w.x, w.y, w.z); 120 121 *this = normalize(q); 122 } 123 124 template <typename T, precision P> 125 GLM_FUNC_QUALIFIER tquat<T, P>::tquat 126 ( 127 tvec3<T, P> const & eulerAngle 128 ) 129 { 130 tvec3<T, P> c = glm::cos(eulerAngle * T(0.5)); 131 tvec3<T, P> s = glm::sin(eulerAngle * T(0.5)); 132 133 this->w = c.x * c.y * c.z + s.x * s.y * s.z; 134 this->x = s.x * c.y * c.z - c.x * s.y * s.z; 135 this->y = c.x * s.y * c.z + s.x * c.y * s.z; 136 this->z = c.x * c.y * s.z - s.x * s.y * c.z; 137 } 138 139 template <typename T, precision P> 140 GLM_FUNC_QUALIFIER tquat<T, P>::tquat 141 ( 142 tmat3x3<T, P> const & m 143 ) 144 { 145 *this = quat_cast(m); 146 } 147 148 template <typename T, precision P> 149 GLM_FUNC_QUALIFIER tquat<T, P>::tquat 150 ( 151 tmat4x4<T, P> const & m 152 ) 153 { 154 *this = quat_cast(m); 155 } 156 157 ////////////////////////////////////////////////////////////// 158 // tquat<T, P> accesses 159 160 template <typename T, precision P> 161 GLM_FUNC_QUALIFIER T & tquat<T, P>::operator[] (length_t i) 162 { 163 assert(i >= 0 && i < this->length()); 164 return (&x)[i]; 165 } 166 167 template <typename T, precision P> 168 GLM_FUNC_QUALIFIER T const & tquat<T, P>::operator[] (length_t i) const 169 { 170 assert(i >= 0 && i < this->length()); 171 return (&x)[i]; 172 } 173}//namespace detail 174 175 template <typename T, precision P> 176 GLM_FUNC_QUALIFIER detail::tquat<T, P> conjugate 177 ( 178 detail::tquat<T, P> const & q 179 ) 180 { 181 return detail::tquat<T, P>(q.w, -q.x, -q.y, -q.z); 182 } 183 184 template <typename T, precision P> 185 GLM_FUNC_QUALIFIER detail::tquat<T, P> inverse 186 ( 187 detail::tquat<T, P> const & q 188 ) 189 { 190 return conjugate(q) / dot(q, q); 191 } 192 193namespace detail 194{ 195 ////////////////////////////////////////////////////////////// 196 // tquat<valType> operators 197 198 template <typename T, precision P> 199 GLM_FUNC_QUALIFIER tquat<T, P> & tquat<T, P>::operator += 200 ( 201 tquat<T, P> const & q 202 ) 203 { 204 this->w += q.w; 205 this->x += q.x; 206 this->y += q.y; 207 this->z += q.z; 208 return *this; 209 } 210 211 template <typename T, precision P> 212 GLM_FUNC_QUALIFIER tquat<T, P> & tquat<T, P>::operator *= 213 ( 214 tquat<T, P> const & q 215 ) 216 { 217 tquat<T, P> const p(*this); 218 219 this->w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z; 220 this->x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y; 221 this->y = p.w * q.y + p.y * q.w + p.z * q.x - p.x * q.z; 222 this->z = p.w * q.z + p.z * q.w + p.x * q.y - p.y * q.x; 223 return *this; 224 } 225 226 template <typename T, precision P> 227 GLM_FUNC_QUALIFIER tquat<T, P> & tquat<T, P>::operator *= 228 ( 229 T const & s 230 ) 231 { 232 this->w *= s; 233 this->x *= s; 234 this->y *= s; 235 this->z *= s; 236 return *this; 237 } 238 239 template <typename T, precision P> 240 GLM_FUNC_QUALIFIER tquat<T, P> & tquat<T, P>::operator /= 241 ( 242 T const & s 243 ) 244 { 245 this->w /= s; 246 this->x /= s; 247 this->y /= s; 248 this->z /= s; 249 return *this; 250 } 251 252 ////////////////////////////////////////////////////////////// 253 // tquat<T, P> external functions 254 255 template <typename T, precision P> 256 struct compute_dot<tquat, T, P> 257 { 258 static T call(tquat<T, P> const & x, tquat<T, P> const & y) 259 { 260 tvec4<T, P> tmp(x.x * y.x, x.y * y.y, x.z * y.z, x.w * y.w); 261 return (tmp.x + tmp.y) + (tmp.z + tmp.w); 262 } 263 }; 264 265 ////////////////////////////////////////////////////////////// 266 // tquat<T, P> external operators 267 268 template <typename T, precision P> 269 GLM_FUNC_QUALIFIER detail::tquat<T, P> operator- 270 ( 271 detail::tquat<T, P> const & q 272 ) 273 { 274 return detail::tquat<T, P>(-q.w, -q.x, -q.y, -q.z); 275 } 276 277 template <typename T, precision P> 278 GLM_FUNC_QUALIFIER detail::tquat<T, P> operator+ 279 ( 280 detail::tquat<T, P> const & q, 281 detail::tquat<T, P> const & p 282 ) 283 { 284 return detail::tquat<T, P>(q) += p; 285 } 286 287 template <typename T, precision P> 288 GLM_FUNC_QUALIFIER detail::tquat<T, P> operator* 289 ( 290 detail::tquat<T, P> const & q, 291 detail::tquat<T, P> const & p 292 ) 293 { 294 return detail::tquat<T, P>(q) *= p; 295 } 296 297 // Transformation 298 template <typename T, precision P> 299 GLM_FUNC_QUALIFIER detail::tvec3<T, P> operator* 300 ( 301 detail::tquat<T, P> const & q, 302 detail::tvec3<T, P> const & v 303 ) 304 { 305 T Two(2); 306 307 detail::tvec3<T, P> uv, uuv; 308 detail::tvec3<T, P> QuatVector(q.x, q.y, q.z); 309 uv = glm::cross(QuatVector, v); 310 uuv = glm::cross(QuatVector, uv); 311 uv *= (Two * q.w); 312 uuv *= Two; 313 314 return v + uv + uuv; 315 } 316 317 template <typename T, precision P> 318 GLM_FUNC_QUALIFIER detail::tvec3<T, P> operator* 319 ( 320 detail::tvec3<T, P> const & v, 321 detail::tquat<T, P> const & q 322 ) 323 { 324 return glm::inverse(q) * v; 325 } 326 327 template <typename T, precision P> 328 GLM_FUNC_QUALIFIER detail::tvec4<T, P> operator* 329 ( 330 detail::tquat<T, P> const & q, 331 detail::tvec4<T, P> const & v 332 ) 333 { 334 return detail::tvec4<T, P>(q * detail::tvec3<T, P>(v), v.w); 335 } 336 337 template <typename T, precision P> 338 GLM_FUNC_QUALIFIER detail::tvec4<T, P> operator* 339 ( 340 detail::tvec4<T, P> const & v, 341 detail::tquat<T, P> const & q 342 ) 343 { 344 return glm::inverse(q) * v; 345 } 346 347 template <typename T, precision P> 348 GLM_FUNC_QUALIFIER detail::tquat<T, P> operator* 349 ( 350 detail::tquat<T, P> const & q, 351 T const & s 352 ) 353 { 354 return detail::tquat<T, P>( 355 q.w * s, q.x * s, q.y * s, q.z * s); 356 } 357 358 template <typename T, precision P> 359 GLM_FUNC_QUALIFIER detail::tquat<T, P> operator* 360 ( 361 T const & s, 362 detail::tquat<T, P> const & q 363 ) 364 { 365 return q * s; 366 } 367 368 template <typename T, precision P> 369 GLM_FUNC_QUALIFIER detail::tquat<T, P> operator/ 370 ( 371 detail::tquat<T, P> const & q, 372 T const & s 373 ) 374 { 375 return detail::tquat<T, P>( 376 q.w / s, q.x / s, q.y / s, q.z / s); 377 } 378 379 ////////////////////////////////////// 380 // Boolean operators 381 382 template <typename T, precision P> 383 GLM_FUNC_QUALIFIER bool operator== 384 ( 385 detail::tquat<T, P> const & q1, 386 detail::tquat<T, P> const & q2 387 ) 388 { 389 return (q1.x == q2.x) && (q1.y == q2.y) && (q1.z == q2.z) && (q1.w == q2.w); 390 } 391 392 template <typename T, precision P> 393 GLM_FUNC_QUALIFIER bool operator!= 394 ( 395 detail::tquat<T, P> const & q1, 396 detail::tquat<T, P> const & q2 397 ) 398 { 399 return (q1.x != q2.x) || (q1.y != q2.y) || (q1.z != q2.z) || (q1.w != q2.w); 400 } 401 402}//namespace detail 403 404 //////////////////////////////////////////////////////// 405 template <typename T, precision P> 406 GLM_FUNC_QUALIFIER T length 407 ( 408 detail::tquat<T, P> const & q 409 ) 410 { 411 return glm::sqrt(dot(q, q)); 412 } 413 414 template <typename T, precision P> 415 GLM_FUNC_QUALIFIER detail::tquat<T, P> normalize 416 ( 417 detail::tquat<T, P> const & q 418 ) 419 { 420 T len = length(q); 421 if(len <= T(0)) // Problem 422 return detail::tquat<T, P>(1, 0, 0, 0); 423 T oneOverLen = T(1) / len; 424 return detail::tquat<T, P>(q.w * oneOverLen, q.x * oneOverLen, q.y * oneOverLen, q.z * oneOverLen); 425 } 426 427 template <typename T, precision P> 428 GLM_FUNC_QUALIFIER detail::tquat<T, P> cross 429 ( 430 detail::tquat<T, P> const & q1, 431 detail::tquat<T, P> const & q2 432 ) 433 { 434 return detail::tquat<T, P>( 435 q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z, 436 q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y, 437 q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z, 438 q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x); 439 } 440/* 441 // (x * sin(1 - a) * angle / sin(angle)) + (y * sin(a) * angle / sin(angle)) 442 template <typename T, precision P> 443 GLM_FUNC_QUALIFIER detail::tquat<T, P> mix 444 ( 445 detail::tquat<T, P> const & x, 446 detail::tquat<T, P> const & y, 447 T const & a 448 ) 449 { 450 if(a <= T(0)) return x; 451 if(a >= T(1)) return y; 452 453 float fCos = dot(x, y); 454 detail::tquat<T, P> y2(y); //BUG!!! tquat<T, P> y2; 455 if(fCos < T(0)) 456 { 457 y2 = -y; 458 fCos = -fCos; 459 } 460 461 //if(fCos > 1.0f) // problem 462 float k0, k1; 463 if(fCos > T(0.9999)) 464 { 465 k0 = T(1) - a; 466 k1 = T(0) + a; //BUG!!! 1.0f + a; 467 } 468 else 469 { 470 T fSin = sqrt(T(1) - fCos * fCos); 471 T fAngle = atan(fSin, fCos); 472 T fOneOverSin = static_cast<T>(1) / fSin; 473 k0 = sin((T(1) - a) * fAngle) * fOneOverSin; 474 k1 = sin((T(0) + a) * fAngle) * fOneOverSin; 475 } 476 477 return detail::tquat<T, P>( 478 k0 * x.w + k1 * y2.w, 479 k0 * x.x + k1 * y2.x, 480 k0 * x.y + k1 * y2.y, 481 k0 * x.z + k1 * y2.z); 482 } 483 484 template <typename T, precision P> 485 GLM_FUNC_QUALIFIER detail::tquat<T, P> mix2 486 ( 487 detail::tquat<T, P> const & x, 488 detail::tquat<T, P> const & y, 489 T const & a 490 ) 491 { 492 bool flip = false; 493 if(a <= static_cast<T>(0)) return x; 494 if(a >= static_cast<T>(1)) return y; 495 496 T cos_t = dot(x, y); 497 if(cos_t < T(0)) 498 { 499 cos_t = -cos_t; 500 flip = true; 501 } 502 503 T alpha(0), beta(0); 504 505 if(T(1) - cos_t < 1e-7) 506 beta = static_cast<T>(1) - alpha; 507 else 508 { 509 T theta = acos(cos_t); 510 T sin_t = sin(theta); 511 beta = sin(theta * (T(1) - alpha)) / sin_t; 512 alpha = sin(alpha * theta) / sin_t; 513 } 514 515 if(flip) 516 alpha = -alpha; 517 518 return normalize(beta * x + alpha * y); 519 } 520*/ 521 522 template <typename T, precision P> 523 GLM_FUNC_QUALIFIER detail::tquat<T, P> mix 524 ( 525 detail::tquat<T, P> const & x, 526 detail::tquat<T, P> const & y, 527 T const & a 528 ) 529 { 530 T cosTheta = dot(x, y); 531 532 // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator 533 if(cosTheta > T(1) - epsilon<T>()) 534 { 535 // Linear interpolation 536 return detail::tquat<T, P>( 537 mix(x.w, y.w, a), 538 mix(x.x, y.x, a), 539 mix(x.y, y.y, a), 540 mix(x.z, y.z, a)); 541 } 542 else 543 { 544 // Essential Mathematics, page 467 545 T angle = acos(cosTheta); 546 return (sin((T(1) - a) * angle) * x + sin(a * angle) * y) / sin(angle); 547 } 548 } 549 550 template <typename T, precision P> 551 GLM_FUNC_QUALIFIER detail::tquat<T, P> lerp 552 ( 553 detail::tquat<T, P> const & x, 554 detail::tquat<T, P> const & y, 555 T const & a 556 ) 557 { 558 // Lerp is only defined in [0, 1] 559 assert(a >= static_cast<T>(0)); 560 assert(a <= static_cast<T>(1)); 561 562 return x * (T(1) - a) + (y * a); 563 } 564 565 template <typename T, precision P> 566 GLM_FUNC_QUALIFIER detail::tquat<T, P> slerp 567 ( 568 detail::tquat<T, P> const & x, 569 detail::tquat<T, P> const & y, 570 T const & a 571 ) 572 { 573 detail::tquat<T, P> z = y; 574 575 T cosTheta = dot(x, y); 576 577 // If cosTheta < 0, the interpolation will take the long way around the sphere. 578 // To fix this, one quat must be negated. 579 if (cosTheta < T(0)) 580 { 581 z = -y; 582 cosTheta = -cosTheta; 583 } 584 585 // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator 586 if(cosTheta > T(1) - epsilon<T>()) 587 { 588 // Linear interpolation 589 return detail::tquat<T, P>( 590 mix(x.w, y.w, a), 591 mix(x.x, y.x, a), 592 mix(x.y, y.y, a), 593 mix(x.z, y.z, a)); 594 } 595 else 596 { 597 // Essential Mathematics, page 467 598 T angle = acos(cosTheta); 599 return (sin((T(1) - a) * angle) * x + sin(a * angle) * z) / sin(angle); 600 } 601 } 602 603 template <typename T, precision P> 604 GLM_FUNC_QUALIFIER detail::tquat<T, P> rotate 605 ( 606 detail::tquat<T, P> const & q, 607 T const & angle, 608 detail::tvec3<T, P> const & v 609 ) 610 { 611 detail::tvec3<T, P> Tmp = v; 612 613 // Axis of rotation must be normalised 614 T len = glm::length(Tmp); 615 if(abs(len - T(1)) > T(0.001)) 616 { 617 T oneOverLen = static_cast<T>(1) / len; 618 Tmp.x *= oneOverLen; 619 Tmp.y *= oneOverLen; 620 Tmp.z *= oneOverLen; 621 } 622 623#ifdef GLM_FORCE_RADIANS 624 T const AngleRad(angle); 625#else 626# pragma message("GLM: rotate function taking degrees as a parameter is deprecated. #define GLM_FORCE_RADIANS before including GLM headers to remove this message.") 627 T const AngleRad = radians(angle); 628#endif 629 T const Sin = sin(AngleRad * T(0.5)); 630 631 return q * detail::tquat<T, P>(cos(AngleRad * T(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); 632 //return gtc::quaternion::cross(q, detail::tquat<T, P>(cos(AngleRad * T(0.5)), Tmp.x * fSin, Tmp.y * fSin, Tmp.z * fSin)); 633 } 634 635 template <typename T, precision P> 636 GLM_FUNC_QUALIFIER detail::tvec3<T, P> eulerAngles 637 ( 638 detail::tquat<T, P> const & x 639 ) 640 { 641 return detail::tvec3<T, P>(pitch(x), yaw(x), roll(x)); 642 } 643 644 template <typename T, precision P> 645 GLM_FUNC_QUALIFIER T roll 646 ( 647 detail::tquat<T, P> const & q 648 ) 649 { 650#ifdef GLM_FORCE_RADIANS 651 return T(atan(T(2) * (q.x * q.y + q.w * q.z), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z)); 652#else 653# pragma message("GLM: roll function returning degrees is deprecated. #define GLM_FORCE_RADIANS before including GLM headers to remove this message.") 654 return glm::degrees(atan(T(2) * (q.x * q.y + q.w * q.z), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z)); 655#endif 656 } 657 658 template <typename T, precision P> 659 GLM_FUNC_QUALIFIER T pitch 660 ( 661 detail::tquat<T, P> const & q 662 ) 663 { 664#ifdef GLM_FORCE_RADIANS 665 return T(atan(T(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z)); 666#else 667# pragma message("GLM: pitch function returning degrees is deprecated. #define GLM_FORCE_RADIANS before including GLM headers to remove this message.") 668 return glm::degrees(atan(T(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z)); 669#endif 670 } 671 672 template <typename T, precision P> 673 GLM_FUNC_QUALIFIER T yaw 674 ( 675 detail::tquat<T, P> const & q 676 ) 677 { 678#ifdef GLM_FORCE_RADIANS 679 return asin(T(-2) * (q.x * q.z - q.w * q.y)); 680#else 681# pragma message("GLM: yaw function returning degrees is deprecated. #define GLM_FORCE_RADIANS before including GLM headers to remove this message.") 682 return glm::degrees(asin(T(-2) * (q.x * q.z - q.w * q.y))); 683#endif 684 } 685 686 template <typename T, precision P> 687 GLM_FUNC_QUALIFIER detail::tmat3x3<T, P> mat3_cast 688 ( 689 detail::tquat<T, P> const & q 690 ) 691 { 692 detail::tmat3x3<T, P> Result(T(1)); 693 T qxx(q.x * q.x); 694 T qyy(q.y * q.y); 695 T qzz(q.z * q.z); 696 T qxz(q.x * q.z); 697 T qxy(q.x * q.y); 698 T qyz(q.y * q.z); 699 T qwx(q.w * q.x); 700 T qwy(q.w * q.y); 701 T qwz(q.w * q.z); 702 703 Result[0][0] = 1 - 2 * (qyy + qzz); 704 Result[0][1] = 2 * (qxy + qwz); 705 Result[0][2] = 2 * (qxz - qwy); 706 707 Result[1][0] = 2 * (qxy - qwz); 708 Result[1][1] = 1 - 2 * (qxx + qzz); 709 Result[1][2] = 2 * (qyz + qwx); 710 711 Result[2][0] = 2 * (qxz + qwy); 712 Result[2][1] = 2 * (qyz - qwx); 713 Result[2][2] = 1 - 2 * (qxx + qyy); 714 return Result; 715 } 716 717 template <typename T, precision P> 718 GLM_FUNC_QUALIFIER detail::tmat4x4<T, P> mat4_cast 719 ( 720 detail::tquat<T, P> const & q 721 ) 722 { 723 return detail::tmat4x4<T, P>(mat3_cast(q)); 724 } 725 726 template <typename T, precision P> 727 GLM_FUNC_QUALIFIER detail::tquat<T, P> quat_cast 728 ( 729 detail::tmat3x3<T, P> const & m 730 ) 731 { 732 T fourXSquaredMinus1 = m[0][0] - m[1][1] - m[2][2]; 733 T fourYSquaredMinus1 = m[1][1] - m[0][0] - m[2][2]; 734 T fourZSquaredMinus1 = m[2][2] - m[0][0] - m[1][1]; 735 T fourWSquaredMinus1 = m[0][0] + m[1][1] + m[2][2]; 736 737 int biggestIndex = 0; 738 T fourBiggestSquaredMinus1 = fourWSquaredMinus1; 739 if(fourXSquaredMinus1 > fourBiggestSquaredMinus1) 740 { 741 fourBiggestSquaredMinus1 = fourXSquaredMinus1; 742 biggestIndex = 1; 743 } 744 if(fourYSquaredMinus1 > fourBiggestSquaredMinus1) 745 { 746 fourBiggestSquaredMinus1 = fourYSquaredMinus1; 747 biggestIndex = 2; 748 } 749 if(fourZSquaredMinus1 > fourBiggestSquaredMinus1) 750 { 751 fourBiggestSquaredMinus1 = fourZSquaredMinus1; 752 biggestIndex = 3; 753 } 754 755 T biggestVal = sqrt(fourBiggestSquaredMinus1 + T(1)) * T(0.5); 756 T mult = static_cast<T>(0.25) / biggestVal; 757 758 detail::tquat<T, P> Result; 759 switch(biggestIndex) 760 { 761 case 0: 762 Result.w = biggestVal; 763 Result.x = (m[1][2] - m[2][1]) * mult; 764 Result.y = (m[2][0] - m[0][2]) * mult; 765 Result.z = (m[0][1] - m[1][0]) * mult; 766 break; 767 case 1: 768 Result.w = (m[1][2] - m[2][1]) * mult; 769 Result.x = biggestVal; 770 Result.y = (m[0][1] + m[1][0]) * mult; 771 Result.z = (m[2][0] + m[0][2]) * mult; 772 break; 773 case 2: 774 Result.w = (m[2][0] - m[0][2]) * mult; 775 Result.x = (m[0][1] + m[1][0]) * mult; 776 Result.y = biggestVal; 777 Result.z = (m[1][2] + m[2][1]) * mult; 778 break; 779 case 3: 780 Result.w = (m[0][1] - m[1][0]) * mult; 781 Result.x = (m[2][0] + m[0][2]) * mult; 782 Result.y = (m[1][2] + m[2][1]) * mult; 783 Result.z = biggestVal; 784 break; 785 786 default: // Silence a -Wswitch-default warning in GCC. Should never actually get here. Assert is just for sanity. 787 assert(false); 788 break; 789 } 790 return Result; 791 } 792 793 template <typename T, precision P> 794 GLM_FUNC_QUALIFIER detail::tquat<T, P> quat_cast 795 ( 796 detail::tmat4x4<T, P> const & m4 797 ) 798 { 799 return quat_cast(detail::tmat3x3<T, P>(m4)); 800 } 801 802 template <typename T, precision P> 803 GLM_FUNC_QUALIFIER T angle 804 ( 805 detail::tquat<T, P> const & x 806 ) 807 { 808#ifdef GLM_FORCE_RADIANS 809 return acos(x.w) * T(2); 810#else 811# pragma message("GLM: angle function returning degrees is deprecated. #define GLM_FORCE_RADIANS before including GLM headers to remove this message.") 812 return glm::degrees(acos(x.w) * T(2)); 813#endif 814 } 815 816 template <typename T, precision P> 817 GLM_FUNC_QUALIFIER detail::tvec3<T, P> axis 818 ( 819 detail::tquat<T, P> const & x 820 ) 821 { 822 T tmp1 = static_cast<T>(1) - x.w * x.w; 823 if(tmp1 <= static_cast<T>(0)) 824 return detail::tvec3<T, P>(0, 0, 1); 825 T tmp2 = static_cast<T>(1) / sqrt(tmp1); 826 return detail::tvec3<T, P>(x.x * tmp2, x.y * tmp2, x.z * tmp2); 827 } 828 829 template <typename T, precision P> 830 GLM_FUNC_QUALIFIER detail::tquat<T, P> angleAxis 831 ( 832 T const & angle, 833 detail::tvec3<T, P> const & v 834 ) 835 { 836 detail::tquat<T, P> result; 837 838#ifdef GLM_FORCE_RADIANS 839 T const a(angle); 840#else 841# pragma message("GLM: angleAxis function taking degrees as a parameter is deprecated. #define GLM_FORCE_RADIANS before including GLM headers to remove this message.") 842 T const a(glm::radians(angle)); 843#endif 844 T s = glm::sin(a * T(0.5)); 845 846 result.w = glm::cos(a * T(0.5)); 847 result.x = v.x * s; 848 result.y = v.y * s; 849 result.z = v.z * s; 850 return result; 851 } 852 853 template <typename T, precision P> 854 GLM_FUNC_QUALIFIER detail::tvec4<bool, P> lessThan 855 ( 856 detail::tquat<T, P> const & x, 857 detail::tquat<T, P> const & y 858 ) 859 { 860 detail::tvec4<bool, P> Result; 861 for(length_t i = 0; i < x.length(); ++i) 862 Result[i] = x[i] < y[i]; 863 return Result; 864 } 865 866 template <typename T, precision P> 867 GLM_FUNC_QUALIFIER detail::tvec4<bool, P> lessThanEqual 868 ( 869 detail::tquat<T, P> const & x, 870 detail::tquat<T, P> const & y 871 ) 872 { 873 detail::tvec4<bool, P> Result; 874 for(length_t i = 0; i < x.length(); ++i) 875 Result[i] = x[i] <= y[i]; 876 return Result; 877 } 878 879 template <typename T, precision P> 880 GLM_FUNC_QUALIFIER detail::tvec4<bool, P> greaterThan 881 ( 882 detail::tquat<T, P> const & x, 883 detail::tquat<T, P> const & y 884 ) 885 { 886 detail::tvec4<bool, P> Result; 887 for(length_t i = 0; i < x.length(); ++i) 888 Result[i] = x[i] > y[i]; 889 return Result; 890 } 891 892 template <typename T, precision P> 893 GLM_FUNC_QUALIFIER detail::tvec4<bool, P> greaterThanEqual 894 ( 895 detail::tquat<T, P> const & x, 896 detail::tquat<T, P> const & y 897 ) 898 { 899 detail::tvec4<bool, P> Result; 900 for(length_t i = 0; i < x.length(); ++i) 901 Result[i] = x[i] >= y[i]; 902 return Result; 903 } 904 905 template <typename T, precision P> 906 GLM_FUNC_QUALIFIER detail::tvec4<bool, P> equal 907 ( 908 detail::tquat<T, P> const & x, 909 detail::tquat<T, P> const & y 910 ) 911 { 912 detail::tvec4<bool, P> Result; 913 for(length_t i = 0; i < x.length(); ++i) 914 Result[i] = x[i] == y[i]; 915 return Result; 916 } 917 918 template <typename T, precision P> 919 GLM_FUNC_QUALIFIER detail::tvec4<bool, P> notEqual 920 ( 921 detail::tquat<T, P> const & x, 922 detail::tquat<T, P> const & y 923 ) 924 { 925 detail::tvec4<bool, P> Result; 926 for(length_t i = 0; i < x.length(); ++i) 927 Result[i] = x[i] != y[i]; 928 return Result; 929 } 930}//namespace glm 931