Developer Documentation
SkeletonTransform.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39 * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43 * *
44 * $Revision$ *
45 * $LastChangedBy$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49 
50 #include "SkeletonTransform.hh"
52 //-----------------------------------------------------------------------------
53 
55 SkeletonTransform::SkeletonTransform(Skeleton& _skeleton) : skeleton_(_skeleton)
56 {
57  refPose_ = skeleton_.referencePose();
58 }
59 
60 //-----------------------------------------------------------------------------
61 
71 void SkeletonTransform::scaleSkeleton(double _factor, Skeleton::Pose* _pose) {
72 
73  // note: scaling the root joints is important since this controls e.g. the size of foot steps
74 
75  if ( _pose == 0)
76  _pose = refPose_;
77 
78  //scale bones in the given pose
79  for (Skeleton::Iterator it = skeleton_.begin(); it != skeleton_.end(); ++it )
80  _pose->setLocalTranslation( (*it)->id(), _pose->localTranslation((*it)->id()) * _factor );
81 
82  // if given pose is refPose
83  if ( _pose == refPose_){
84  //scale bones in the animations
85  for (unsigned int a=0; a < skeleton_.animationCount(); a++)
86  for (unsigned int iFrame = 0; iFrame < skeleton_.animation(a)->frameCount(); iFrame++){
87 
88  Skeleton::Pose* pose = skeleton_.animation(a)->pose( iFrame );
89 
90  if ( pose == refPose_ )
91  continue;
92 
93  for (Skeleton::Iterator it = skeleton_.begin(); it != skeleton_.end(); ++it )
94  pose->setLocalTranslation( (*it)->id(), pose->localTranslation((*it)->id()) * _factor );
95  }
96  }
97 }
98 
99 //-----------------------------------------------------------------------------
100 
113 
114  if ( _pose == 0)
115  _pose = refPose_;
116 
117  //apply the transformation to given pose
118  ACG::Vec3d position = _pose->globalTranslation( 0 );
119  _pose->setGlobalTranslation( 0, position + _translation );
120 
121  // apply to all animations if the refpose was changed
122  if ( _pose == refPose_ ){
123 
124  // apply transformation to all frames of all animations
125  for (unsigned int a=0; a < skeleton_.animationCount(); a++)
126  for (unsigned int iFrame = 0; iFrame < skeleton_.animation(a)->frameCount(); iFrame++){
127 
128  Skeleton::Pose* pose = skeleton_.animation(a)->pose( iFrame );
129 
130  if ( pose == refPose_ )
131  continue;
132 
133  ACG::Vec3d position = pose->globalTranslation( 0 );
134  pose->setGlobalTranslation( 0, position + _translation );
135  }
136  }
137 }
138 
139 //-----------------------------------------------------------------------------
140 
150 
151  if ( _pose == 0)
152  _pose = refPose_;
153 
154  //apply the transformation to given pose
155  ACG::Matrix4x4d local = _pose->localMatrix( 0 );
156  _pose->setLocalMatrix( 0, _transformation * local );
157 
158  // apply to all animations if the refpose was changed
159  if ( _pose == refPose_ ){
160 
161  // apply transformation to all frames of all animations
162  for (unsigned int a=0; a < skeleton_.animationCount(); a++)
163  for (unsigned int iFrame = 0; iFrame < skeleton_.animation(a)->frameCount(); iFrame++){
164 
165  Skeleton::Pose* pose = skeleton_.animation(a)->pose( iFrame );
166 
167  if ( pose == refPose_ )
168  continue;
169 
170  ACG::Matrix4x4d local = pose->localMatrix( 0 );
171  pose->setLocalMatrix( 0, _transformation * local );
172  }
173  }
174 }
175 
176 //-----------------------------------------------------------------------------
177 
192 void SkeletonTransform::transformJoint(Skeleton::Joint* _joint, Matrix4x4 _matrix, bool _keepChildPositions) {
193 
194  if (_joint == 0)
195  return;
196 
197  Matrix4x4 transform;
198  transform.identity();
199 
200  //get transformation matrix
201  Skeleton::Joint* parent = _joint->parent();
202 
203  if ( parent != 0 )
204  // new GlobalMatrix after application of _matrix is: newGlobal = _matrix * activePose->getGlobal( joint )
205  // new LocalMatrix : activePose->getGlobalInv( parent->getID() ) * newGlobal
206  // Transformation from LocalMatrix to new LocalMatrix:
207  transform = refPose_->globalMatrixInv( parent->id() ) * _matrix * refPose_->globalMatrix( _joint->id() ) * refPose_->localMatrixInv( _joint->id() );
208  else
209  // the transformation for the root joint has to be applied directly
210  // _matrix defines a post-multiplication but we need a pre-multiplication matrix X in order to apply
211  // the transformation to all frames: _matrix * Global = Global * X --> X = GlobalInverse * _matrix * global
212  transform = refPose_->globalMatrixInv( _joint->id() ) * _matrix * refPose_->globalMatrix( _joint->id() );
213 
214 
215  //transform refPose
216  if ( parent != 0 ){
217 
218  Matrix4x4 newMatrix = transform * refPose_->localMatrix( _joint->id() );
219  refPose_->setLocalMatrix( _joint->id(), newMatrix, !_keepChildPositions); //keep child for local means !keepChild global
220 
221  } else {
222  //directly apply the global transformation
223  Matrix4x4 newMatrix = refPose_->globalMatrix( _joint->id() ) * transform;
224  refPose_->setLocalMatrix( _joint->id(), newMatrix, !_keepChildPositions);
225  }
226 
227  // apply transformation to all frames of all animations
228  for (unsigned int a=0; a < skeleton_.animationCount(); a++)
229  for (unsigned int iFrame = 0; iFrame < skeleton_.animation(a)->frameCount(); iFrame++){
230 
231  Skeleton::Pose* pose = skeleton_.animation(a)->pose( iFrame );
232 
233  if ( parent != 0 ){
234 
235  //transform the local matrix
236  Matrix4x4 newMatrix = transform * pose->localMatrix( _joint->id() );
237  pose->setLocalMatrix( _joint->id(), newMatrix, !_keepChildPositions);
238 
239  // the transformation may have changed two things
240  // 1. due to the changed length of neighboring bones the rotation
241  // angle changes this has to be corrected by rotating the coord-frame
242  // 2. the length of the bone to a child may have changed. Check that
243  // the length is the same like in the refPose
244 
245  } else {
246 
247  //directly apply the global transformation
248  Matrix4x4 newMatrix = pose->globalMatrix( _joint->id() ) * transform;
249 
250  pose->setLocalMatrix( _joint->id(), newMatrix, !_keepChildPositions);
251  }
252  }
253 }
254 
255 //-----------------------------------------------------------------------------
256 
271 void SkeletonTransform::translateJoint(Skeleton::Joint* _joint, ACG::Vec3d _translation, bool _keepChildPositions) {
272  ACG::GLMatrixd transformation;
273  transformation.identity();
274  transformation.translate( _translation );
275 
276  transformJoint(_joint, transformation, _keepChildPositions);
277 }
278 
279 //-----------------------------------------------------------------------------
280 
291 void SkeletonTransform::rotateJoint(Skeleton::Joint* _joint, Skeleton::Pose* _pose, Matrix4x4 _rotation, bool _applyToWholeAnimation) {
292 
293  if (_joint == 0)
294  return;
295 
296  if ( fabs(1.0 - determinant(_rotation)) > 1E-6 ){
297  std::cerr << "Cannot rotate joint. Matrix is not a rotation matrix (det:" << determinant(_rotation) << ")" << std::endl;
298  return;
299  }
300 
301  Matrix4x4 transform;
302  transform.identity();
303 
304  //get transformation matrix
305  Skeleton::Joint* parent = _joint->parent();
306 
307  if ( parent != 0 )
308  // new GlobalMatrix after application of _matrix is: newGlobal = _matrix * activePose->getGlobal( joint )
309  // new LocalMatrix : activePose->getGlobalInv( parent->getID() ) * newGlobal
310  // Transformation from LocalMatrix to new LocalMatrix:
311  transform = _pose->globalMatrixInv( parent->id() ) * _rotation * _pose->globalMatrix( _joint->id() ) * _pose->localMatrixInv( _joint->id() );
312  else
313  // the transformation for the root joint has to be applied directly
314  // _matrix defines a post-multiplication but we need a pre-multiplication matrix X in order to apply
315  // the transformation to all frames: _matrix * Global = Global * X --> X = GlobalInverse * _matrix * global
316  transform = _pose->globalMatrixInv( _joint->id() ) * _rotation * _pose->globalMatrix( _joint->id() );
317 
318 
319  //transform pose
320  if ( (_pose == refPose_) || !_applyToWholeAnimation ){
321 
322  if ( parent != 0 ){
323 
324  Matrix4x4 newMatrix = transform * _pose->localMatrix( _joint->id() );
325  _pose->setLocalMatrix( _joint->id(), newMatrix);
326 
327  } else {
328 
329  //directly apply the global transformation
330  Matrix4x4 newMatrix = _pose->globalMatrix( _joint->id() ) * transform;
331  _pose->setLocalMatrix( _joint->id(), newMatrix);
332  }
333  }
334 
335  //TODO don't apply to all frames but only to those belonging to the same animation as _pose
336  if ( _applyToWholeAnimation ){
337  // apply transformation to all frames of all animations
338  for (unsigned int a=0; a < skeleton_.animationCount(); a++)
339  for (unsigned int iFrame = 0; iFrame < skeleton_.animation(a)->frameCount(); iFrame++){
340 
341  Skeleton::Pose* pose = skeleton_.animation(a)->pose( iFrame );
342 
343  if ( parent != 0 ){
344  //transform the local matrix
345  Matrix4x4 newMatrix = transform * pose->localMatrix( _joint->id() );
346 
347  pose->setLocalMatrix( _joint->id(), newMatrix);
348 
349  } else {
350 
351  //directly apply the global transformation
352  Matrix4x4 newMatrix = pose->globalMatrix( _joint->id() ) * transform;
353 
354  pose->setLocalMatrix( _joint->id(), newMatrix);
355  }
356  }
357  }
358 }
359 
360 //-----------------------------------------------------------------------------
361 
362 
364  double value;
365 
366  value =
367  _m(0,3) * _m(1,2) * _m(2,1) * _m(3,0)-_m(0,2) * _m(1,3) * _m(2,1) * _m(3,0)-_m(0,3) * _m(1,1) * _m(2,2) * _m(3,0)+_m(0,1) * _m(1,3) * _m(2,2) * _m(3,0)+
368  _m(0,2) * _m(1,1) * _m(2,3) * _m(3,0)-_m(0,1) * _m(1,2) * _m(2,3) * _m(3,0)-_m(0,3) * _m(1,2) * _m(2,0) * _m(3,1)+_m(0,2) * _m(1,3) * _m(2,0) * _m(3,1)+
369  _m(0,3) * _m(1,0) * _m(2,2) * _m(3,1)-_m(0,0) * _m(1,3) * _m(2,2) * _m(3,1)-_m(0,2) * _m(1,0) * _m(2,3) * _m(3,1)+_m(0,0) * _m(1,2) * _m(2,3) * _m(3,1)+
370  _m(0,3) * _m(1,1) * _m(2,0) * _m(3,2)-_m(0,1) * _m(1,3) * _m(2,0) * _m(3,2)-_m(0,3) * _m(1,0) * _m(2,1) * _m(3,2)+_m(0,0) * _m(1,3) * _m(2,1) * _m(3,2)+
371  _m(0,1) * _m(1,0) * _m(2,3) * _m(3,2)-_m(0,0) * _m(1,1) * _m(2,3) * _m(3,2)-_m(0,2) * _m(1,1) * _m(2,0) * _m(3,3)+_m(0,1) * _m(1,2) * _m(2,0) * _m(3,3)+
372  _m(0,2) * _m(1,0) * _m(2,1) * _m(3,3)-_m(0,0) * _m(1,2) * _m(2,1) * _m(3,3)-_m(0,1) * _m(1,0) * _m(2,2) * _m(3,3)+_m(0,0) * _m(1,1) * _m(2,2) * _m(3,3);
373 
374  return value;
375 }
Iterator class for the skeleton.
Definition: SkeletonT.hh:88
void scaleSkeleton(double _factor, Skeleton::Pose *_pose=0)
scale all bones of the skeleton by the given factor
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
Definition: GLMatrixT.cc:102
void setGlobalTranslation(unsigned int _joint, const Vector &_position, bool _keepGlobalChildPositions=true)
Sets the global translation vector.
Definition: PoseT.cc:255
Represents a single joint in the skeleton.
Definition: JointT.hh:66
virtual Matrix globalMatrixInv(unsigned int _joint) const
Simply returns the inverse of the global matrix.
Definition: PoseT.cc:273
Functions for geometric operations related to angles.
Vector globalTranslation(unsigned int _joint)
Returns the global translation vector.
Definition: PoseT.cc:233
const Matrix & globalMatrix(unsigned int _joint) const
Returns the global matrix for the given joint.
Definition: PoseT.cc:199
Iterator begin()
Iterator over joints of the skeletal tree in TOP-DOWN order (from root to leafs)
Definition: SkeletonT.cc:714
void translateSkeleton(ACG::Vec3d _translation, Skeleton::Pose *_pose=0)
translate the skeleton
static double determinant(Matrix4x4 &_m)
compute determinant to check if matrix is rotation matrix
unsigned int id()
returns the joint id
Definition: JointT.cc:103
A general pose, used to store the frames of the animation.
Definition: PoseT.hh:68
Animation * animation(std::string _name)
Returns a pointer to the animation to the given name.
Definition: SkeletonT.cc:858
void rotateJoint(Skeleton::Joint *_joint, Skeleton::Pose *_pose, Matrix4x4 _rotation, bool _applyToWholeAnimation=true)
rotate a joint in an arbitrary Pose
const Matrix & localMatrix(unsigned int _joint) const
Returns the local matrix for the given joint.
Definition: PoseT.cc:110
void identity()
setup an identity matrix
Definition: Matrix4x4T.cc:256
Matrix localMatrixInv(unsigned int _joint) const
Simply returns the inverse of the local matrix.
Definition: PoseT.cc:182
Vector localTranslation(unsigned int _joint)
Returns the local translation vector.
Definition: PoseT.cc:145
void transformJoint(Skeleton::Joint *_joint, Matrix4x4 _matrix, bool _keepChildPositions=true)
apply a transformation to a joint in the refPose
Iterator end()
Compare an iterator with the return value of this method to test if it is done.
Definition: SkeletonT.cc:725
unsigned int animationCount()
Returns the number of animations stored in this skeleton.
Definition: SkeletonT.cc:971
void setLocalTranslation(unsigned int _joint, const Vector &_position, bool _keepLocalChildPositions=true)
Sets the local translation vector.
Definition: PoseT.cc:167
Joint * parent()
Returns the parent joint.
Definition: JointT.cc:162
SkeletonTransform(Skeleton &_skeleton)
Le constructeur.
void transformSkeleton(Matrix4x4 _transformation, Skeleton::Pose *_pose=0)
transform the skeleton
void translateJoint(Skeleton::Joint *_joint, ACG::Vec3d _translation, bool _keepChildPositions=true)
apply a translation to a joint in the refPose
void setLocalMatrix(unsigned int _joint, const Matrix &_local, bool _keepLocalChildPositions=true)
Sets the local coordinate system.
Definition: PoseT.cc:126
Pose * referencePose()
Returns a pointer to the reference pose.
Definition: SkeletonT.cc:761