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