1 // 2 // Copyright 2016 Pixar 3 // 4 // Licensed under the Apache License, Version 2.0 (the "Apache License") 5 // with the following modification; you may not use this file except in 6 // compliance with the Apache License and the following modification to it: 7 // Section 6. Trademarks. is deleted and replaced with: 8 // 9 // 6. Trademarks. This License does not grant permission to use the trade 10 // names, trademarks, service marks, or product names of the Licensor 11 // and its affiliates, except as required to comply with Section 4(c) of 12 // the License and to reproduce the content of the NOTICE file. 13 // 14 // You may obtain a copy of the Apache License at 15 // 16 // http://www.apache.org/licenses/LICENSE-2.0 17 // 18 // Unless required by applicable law or agreed to in writing, software 19 // distributed under the Apache License with the above modification is 20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 21 // KIND, either express or implied. See the Apache License for the specific 22 // language governing permissions and limitations under the Apache License. 23 // 24 #ifndef PXR_BASE_GF_QUATERNION_H 25 #define PXR_BASE_GF_QUATERNION_H 26 27 /// \file gf/quaternion.h 28 /// \ingroup group_gf_LinearAlgebra 29 30 #include "pxr/pxr.h" 31 #include "pxr/base/gf/api.h" 32 #include "pxr/base/gf/vec3d.h" 33 34 #include <boost/functional/hash.hpp> 35 36 #include <iosfwd> 37 38 PXR_NAMESPACE_OPEN_SCOPE 39 40 /// \class GfQuaternion 41 /// \ingroup group_gf_LinearAlgebra 42 /// 43 /// Basic type: complex number with scalar real part and vector imaginary 44 /// part. 45 /// 46 /// This class represents a generalized complex number that has a scalar real 47 /// part and a vector of three imaginary values. Quaternions are used by the 48 /// \c GfRotation class to represent arbitrary-axis rotations. 49 /// 50 class GfQuaternion 51 { 52 public: 53 54 /// The default constructor leaves the quaternion undefined. GfQuaternion()55 GfQuaternion() { 56 } 57 58 /// This constructor initializes the real part to the argument and 59 /// the imaginary parts to zero. 60 /// 61 /// Since quaternions typically need to be normalized, the only reasonable 62 /// values for \p realVal are -1, 0, or 1. Other values are legal but are 63 /// likely to be meaningless. GfQuaternion(int realVal)64 explicit GfQuaternion(int realVal) 65 : _real(realVal), _imaginary(0) 66 { 67 } 68 69 /// This constructor initializes the real and imaginary parts. GfQuaternion(double real,const GfVec3d & imaginary)70 GfQuaternion(double real, const GfVec3d &imaginary) 71 : _real(real), _imaginary(imaginary) { 72 } 73 74 /// Sets the real part of the quaternion. SetReal(double real)75 void SetReal(double real) { 76 _real = real; 77 } 78 79 /// Sets the imaginary part of the quaternion. SetImaginary(const GfVec3d & imaginary)80 void SetImaginary(const GfVec3d &imaginary) { 81 _imaginary = imaginary; 82 } 83 84 /// Returns the real part of the quaternion. GetReal()85 double GetReal() const { 86 return _real; 87 } 88 89 /// Returns the imaginary part of the quaternion. GetImaginary()90 const GfVec3d & GetImaginary() const { 91 return _imaginary; 92 } 93 94 /// Returns the identity quaternion, which has a real part of 1 and 95 /// an imaginary part of (0,0,0). GetIdentity()96 static GfQuaternion GetIdentity() { 97 return GfQuaternion(1.0, GfVec3d(0.0, 0.0, 0.0)); 98 } 99 100 /// Returns geometric length of this quaternion. 101 GF_API 102 double GetLength() const; 103 104 /// Returns a normalized (unit-length) version of this quaternion. 105 /// direction as this. If the length of this quaternion is smaller than \p 106 /// eps, this returns the identity quaternion. 107 GF_API 108 GfQuaternion GetNormalized(double eps = GF_MIN_VECTOR_LENGTH) const; 109 110 /// Normalizes this quaternion in place to unit length, returning the 111 /// length before normalization. If the length of this quaternion is 112 /// smaller than \p eps, this sets the quaternion to identity. 113 GF_API 114 double Normalize(double eps = GF_MIN_VECTOR_LENGTH); 115 116 /// Returns the inverse of this quaternion. 117 GF_API 118 GfQuaternion GetInverse() const; 119 120 /// Hash. hash_value(const GfQuaternion & q)121 friend inline size_t hash_value(const GfQuaternion &q) { 122 size_t h = 0; 123 boost::hash_combine(h, q.GetReal()); 124 boost::hash_combine(h, q.GetImaginary()); 125 return h; 126 } 127 128 /// Component-wise quaternion equality test. The real and imaginary parts 129 /// must match exactly for quaternions to be considered equal. 130 bool operator ==(const GfQuaternion &q) const { 131 return (GetReal() == q.GetReal() && 132 GetImaginary() == q.GetImaginary()); 133 } 134 135 /// Component-wise quaternion inequality test. The real and imaginary 136 /// parts must match exactly for quaternions to be considered equal. 137 bool operator !=(const GfQuaternion &q) const { 138 return ! (*this == q); 139 } 140 141 /// Post-multiplies quaternion \p q into this quaternion. 142 GF_API 143 GfQuaternion & operator *=(const GfQuaternion &q); 144 145 /// Scales this quaternion by \p s. 146 GF_API 147 GfQuaternion & operator *=(double s); 148 149 /// Scales this quaternion by 1 / \p s. 150 GfQuaternion & operator /=(double s) { 151 return (*this) *= 1.0 / s; 152 } 153 154 /// Component-wise unary sum operator. 155 GfQuaternion & operator +=(const GfQuaternion &q) { 156 _real += q._real; 157 _imaginary += q._imaginary; 158 return *this; 159 } 160 161 /// Component-wise unary difference operator. 162 GfQuaternion & operator -=(const GfQuaternion &q) { 163 _real -= q._real; 164 _imaginary -= q._imaginary; 165 return *this; 166 } 167 168 /// Component-wise binary sum operator. 169 friend GfQuaternion operator +(const GfQuaternion &q1, 170 const GfQuaternion &q2) { 171 GfQuaternion qt = q1; 172 return qt += q2; 173 } 174 175 /// Component-wise binary difference operator. 176 friend GfQuaternion operator -(const GfQuaternion &q1, 177 const GfQuaternion &q2) { 178 GfQuaternion qt = q1; 179 return qt -= q2; 180 } 181 182 /// Returns the product of quaternions \p q1 and \p q2. 183 friend GfQuaternion operator *(const GfQuaternion &q1, 184 const GfQuaternion &q2) { 185 GfQuaternion qt = q1; 186 return qt *= q2; 187 } 188 189 /// Returns the product of quaternion \p q and scalar \p s. 190 friend GfQuaternion operator *(const GfQuaternion &q, double s) { 191 GfQuaternion qt = q; 192 return qt *= s; 193 } 194 195 /// Returns the product of quaternion \p q and scalar \p s. 196 friend GfQuaternion operator *(double s, const GfQuaternion &q) { 197 GfQuaternion qt = q; 198 return qt *= s; 199 } 200 201 /// Returns the product of quaternion \p q and scalar 1 / \p s. 202 friend GfQuaternion operator /(const GfQuaternion &q, double s) { 203 GfQuaternion qt = q; 204 return qt /= s; 205 } 206 207 /// Spherically interpolate between \p q0 and \p q1. 208 /// 209 /// If the interpolant \p alpha 210 /// is zero, then the result is \p q0, while \p alpha of one yields 211 /// \p q1. 212 GF_API 213 friend GfQuaternion GfSlerp(double alpha, 214 const GfQuaternion& q0, 215 const GfQuaternion& q1); 216 217 // TODO Remove this legacy alias/overload. 218 friend GF_API GfQuaternion GfSlerp(const GfQuaternion& q0, 219 const GfQuaternion& q1, 220 double alpha); 221 222 private: 223 /// Real part 224 double _real; 225 /// Imaginary part 226 GfVec3d _imaginary; 227 228 /// Returns the square of the length _GetLengthSquared()229 double _GetLengthSquared() const { 230 return (_real * _real + GfDot(_imaginary, _imaginary)); 231 } 232 }; 233 234 // Friend functions must be declared. 235 GF_API GfQuaternion GfSlerp(double alpha, const GfQuaternion& q0, const GfQuaternion& q1); 236 GF_API GfQuaternion GfSlerp(const GfQuaternion& q0, const GfQuaternion& q1, double alpha); 237 238 /// Output a GfQuaternion using the format (r + (x, y, z)). 239 /// \ingroup group_gf_DebuggingOutput 240 GF_API std::ostream& operator<<(std::ostream& out, const GfQuaternion& q); 241 242 PXR_NAMESPACE_CLOSE_SCOPE 243 244 #endif // PXR_BASE_GF_QUATERNION_H 245