llquaternion2.inl 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /**
  2. * @file llquaternion2.inl
  3. * @brief LLQuaternion2 inline definitions
  4. *
  5. * $LicenseInfo:firstyear=2010&license=viewergpl$
  6. *
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #ifndef LL_INL_INCLUDE
  33. # error "You cannot #include this file yourself, #include llmath.h instead !"
  34. #endif
  35. thread_local const LLQuad LL_V4A_PLUS_ONE = { 1.f, 1.f, 1.f, 1.f };
  36. thread_local const LLQuad LL_V4A_MINUS_ONE = { -1.f, -1.f, -1.f, -1.f };
  37. // Ctor from LLQuaternion
  38. LL_INLINE LLQuaternion2::LLQuaternion2(const LLQuaternion& quat)
  39. {
  40. mQ.set(quat.mQ[VX], quat.mQ[VY], quat.mQ[VZ], quat.mQ[VW]);
  41. }
  42. //////////////////////////
  43. // Get/Set
  44. //////////////////////////
  45. // Return the internal LLVector4a representation of the quaternion
  46. LL_INLINE const LLVector4a& LLQuaternion2::getVector4a() const
  47. {
  48. return mQ;
  49. }
  50. LL_INLINE LLVector4a& LLQuaternion2::getVector4aRw()
  51. {
  52. return mQ;
  53. }
  54. /////////////////////////
  55. // Quaternion modification
  56. /////////////////////////
  57. // Set this quaternion to the conjugate of src
  58. LL_INLINE void LLQuaternion2::setConjugate(const LLQuaternion2& src)
  59. {
  60. alignas(16) thread_local const U32 F_QUAT_INV_MASK_4A[4] = { 0x80000000,
  61. 0x80000000,
  62. 0x80000000,
  63. 0x00000000 };
  64. mQ = _mm_xor_ps(src.mQ,
  65. *reinterpret_cast<const LLQuad*>(&F_QUAT_INV_MASK_4A));
  66. }
  67. // Renormalizes the quaternion. Assumes it has nonzero length.
  68. LL_INLINE void LLQuaternion2::normalize()
  69. {
  70. mQ.normalize4();
  71. }
  72. // Quantize this quaternion to 8 bit precision
  73. LL_INLINE void LLQuaternion2::quantize8()
  74. {
  75. mQ.quantize8(LL_V4A_MINUS_ONE, LL_V4A_PLUS_ONE);
  76. normalize();
  77. }
  78. // Quantize this quaternion to 16 bit precision
  79. LL_INLINE void LLQuaternion2::quantize16()
  80. {
  81. mQ.quantize16(LL_V4A_MINUS_ONE, LL_V4A_PLUS_ONE);
  82. normalize();
  83. }
  84. LL_INLINE void LLQuaternion2::mul(const LLQuaternion2& b)
  85. {
  86. alignas(16) thread_local const unsigned int signMask[4] = {
  87. 0x0, 0x0, 0x0, 0x80000000
  88. };
  89. LLVector4a sum1, sum2, prod1, prod2, prod3, prod4;
  90. const LLVector4a& va = mQ;
  91. const LLVector4a& vb = b.getVector4a();
  92. // [VX] [VY] [VZ] [VW]
  93. // prod1: +wx +wy +wz +ww Bwwww*Axyzw
  94. // prod2: +xw +yw +zw -xx Bxyzx*Awwwx [VW] sign flip
  95. // prod3: +yz +zx +xy -yy Byzxy*Azxyy [VW] sign flip
  96. // prod4: -zy -xz -yx -zz Bzxyz*Ayzzz
  97. const LLVector4a Bwwww = _mm_shuffle_ps(vb, vb, _MM_SHUFFLE(3, 3, 3, 3));
  98. const LLVector4a Bxyzx = _mm_shuffle_ps(vb, vb, _MM_SHUFFLE(0, 2, 1, 0));
  99. const LLVector4a Awwwx = _mm_shuffle_ps(va, va, _MM_SHUFFLE(0, 3, 3, 3));
  100. const LLVector4a Byzxy = _mm_shuffle_ps(vb, vb, _MM_SHUFFLE(1, 0, 2, 1));
  101. const LLVector4a Azxyy = _mm_shuffle_ps(va, va, _MM_SHUFFLE(1, 1, 0, 2));
  102. const LLVector4a Bzxyz = _mm_shuffle_ps(vb, vb, _MM_SHUFFLE(2, 1, 0, 2));
  103. const LLVector4a Ayzxz = _mm_shuffle_ps(va, va, _MM_SHUFFLE(2, 0, 2, 1));
  104. prod1.setMul(Bwwww, va);
  105. prod2.setMul(Bxyzx, Awwwx);
  106. prod3.setMul(Byzxy, Azxyy);
  107. prod4.setMul(Bzxyz, Ayzxz);
  108. sum1.setAdd(prod2, prod3);
  109. sum1 = _mm_xor_ps(sum1, _mm_load_ps((const float*)signMask));
  110. sum2.setSub(prod1, prod4);
  111. mQ.setAdd(sum1, sum2);
  112. }
  113. /////////////////////////
  114. // Quaternion inspection
  115. /////////////////////////
  116. // Return true if this quaternion is equal to 'rhs'.
  117. // Note: Quaternions exhibit "double-cover", so any rotation has two equally valid
  118. // quaternion representations and they will NOT compare equal.
  119. LL_INLINE bool LLQuaternion2::equals(const LLQuaternion2 &rhs, F32 tolerance) const
  120. {
  121. return mQ.equals4(rhs.mQ, tolerance);
  122. }
  123. // Return true if all components are finite and the quaternion is normalized
  124. LL_INLINE bool LLQuaternion2::isOkRotation() const
  125. {
  126. return mQ.isFinite4() && mQ.isNormalized4();
  127. }