Developer Documentation

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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"
51 #include <ACG/Geometry/AlgorithmsAngleT.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
112 void SkeletonTransform::translateSkeleton(ACG::Vec3d _translation, Skeleton::Pose* _pose) {
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
149 void SkeletonTransform::transformSkeleton(Matrix4x4 _transformation, Skeleton::Pose* _pose) {
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
363 double SkeletonTransform::determinant(Matrix4x4& _m) {
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 }
PoseT::globalMatrixInv
virtual Matrix globalMatrixInv(unsigned int _joint) const
Simply returns the inverse of the global matrix.
Definition: PoseT.cc:273
PoseT::setGlobalTranslation
void setGlobalTranslation(unsigned int _joint, const Vector &_position, bool _keepGlobalChildPositions=true)
Sets the global translation vector.
Definition: PoseT.cc:255
PoseT::localTranslation
Vector localTranslation(unsigned int _joint)
Returns the local translation vector.
Definition: PoseT.cc:145
SkeletonT::referencePose
Pose * referencePose()
Returns a pointer to the reference pose.
Definition: SkeletonT.cc:761
SkeletonT::animation
Animation * animation(std::string _name)
Returns a pointer to the animation to the given name.
Definition: SkeletonT.cc:858
PoseT
A general pose, used to store the frames of the animation.
Definition: PoseT.hh:68
SkeletonT::end
Iterator end()
Compare an iterator with the return value of this method to test if it is done.
Definition: SkeletonT.cc:725
SkeletonT::Iterator
Iterator class for the skeleton.
Definition: SkeletonT.hh:88
ACG::GLMatrixT::translate
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
SkeletonTransform::determinant
static double determinant(Matrix4x4 &_m)
compute determinant to check if matrix is rotation matrix
Definition: SkeletonTransform.cc:363
ACG::GLMatrixT< double >
SkeletonT::begin
Iterator begin()
Iterator over joints of the skeletal tree in TOP-DOWN order (from root to leafs)
Definition: SkeletonT.cc:714
SkeletonTransform::translateSkeleton
void translateSkeleton(ACG::Vec3d _translation, Skeleton::Pose *_pose=0)
translate the skeleton
Definition: SkeletonTransform.cc:112
PoseT::localMatrix
const Matrix & localMatrix(unsigned int _joint) const
Returns the local matrix for the given joint.
Definition: PoseT.cc:110
JointT::parent
Joint * parent()
Returns the parent joint.
Definition: JointT.cc:162
OpenMesh::VectorT
Definition: Vector11T.hh:83
SkeletonT::animationCount
unsigned int animationCount()
Returns the number of animations stored in this skeleton.
Definition: SkeletonT.cc:971
PoseT::setLocalTranslation
void setLocalTranslation(unsigned int _joint, const Vector &_position, bool _keepLocalChildPositions=true)
Sets the local translation vector.
Definition: PoseT.cc:167
SkeletonT
Definition: JointT.hh:56
PoseT::globalTranslation
Vector globalTranslation(unsigned int _joint)
Returns the global translation vector.
Definition: PoseT.cc:233
PoseT::localMatrixInv
Matrix localMatrixInv(unsigned int _joint) const
Simply returns the inverse of the local matrix.
Definition: PoseT.cc:182
AlgorithmsAngleT.hh
Functions for geometric operations related to angles.
ACG::Matrix4x4T::identity
void identity()
setup an identity matrix
Definition: Matrix4x4T.cc:256
JointT::id
unsigned int id()
returns the joint id
Definition: JointT.cc:103
PoseT::setLocalMatrix
void setLocalMatrix(unsigned int _joint, const Matrix &_local, bool _keepLocalChildPositions=true)
Sets the local coordinate system.
Definition: PoseT.cc:126
SkeletonTransform::transformSkeleton
void transformSkeleton(Matrix4x4 _transformation, Skeleton::Pose *_pose=0)
transform the skeleton
Definition: SkeletonTransform.cc:149
SkeletonTransform::SkeletonTransform
SkeletonTransform(Skeleton &_skeleton)
Le constructeur.
Definition: SkeletonTransform.cc:55
PoseT::globalMatrix
const Matrix & globalMatrix(unsigned int _joint) const
Returns the global matrix for the given joint.
Definition: PoseT.cc:199
SkeletonTransform::transformJoint
void transformJoint(Skeleton::Joint *_joint, Matrix4x4 _matrix, bool _keepChildPositions=true)
apply a transformation to a joint in the refPose
Definition: SkeletonTransform.cc:192
SkeletonTransform::rotateJoint
void rotateJoint(Skeleton::Joint *_joint, Skeleton::Pose *_pose, Matrix4x4 _rotation, bool _applyToWholeAnimation=true)
rotate a joint in an arbitrary Pose
Definition: SkeletonTransform.cc:291
JointT
Represents a single joint in the skeleton.
Definition: JointT.hh:66
SkeletonTransform::translateJoint
void translateJoint(Skeleton::Joint *_joint, ACG::Vec3d _translation, bool _keepChildPositions=true)
apply a translation to a joint in the refPose
Definition: SkeletonTransform.cc:271
ACG::Matrix4x4T< double >
SkeletonTransform::scaleSkeleton
void scaleSkeleton(double _factor, Skeleton::Pose *_pose=0)
scale all bones of the skeleton by the given factor
Definition: SkeletonTransform.cc:71