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