4 #ifndef OPENVDB_MATH_QUAT_H_HAS_BEEN_INCLUDED
5 #define OPENVDB_MATH_QUAT_H_HAS_BEEN_INCLUDED
24 template<
typename T>
class Quat;
34 if (fabs(qdot) >= 1.0) {
39 sineAngle = sin(angle);
48 if (sineAngle <= tolerance) {
51 Quat<T> qtemp(s * q1[0] + t * q2[0], s * q1[1] + t * q2[1],
52 s * q1[2] + t * q2[2], s * q1[3] + t * q2[3]);
59 double lengthSquared = qtemp.dot(qtemp);
61 if (lengthSquared <= tolerance * tolerance) {
62 qtemp = (t < 0.5) ? q1 : q2;
64 qtemp *= 1.0 /
sqrt(lengthSquared);
69 T sine = 1.0 / sineAngle;
70 T a = sin((1.0 - t) * angle) * sine;
71 T b = sin(t * angle) * sine;
72 return Quat<T>(a * q1[0] + b * q2[0], a * q1[1] + b * q2[1],
73 a * q1[2] + b * q2[2], a * q1[3] + b * q2[3]);
117 T s =
T(sin(angle*
T(0.5)));
119 mm[0] = axis.
x() *
s;
120 mm[1] = axis.
y() *
s;
121 mm[2] = axis.
z() *
s;
123 mm[3] =
T(cos(angle*
T(0.5)));
130 T s =
T(sin(angle*
T(0.5)));
136 mm[3] =
T(cos(angle*
T(0.5)));
142 template<
typename T1>
149 T factor =
T(0.25) / q_w;
151 mm[0] = factor * (
rot(1,2) -
rot(2,1));
152 mm[1] = factor * (
rot(2,0) -
rot(0,2));
153 mm[2] = factor * (
rot(0,1) -
rot(1,0));
155 }
else if (
rot(0,0) >
rot(1,1) &&
rot(0,0) >
rot(2,2)) {
158 T factor =
T(0.25) / q_x;
161 mm[1] = factor * (
rot(0,1) +
rot(1,0));
162 mm[2] = factor * (
rot(2,0) +
rot(0,2));
163 mm[3] = factor * (
rot(1,2) -
rot(2,1));
164 }
else if (
rot(1,1) >
rot(2,2)) {
167 T factor =
T(0.25) / q_y;
169 mm[0] = factor * (
rot(0,1) +
rot(1,0));
171 mm[2] = factor * (
rot(1,2) +
rot(2,1));
172 mm[3] = factor * (
rot(2,0) -
rot(0,2));
176 T factor =
T(0.25) / q_z;
178 mm[0] = factor * (
rot(2,0) +
rot(0,2));
179 mm[1] = factor * (
rot(1,2) +
rot(2,1));
181 mm[3] = factor * (
rot(0,1) -
rot(1,0));
186 template<
typename T1>
192 "A non-rotation matrix can not be used to construct a quaternion");
196 "A reflection matrix can not be used to construct a quaternion");
204 T&
x() {
return mm[0]; }
205 T&
y() {
return mm[1]; }
206 T&
z() {
return mm[2]; }
207 T&
w() {
return mm[3]; }
210 T x()
const {
return mm[0]; }
211 T y()
const {
return mm[1]; }
212 T z()
const {
return mm[2]; }
213 T w()
const {
return mm[3]; }
216 static unsigned numElements() {
return 4; }
219 T& operator[](
int i) {
return mm[i]; }
222 T operator[](
int i)
const {
return mm[i]; }
225 operator T*() {
return mm; }
226 operator const T*()
const {
return mm; }
229 T& operator()(
int i) {
return mm[i]; }
232 T operator()(
int i)
const {
return mm[i]; }
239 if ( sqrLength > 1.0e-8 ) {
241 return T(
T(2.0) * acos(mm[3]));
252 T sqrLength = mm[0]*mm[0] + mm[1]*mm[1] + mm[2]*mm[2];
254 if ( sqrLength > 1.0e-8 ) {
256 T invLength =
T(
T(1)/
sqrt(sqrLength));
258 return Vec3<T>( mm[0]*invLength, mm[1]*invLength, mm[2]*invLength );
269 mm[0] =
x; mm[1] =
y; mm[2] =
z; mm[3] =
w;
274 Quat& init() {
return setIdentity(); }
281 T s =
T(sin(angle*
T(0.5)));
283 mm[0] = axis.
x() *
s;
284 mm[1] = axis.
y() *
s;
285 mm[2] = axis.
z() *
s;
287 mm[3] =
T(cos(angle*
T(0.5)));
295 mm[0] = mm[1] = mm[2] = mm[3] = 0;
302 mm[0] = mm[1] = mm[2] = 0;
321 bool eq(
const Quat &q, T eps=1.0e-7)
const
363 return Quat<T>(mm[0]+q.mm[0], mm[1]+q.mm[1], mm[2]+q.mm[2], mm[3]+q.mm[3]);
369 return Quat<T>(mm[0]-q.mm[0], mm[1]-q.mm[1], mm[2]-q.mm[2], mm[3]-q.mm[3]);
377 prod.mm[0] = mm[3]*q.mm[0] + mm[0]*q.mm[3] + mm[1]*q.mm[2] - mm[2]*q.mm[1];
378 prod.mm[1] = mm[3]*q.mm[1] + mm[1]*q.mm[3] + mm[2]*q.mm[0] - mm[0]*q.mm[2];
379 prod.mm[2] = mm[3]*q.mm[2] + mm[2]*q.mm[3] + mm[0]*q.mm[1] - mm[1]*q.mm[0];
380 prod.mm[3] = mm[3]*q.mm[3] - mm[0]*q.mm[0] - mm[1]*q.mm[1] - mm[2]*q.mm[2];
396 return Quat<T>(mm[0]*scalar, mm[1]*scalar, mm[2]*scalar, mm[3]*scalar);
402 return Quat<T>(mm[0]/scalar, mm[1]/scalar, mm[2]/scalar, mm[3]/scalar);
407 {
return Quat<T>(-mm[0], -mm[1], -mm[2], -mm[3]); }
413 mm[0] = q1.mm[0] + q2.mm[0];
414 mm[1] = q1.mm[1] + q2.mm[1];
415 mm[2] = q1.mm[2] + q2.mm[2];
416 mm[3] = q1.mm[3] + q2.mm[3];
425 mm[0] = q1.mm[0] - q2.mm[0];
426 mm[1] = q1.mm[1] - q2.mm[1];
427 mm[2] = q1.mm[2] - q2.mm[2];
428 mm[3] = q1.mm[3] - q2.mm[3];
437 mm[0] = q1.mm[3]*q2.mm[0] + q1.mm[0]*q2.mm[3] +
438 q1.mm[1]*q2.mm[2] - q1.mm[2]*q2.mm[1];
439 mm[1] = q1.mm[3]*q2.mm[1] + q1.mm[1]*q2.mm[3] +
440 q1.mm[2]*q2.mm[0] - q1.mm[0]*q2.mm[2];
441 mm[2] = q1.mm[3]*q2.mm[2] + q1.mm[2]*q2.mm[3] +
442 q1.mm[0]*q2.mm[1] - q1.mm[1]*q2.mm[0];
443 mm[3] = q1.mm[3]*q2.mm[3] - q1.mm[0]*q2.mm[0] -
444 q1.mm[1]*q2.mm[1] - q1.mm[2]*q2.mm[2];
453 mm[0] = scale * q.mm[0];
454 mm[1] = scale * q.mm[1];
455 mm[2] = scale * q.mm[2];
456 mm[3] = scale * q.mm[3];
464 return (mm[0]*q.mm[0] + mm[1]*q.mm[1] + mm[2]*q.mm[2] + mm[3]*q.mm[3]);
471 return Quat<T>( +
w()*omega.
x() -
z()*omega.
y() +
y()*omega.
z() ,
472 +
z()*omega.
x() +
w()*omega.
y() -
x()*omega.
z() ,
473 -
y()*omega.
x() +
x()*omega.
y() +
w()*omega.
z() ,
474 -
x()*omega.
x() -
y()*omega.
y() -
z()*omega.
z() );
480 T d =
T(
sqrt(mm[0]*mm[0] + mm[1]*mm[1] + mm[2]*mm[2] + mm[3]*mm[3]));
489 T d =
sqrt(mm[0]*mm[0] + mm[1]*mm[1] + mm[2]*mm[2] + mm[3]*mm[3]);
492 "Normalizing degenerate quaternion");
497 Quat inverse(T tolerance =
T(0))
const
499 T d = mm[0]*mm[0] + mm[1]*mm[1] + mm[2]*mm[2] + mm[3]*mm[3];
502 "Cannot invert degenerate quaternion");
504 result.mm[3] = -result.mm[3];
511 Quat conjugate()
const
513 return Quat<T>(-mm[0], -mm[1], -mm[2], mm[3]);
520 return m.transform(v);
525 static Quat identity() {
return Quat<T>(0,0,0,1); }
528 std::string str()
const
530 std::ostringstream
buffer;
535 for (
unsigned j(0);
j < 4;
j++) {
536 if (
j) buffer <<
", ";
554 void write(std::ostream& os)
const { os.write(static_cast<char*>(&mm),
sizeof(
T) * 4); }
555 void read(std::istream& is) { is.read(static_cast<char*>(&mm),
sizeof(
T) * 4); }
562 template <
typename S,
typename T>
569 template <
typename T,
typename T0>
577 if (q1.dot(q2) < 0) q2 *= -1;
579 Quat<T> qslerp = slerp<T>(q1, q2,
static_cast<T>(
t));
580 MatType m = rotation<MatType>(qslerp);
594 template <
typename T,
typename T0>
599 Mat3<T> m00, m01, m02, m10, m11;
601 m00 =
slerp(m1, m2, t);
602 m01 =
slerp(m2, m3, t);
603 m02 =
slerp(m3, m4, t);
605 m10 =
slerp(m00, m01, t);
606 m11 =
slerp(m01, m02, t);
608 return slerp(m10, m11, t);
621 template<>
inline math::Quatd zeroVal<math::Quatd >() {
return math::Quatd::zero(); }
626 #endif //OPENVDB_MATH_QUAT_H_HAS_BEEN_INCLUDED
Quat(T x, T y, T z, T w)
Constructor with four arguments, e.g. Quatf q(1,2,3,4);.
bool isExactlyEqual(const T0 &a, const T1 &b)
Return true if a is exactly equal to b.
Vec3< typename promote< T, Coord::ValueType >::type > operator-(const Vec3< T > &v0, const Coord &v1)
Allow a Coord to be subtracted from a Vec3.
GA_API const UT_StringHolder rot
vfloat4 sqrt(const vfloat4 &a)
GLdouble GLdouble GLdouble z
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Multiply m0 by m1 and return the resulting matrix.
GLboolean GLboolean GLboolean GLboolean a
#define OPENVDB_USE_VERSION_NAMESPACE
**But if you need a result
GLdouble GLdouble GLdouble q
MatType unit(const MatType &mat, typename MatType::value_type eps=1.0e-8)
Return a copy of the given matrix with its upper 3×3 rows normalized.
Vec3< typename MatType::value_type > eulerAngles(const MatType &mat, RotationOrder rotationOrder, typename MatType::value_type eps=static_cast< typename MatType::value_type >(1.0e-8))
Return the Euler angles composing the given rotation matrix.
Vec2< typename promote< S, T >::type > operator/(S scalar, const Vec2< T > &v)
Divide scalar by each element of the given vector and return the result.
#define OPENVDB_ASSERT(X)
constexpr T zeroVal()
Return the value of type T that corresponds to zero.
#define OPENVDB_IS_POD(Type)
Mat3< T > bezLerp(const Mat3< T0 > &m1, const Mat3< T0 > &m2, const Mat3< T0 > &m3, const Mat3< T0 > &m4, T t)
Quat(T *a)
Constructor with array argument, e.g. float a[4]; Quatf q(a);.
Quat(const Mat3< T1 > &rot)
Constructor given a rotation matrix.
ImageBuf OIIO_API sub(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
bool isApproxEqual(const Type &a, const Type &b, const Type &tolerance)
Return true if a is equal to b to within the given tolerance.
void read(std::istream &is)
OIIO_FORCEINLINE const vint4 & operator+=(vint4 &a, const vint4 &b)
Quat(math::Axis axis, T angle)
Constructor given rotation as axis and angle.
General-purpose arithmetic and comparison routines, most of which accept arbitrary value types (or at...
fpreal64 dot(const CE_VectorT< T > &a, const CE_VectorT< T > &b)
T angle(const Vec2< T > &v1, const Vec2< T > &v2)
bool isUnitary(const MatType &m)
Determine if a matrix is unitary (i.e., rotation or reflection).
T det() const
Determinant of matrix.
Quat(const Mat3< T1 > &rot, UnsafeConstruct)
GLboolean GLboolean GLboolean b
IMATH_HOSTDEVICE const Vec2< S > & operator*=(Vec2< S > &v, const Matrix22< T > &m) IMATH_NOEXCEPT
Vector-matrix multiplication: v *= m.
MatType scale(const Vec3< typename MatType::value_type > &s)
Return a matrix that scales by s.
T & x()
Reference to the component, e.g. v.x() = 4.5f;.
T trace() const
Trace of matrix.
void write(std::ostream &os) const
OIIO_FORCEINLINE const vint4 & operator-=(vint4 &a, const vint4 &b)
Vec3< typename promote< T, typename Coord::ValueType >::type > operator+(const Vec3< T > &v0, const Coord &v1)
Allow a Coord to be added to or subtracted from a Vec3.
GLubyte GLubyte GLubyte GLubyte w
Quat< T > slerp(const Quat< T > &q1, const Quat< T > &q2, T t, T tolerance=0.00001)
Linear interpolation between the two quaternions.
ImageBuf OIIO_API add(Image_or_Const A, Image_or_Const B, ROI roi={}, int nthreads=0)
ImageBuf OIIO_API zero(ROI roi, int nthreads=0)
Quat(const Vec3< T > &axis, T angle)
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
bool operator==(const Vec3< T0 > &v0, const Vec3< T1 > &v1)
Equality operator, does exact floating point comparisons.
T length() const
Length of the vector.
#define OPENVDB_THROW(exception, message)
std::ostream & operator<<(std::ostream &os, const BBox< Vec3T > &b)