📄 imathquat.h
字号:
///////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
// Digital Ltd. LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Industrial Light & Magic nor the names of
// its contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////
#ifndef INCLUDED_IMATHQUAT_H
#define INCLUDED_IMATHQUAT_H
//----------------------------------------------------------------------
//
// template class Quat<T>
//
// "Quaternions came from Hamilton ... and have been an unmixed
// evil to those who have touched them in any way. Vector is a
// useless survival ... and has never been of the slightest use
// to any creature."
//
// - Lord Kelvin
//
// This class implements the quaternion numerical type -- you
// will probably want to use this class to represent orientations
// in R3 and to convert between various euler angle reps. You
// should probably use Imath::Euler<> for that.
//
//----------------------------------------------------------------------
#include "ImathExc.h"
#include "ImathMatrix.h"
#include <iostream>
namespace Imath {
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
// Disable MS VC++ warnings about conversion from double to float
#pragma warning(disable:4244)
#endif
template <class T>
class Quat;
template<class T>
Quat<T> slerp (const Quat<T> &q1,const Quat<T> &q2, T t);
template<class T>
Quat<T> squad (const Quat<T> &q1,const Quat<T> &q2,
const Quat<T> &qa,const Quat<T> &qb, T t);
template<class T>
void intermediate (const Quat<T> &q0, const Quat<T> &q1,
const Quat<T> &q2, const Quat<T> &q3,
Quat<T> &qa, Quat<T> &qb);
template <class T>
class Quat
{
public:
T r; // real part
Vec3<T> v; // imaginary vector
//-----------------------------------------------------
// Constructors - default constructor is identity quat
//-----------------------------------------------------
Quat() : r(1), v(0,0,0) {}
template <class S>
Quat( const Quat<S>& q) : r(q.r), v(q.v) {}
Quat( T s, T i, T j, T k ) : r(s), v(i,j,k) {}
Quat( T s, Vec3<T> d ) : r(s), v(d) {}
static Quat<T> identity() { return Quat<T>(); }
//------------------------------------------------
// Basic Algebra - Operators and Methods
// The operator return values are *NOT* normalized
//
// operator^ is 4D dot product
// operator/ uses the inverse() quaternion
// operator~ is conjugate -- if (S+V) is quat then
// the conjugate (S+V)* == (S-V)
//
// some operators (*,/,*=,/=) treat the quat as
// a 4D vector when one of the operands is scalar
//------------------------------------------------
const Quat<T>& operator= (const Quat<T>&);
const Quat<T>& operator*= (const Quat<T>&);
const Quat<T>& operator*= (T);
const Quat<T>& operator/= (const Quat<T>&);
const Quat<T>& operator/= (T);
const Quat<T>& operator+= (const Quat<T>&);
const Quat<T>& operator-= (const Quat<T>&);
T& operator[] (int index); // as 4D vector
T operator[] (int index) const;
template <class S> bool operator == (const Quat<S> &q) const;
template <class S> bool operator != (const Quat<S> &q) const;
Quat<T>& invert(); // this -> 1 / this
Quat<T> inverse() const;
Quat<T>& normalize(); // returns this
Quat<T> normalized() const;
T length() const; // in R4
//-----------------------
// Rotation conversion
//-----------------------
Quat<T>& setAxisAngle(const Vec3<T>& axis, T radians);
Quat<T>& setRotation(const Vec3<T>& fromDirection,
const Vec3<T>& toDirection);
T angle() const;
Vec3<T> axis() const;
Matrix33<T> toMatrix33() const;
Matrix44<T> toMatrix44() const;
Quat<T> log() const;
Quat<T> exp() const;
private:
void setRotationInternal (const Vec3<T>& f0,
const Vec3<T>& t0,
Quat<T> &q);
};
//--------------------
// Convenient typedefs
//--------------------
typedef Quat<float> Quatf;
typedef Quat<double> Quatd;
//---------------
// Implementation
//---------------
template<class T>
inline const Quat<T>& Quat<T>::operator= (const Quat<T>& q)
{
r = q.r;
v = q.v;
return *this;
}
template<class T>
inline const Quat<T>& Quat<T>::operator*= (const Quat<T>& q)
{
T rtmp = r * q.r - (v ^ q.v);
v = r * q.v + v * q.r + v % q.v;
r = rtmp;
return *this;
}
template<class T>
inline const Quat<T>& Quat<T>::operator*= (T t)
{
r *= t;
v *= t;
return *this;
}
template<class T>
inline const Quat<T>& Quat<T>::operator/= (const Quat<T>& q)
{
*this = *this * q.inverse();
return *this;
}
template<class T>
inline const Quat<T>& Quat<T>::operator/= (T t)
{
r /= t;
v /= t;
return *this;
}
template<class T>
inline const Quat<T>& Quat<T>::operator+= (const Quat<T>& q)
{
r += q.r;
v += q.v;
return *this;
}
template<class T>
inline const Quat<T>& Quat<T>::operator-= (const Quat<T>& q)
{
r -= q.r;
v -= q.v;
return *this;
}
template<class T>
inline T& Quat<T>::operator[] (int index)
{
return index ? v[index-1] : r;
}
template<class T>
inline T Quat<T>::operator[] (int index) const
{
return index ? v[index-1] : r;
}
template <class T>
template <class S>
inline bool
Quat<T>::operator == (const Quat<S> &q) const
{
return r == q.r && v == q.v;
}
template <class T>
template <class S>
inline bool
Quat<T>::operator != (const Quat<S> &q) const
{
return r != q.r || v != q.v;
}
template<class T>
inline T operator^ (const Quat<T>& q1,const Quat<T>& q2)
{
return q1.r * q2.r + (q1.v ^ q2.v);
}
template <class T>
inline T Quat<T>::length() const
{
return Math<T>::sqrt( r * r + (v ^ v) );
}
template <class T>
inline Quat<T>& Quat<T>::normalize()
{
if ( T l = length() ) { r /= l; v /= l; }
else { r = 1; v = Vec3<T>(0); }
return *this;
}
template <class T>
inline Quat<T> Quat<T>::normalized() const
{
if ( T l = length() ) return Quat( r / l, v / l );
return Quat();
}
template<class T>
inline Quat<T> Quat<T>::inverse() const
{
// 1 Q*
// - = ---- where Q* is conjugate (operator~)
// Q Q* Q and (Q* Q) == Q ^ Q (4D dot)
T qdot = *this ^ *this;
return Quat( r / qdot, -v / qdot );
}
template<class T>
inline Quat<T>& Quat<T>::invert()
{
T qdot = (*this) ^ (*this);
r /= qdot;
v = -v / qdot;
return *this;
}
template<class T>
T
angle4D (const Quat<T> &q1, const Quat<T> &q2)
{
//
// Compute the angle between two quaternions,
// interpreting the quaternions as 4D vectors.
//
Quat<T> d = q1 - q2;
T lengthD = Math<T>::sqrt (d ^ d);
Quat<T> s = q1 + q2;
T lengthS = Math<T>::sqrt (s ^ s);
return 2 * Math<T>::atan2 (lengthD, lengthS);
}
template<class T>
Quat<T>
slerp(const Quat<T> &q1,const Quat<T> &q2, T t)
{
//
// Spherical linear interpolation.
// Assumes q1 and q2 are normalized and that q1 != -q2.
//
// This method does *not* interpolate along the shortest
// arc between q1 and q2. If you desire interpolation
// along the shortest arc, and q1^q2 is negative, then
// consider flipping the second quaternion explicitly.
//
// The implementation of squad() depends on a slerp()
// that interpolates as is, without the automatic
// flipping.
//
// Don Hatch explains the method we use here on his
// web page, The Right Way to Calculate Stuff, at
// http://www.plunk.org/~hatch/rightway.php
//
T a = angle4D (q1, q2);
T s = 1 - t;
Quat<T> q = sinx_over_x (s * a) / sinx_over_x (a) * s * q1 +
sinx_over_x (t * a) / sinx_over_x (a) * t * q2;
return q.normalized();
}
template<class T>
Quat<T> spline(const Quat<T> &q0, const Quat<T> &q1,
const Quat<T> &q2, const Quat<T> &q3,
T t)
{
// Spherical Cubic Spline Interpolation -
// from Advanced Animation and Rendering
// Techniques by Watt and Watt, Page 366:
// A spherical curve is constructed using three
// spherical linear interpolations of a quadrangle
// of unit quaternions: q1, qa, qb, q2.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -