Commit 8a121cc0 authored by Dirk Wilden's avatar Dirk Wilden
Browse files

dual quaternion blend skinning

git-svn-id: http://www.openflipper.org/svnrepo/OpenFlipper/branches/Free@9842 383ad7c9-94d9-4d36-a494-682f7c89f535
parent 525adbc9
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2010 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenFlipper. *
* *
* OpenFlipper is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision: 9595 $ *
* $Author: wilden $ *
* $Date: 2010-06-17 12:48:23 +0200 (Thu, 17 Jun 2010) $ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS DualQuaternionT - IMPLEMENTATION
//
//=============================================================================
#define ACG_DUALQUATERNIONT_C
//== INCLUDES =================================================================
#include "DualQuaternionT.hh"
#include <iostream>
//== IMPLEMENTATION ==========================================================
namespace ACG {
//-----------------------------------------------------------------------------
/// Default constructor ( constructs an identity dual quaternion )
template <typename Scalar>
DualQuaternionT<Scalar>::DualQuaternionT(){
*this = DualQuaternion::identity();
}
//-----------------------------------------------------------------------------
/// Copy constructor
template <typename Scalar>
DualQuaternionT<Scalar>::DualQuaternionT(const DualQuaternion& _other){
real_ = _other.real_;
dual_ = _other.dual_;
}
//-----------------------------------------------------------------------------
/// Construct from given real,dual parts
template <typename Scalar>
DualQuaternionT<Scalar>::DualQuaternionT(const Quaternion& _real, const Quaternion& _dual){
real_ = _real;
dual_ = _dual;
}
//-----------------------------------------------------------------------------
/// Construct from 8 scalars
template <typename Scalar>
DualQuaternionT<Scalar>::DualQuaternionT(Scalar _Rw, Scalar _Rx, Scalar _Ry, Scalar _Rz,
Scalar _Dw, Scalar _Dx, Scalar _Dy, Scalar _Dz){
real_ = Quaternion(_Rw, _Rx, _Ry, _Rz);
dual_ = Quaternion(_Dw, _Dx, _Dy, _Dz);
}
//-----------------------------------------------------------------------------
/// Construct from a rotation given as quaternion
template <typename Scalar>
DualQuaternionT<Scalar>::DualQuaternionT(Quaternion _rotation){
real_ = _rotation;
dual_ = Quaternion(0.0,0.0,0.0,0.0);
}
//-----------------------------------------------------------------------------
/// Construct from a translatation given as a vector
template <typename Scalar>
DualQuaternionT<Scalar>::DualQuaternionT(const Vec3& _translation){
real_.identity();
dual_ = Quaternion( 0.0, 0.5 * _translation[0], 0.5 * _translation[1], 0.5 * _translation[2] );
}
//-----------------------------------------------------------------------------
/// Construct from a translation+rotation
template <typename Scalar>
DualQuaternionT<Scalar>::DualQuaternionT(const Vec3& _translation, const Quaternion& _rotation){
real_ = _rotation;
dual_ = Quaternion( 0.0, 0.5 * _translation[0], 0.5 * _translation[1], 0.5 * _translation[2] );
dual_ *= real_;
}
//-----------------------------------------------------------------------------
/// Construct from a rigid transformation given as matrix
template <typename Scalar>
DualQuaternionT<Scalar>::DualQuaternionT(const Matrix& _transformation){
real_ = Quaternion(_transformation); //the quaternion constructor ignores the translation
dual_ = Quaternion( 0.0, 0.5 * _transformation(0,3), 0.5 * _transformation(1,3), 0.5 * _transformation(2,3) );
dual_ *= real_;
}
//-----------------------------------------------------------------------------
/// identity dual quaternion [ R(1, 0, 0, 0), D(0,0,0,0) ]
template <typename Scalar>
DualQuaternionT<Scalar> DualQuaternionT<Scalar>::identity(){
Quaternion real;
real.identity();
Quaternion dual = Quaternion(0.0, 0.0, 0.0, 0.0);
return DualQuaternion( real, dual );
}
//-----------------------------------------------------------------------------
/// zero dual quaternion [ R(0, 0, 0, 0), D(0,0,0,0) ]
template <typename Scalar>
DualQuaternionT<Scalar> DualQuaternionT<Scalar>::zero(){
Quaternion real = Quaternion(0.0, 0.0, 0.0, 0.0);
Quaternion dual = Quaternion(0.0, 0.0, 0.0, 0.0);
return DualQuaternion( real, dual );
}
//-----------------------------------------------------------------------------
/// conjugate dual quaternion
template <typename Scalar>
DualQuaternionT<Scalar> DualQuaternionT<Scalar>::conjugate() const {
return DualQuaternion( real_.conjugate(), dual_.conjugate() );
}
//-----------------------------------------------------------------------------
/// invert dual quaternion
template <typename Scalar>
DualQuaternionT<Scalar> DualQuaternionT<Scalar>::invert() const {
double sqrLen0 = real_.sqrnorm();
double sqrLenE = 2.0 * (real_ | dual_);
if ( sqrLen0 > 0.0 ){
double invSqrLen0 = 1.0/sqrLen0;
double invSqrLenE = -sqrLenE/(sqrLen0*sqrLen0);
DualQuaternion conj = conjugate();
conj.real_ = invSqrLen0 * conj.real_;
conj.dual_ = invSqrLen0 * conj.dual_ + invSqrLenE * conj.real_;
return conj;
} else
return DualQuaternion::zero();
}
//-----------------------------------------------------------------------------
/// normalize dual quaternion
template <typename Scalar>
void DualQuaternionT<Scalar>::normalize() {
double magn = 1.0/real_.norm();
double magnSqr = 1.0/real_.sqrnorm();
//normalize rotation
real_ *= magn;
dual_ *= magn;
//normalize the rest
dual_ -= ((real_| dual_)* magnSqr) * real_;
}
//-----------------------------------------------------------------------------
/// dual quaternion comparison
template <typename Scalar>
bool DualQuaternionT<Scalar>::operator==(const DualQuaternion& _other) const {
return (_other.real_ == real_) && (_other.dual_ == dual_);
}
//-----------------------------------------------------------------------------
/// dual quaternion comparison
template <typename Scalar>
bool DualQuaternionT<Scalar>::operator!=(const DualQuaternion& _other) const {
return (_other.real_ != real_) || (_other.dual_ != dual_);
}
//-----------------------------------------------------------------------------
/// addition
template <typename Scalar>
DualQuaternionT<Scalar> DualQuaternionT<Scalar>::operator+(const DualQuaternion& _other) const {
return DualQuaternion( real_ + _other.real_, dual_ + _other.dual_ );
}
//-----------------------------------------------------------------------------
/// addition
template <typename Scalar>
DualQuaternionT<Scalar>& DualQuaternionT<Scalar>::operator+=(const DualQuaternion& _other) {
real_ = real_ + _other.real_;
dual_ = dual_ + _other.dual_;
return (*this);
}
//-----------------------------------------------------------------------------
/// substraction
template <typename Scalar>
DualQuaternionT<Scalar> DualQuaternionT<Scalar>::operator-(const DualQuaternion& _other) const {
return DualQuaternion( real_ - _other.real_, dual_ - _other.dual_ );
}
//-----------------------------------------------------------------------------
/// substraction
template <typename Scalar>
DualQuaternionT<Scalar>& DualQuaternionT<Scalar>::operator-=(const DualQuaternion& _other) {
real_ -= _other.real_;
dual_ -= _other.dual_;
return (*this);
}
//-----------------------------------------------------------------------------
/// dualQuaternion * dualQuaternion
template <typename Scalar>
DualQuaternionT<Scalar> DualQuaternionT<Scalar>::operator*(const DualQuaternion& _q) const {
return DualQuaternion( real_ * _q.real_, real_ * _q.dual_ + dual_ * _q.real_ );
}
//-----------------------------------------------------------------------------
/// dualQuaternion *= dualQuaternion
template <typename Scalar>
DualQuaternionT<Scalar>& DualQuaternionT<Scalar>::operator*=(const DualQuaternion& _q){
dual_ = real_ * _q.dual_ + dual_ * _q.real_;
real_ *= _q.real_;
return (*this);
}
//-----------------------------------------------------------------------------
/// dualQuaternion * scalar
template <typename Scalar>
DualQuaternionT<Scalar> DualQuaternionT<Scalar>::operator*(const Scalar& _scalar) const {
DualQuaternion q;
q.real_ = real_ * _scalar;
q.dual_ = dual_ * _scalar;
return q;
}
//-----------------------------------------------------------------------------
/// linear interpolation of dual quaternions. Result is normalized afterwards.
template <typename Scalar>
DualQuaternionT<Scalar> DualQuaternionT<Scalar>::interpolate(std::vector<double>& _weights, const std::vector<DualQuaternion>& _dualQuaternions)
{
if ( (_weights.size() != _dualQuaternions.size()) || (_weights.size() == 0) ){
std::cerr << "Cannot interpolate dual quaternions ( weights: " << _weights.size() << ", DQs: " << _dualQuaternions.size() << std::endl;
return DualQuaternionT::zero();
}
// Find max weight for pivoting to that quaternion,
// so shortest arc is taken (see: 'coping antipodality' in the paper )
uint pivotID = 0;
for (uint i=1; i<_dualQuaternions.size(); i++)
if (_weights[pivotID] < _weights[i])
pivotID = i;
DualQuaternion pivotDQ = _dualQuaternions[ pivotID ];
Quaternion pivotQ = pivotDQ.real_;
DualQuaternion res = DualQuaternion::zero();
for (uint i=0; i<_dualQuaternions.size(); i++){
DualQuaternion currentDQ = _dualQuaternions[i];
Quaternion currentQ = currentDQ.real_;
// Make sure dot product is >= 0
if ( ( currentQ | pivotQ ) < 0.0 )
_weights[i] = -_weights[i];
res += _dualQuaternions[i] * _weights[i];
}
res.normalize();
return res;
}
//-----------------------------------------------------------------------------
/// transform a given point with this dual quaternion
template <typename Scalar>
VectorT<Scalar,3> DualQuaternionT<Scalar>::transform_point(const Vec3& _point) const
{
///TODO check if this is a unit dual quaternion
// for details about the calculation see the paper (algorithm 1)
Vec3 p(_point);
double r = real_[0];
Vec3 rv = Vec3(real_[1], real_[2], real_[3]);
double d = dual_[0];
Vec3 dv = Vec3(dual_[1], dual_[2], dual_[3]);
Vec3 tempVec = (rv % p) + r * p;
p+=2.0*(rv % tempVec);
Vec3 t = dv % rv;
t+= d * rv;
t+= -r*dv;
p+=-2.0*t;
return p;
}
//-----------------------------------------------------------------------------
/// transform a given point with this dual quaternion
template <typename Scalar>
VectorT<Scalar,3> DualQuaternionT<Scalar>::transform_vector(const Vec3& _point) const
{
///TODO check if this is a unit dual quaternion
// for details about the calculation see the paper (algorithm 1)
Vec3 p(_point);
double r = real_[0];
Vec3 rv = Vec3(real_[1], real_[2], real_[3]);
double d = dual_[0];
Vec3 dv = Vec3(dual_[1], dual_[2], dual_[3]);
Vec3 tempVec = (rv % p) + r * p;
p+=2.0*(rv % tempVec);
return p;
}
//-----------------------------------------------------------------------------
/// print some info about the DQ
template <typename Scalar>
void DualQuaternionT<Scalar>::printInfo(){
std::cerr << "Real Part:" << std::endl;
real_.print_info();
std::cerr << "Dual Part:" << std::endl;
dual_.print_info();
}
//-----------------------------------------------------------------------------
//=============================================================================
} // namespace ACG
//=============================================================================
\ No newline at end of file
/*===========================================================================*\
* *
* OpenFlipper *
* Copyright (C) 2001-2010 by Computer Graphics Group, RWTH Aachen *
* www.openflipper.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenFlipper. *
* *
* OpenFlipper is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenFlipper is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenFlipper. If not, *
* see <http://www.gnu.org/licenses/>. *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision: 9595 $ *
* $Author: wilden $ *
* $Date: 2010-06-17 12:48:23 +0200 (Thu, 17 Jun 2010) $ *
* *
\*===========================================================================*/
//=============================================================================
//
// CLASS DualQuaternion
//
//=============================================================================
#ifndef ACG_DUALQUATERNION_HH
#define ACG_DUALQUATERNION_HH
//== INCLUDES =================================================================
#include "QuaternionT.hh"
//== NAMESPACES ==============================================================
namespace ACG {
//== CLASS DEFINITION =========================================================
/**
DualQuaternion class for representing rigid motions in 3d
*/
template <class Scalar>
class DualQuaternionT
{
public:
typedef QuaternionT<Scalar> Quaternion;
typedef DualQuaternionT<Scalar> DualQuaternion;
typedef VectorT<Scalar,3> Vec3;
typedef VectorT<Scalar,4> Vec4;
typedef Matrix4x4T<Scalar> Matrix;
/// real and dual quaternion parts
Quaternion real_;
Quaternion dual_;
// Constructors
//
/// Default constructor ( constructs an identity dual quaternion )
DualQuaternionT();
/// Copy constructor
DualQuaternionT(const DualQuaternion& _other);
/// Construct from given real,dual parts
DualQuaternionT(const Quaternion& _real, const Quaternion& _dual);
/// Construct from 8 scalars
DualQuaternionT(Scalar _Rw, Scalar _Rx, Scalar _Ry, Scalar _Rz,
Scalar _Dw, Scalar _Dx, Scalar _Dy, Scalar _Dz);
/// Construct from a rotation given as quaternion
DualQuaternionT(Quaternion _rotation);
/// Construct from a translatation given as a vector
DualQuaternionT(const Vec3& _translation);
/// Construct from a translation+rotation
DualQuaternionT(const Vec3& _translation, const Quaternion& _rotation);
/// Construct from a rigid transformation given as matrix
DualQuaternionT(const Matrix& _transformation);
// default quaternions
/// identity dual quaternion [ R(1, 0, 0, 0), D(0,0,0,0) ]
static DualQuaternion identity();
/// zero dual quaternion [ R(0, 0, 0, 0), D(0,0,0,0) ]
static DualQuaternion zero();
// Operators
//
/// conjugate dual quaternion
DualQuaternion conjugate() const;
/// invert dual quaternion
DualQuaternion invert() const;
/// normalize dual quaternion
void normalize();
/// dual quaternion comparison
bool operator==(const DualQuaternion& _other) const;
bool operator!=(const DualQuaternion& _other) const;
/// addition
DualQuaternion operator+(const DualQuaternion& _other) const;
DualQuaternion& operator+=(const DualQuaternion& _other);
/// substraction
DualQuaternion operator-(const DualQuaternion& _other) const;
DualQuaternion& operator-=(const DualQuaternion& _other);
/// dualQuaternion * dualQuaternion
DualQuaternion operator*(const DualQuaternion& _q) const;
/// dualQuaternion * scalar
DualQuaternion operator*(const Scalar& _scalar) const;
/// dualQuaternion *= dualQuaternion
DualQuaternion& operator*=(const DualQuaternion& _q);
/// linear interpolation of dual quaternions. Result is normalized afterwards
static DualQuaternion interpolate(std::vector<double>& _weights, const std::vector<DualQuaternion>& _dualQuaternions);
/// Transform a point with the dual quaternion
Vec3 transform_point(const Vec3& _point) const;
/// Transform a vector with the dual quaternion
Vec3 transform_vector(const Vec3& _point) const;
/// print some info about the DQ
void printInfo();
};
typedef DualQuaternionT<float> DualQuaternionf;
typedef DualQuaternionT<double> DualQuaterniond;
//=============================================================================
} // namespace ACG
//=============================================================================
#if defined(INCLUDE_TEMPLATES) && !defined(ACG_DUALQUATERNIONT_C)
#define ACG_QUATERNIONT_TEMPLATES
#include "DualQuaternionT.cc"
#endif
//=============================================================================
#endif // ACG_DUALQUATERNION_HH defined
//=============================================================================
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment