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
FileBVH.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 * $Author$ *
46 * $Date$ *
47 * *
48 \*===========================================================================*/
49
50 #include "FileBVH.hh"
51 #include <OpenFlipper/BasePlugin/PluginFunctions.hh>
52
53 #if QT_VERSION >= 0x050000
54 #include <QtWidgets>
55 #else
56 #include <QtGui>
57 #endif
58
59 #include <sstream>
60
61 #include <ACG/Geometry/AlgorithmsAngleT.hh>
62
63 const std::bitset<4> HIERARCHY (static_cast<int>(0));
64 const std::bitset<4> ROOT_DEFINITION (static_cast<int>(1));
65 const std::bitset<4> OPENED_BRACKET (static_cast<int>(2));
66 const std::bitset<4> CLOSED_BRACKET (static_cast<int>(3));
67 const std::bitset<4> OFFSET (static_cast<int>(4));
68 const std::bitset<4> CHANNELS (static_cast<int>(5));
69 const std::bitset<4> JOINT (static_cast<int>(6));
70 const std::bitset<4> ENDSITE (static_cast<int>(7));
71 const std::bitset<4> MOTION (static_cast<int>(8));
72 const std::bitset<4> FRAMES (static_cast<int>(9));
73 const std::bitset<4> FRAME_TIME (static_cast<int>(10));
74 const std::bitset<4> CHANNEL_DATA (static_cast<int>(11));
75
76 //-----------------------------------------------------------------------------
77 //data structures used for parsing
78 enum ChannelType{NotGiven,XP,YP,ZP,XR,YR,ZR}; //contains the informations about the use of this datafield
79
80 class JointInfo{ //for every Joint we will create one such instance during Hirachy parsing. It will contain the informations needed to generate the Transformation from the frame values
81 public:
82 ChannelType dataChannels[6]; //will state which channels information is stored in the current datafields value.
83 unsigned int dataOffset[6]; //will contain the index of the channel in the frame data
84
85 unsigned int channelOffset; //used top keep track of the highest channel currently used
86
87 //constructor
88 //will set proper default values (as the dataChannels will only be written if an according option is found in the file)
89 JointInfo(){
90 channelOffset=0; //we assign the first channelType to the first entry
91 for(int i=0;i<6;i++){ //all channels that are not overwritten are Unused
92 dataChannels[i]=NotGiven;
93 dataOffset[i]=0;
94 }
95 } //end ctor()
96 }; //end class
97
98 //end of data structure
99 //-----------------------------------------------------------------------------
100
101
102
104 FileBVHPlugin::FileBVHPlugin()
105 : ignoreJointScaling_(true),
106 loadOptions_(0),
107 checkJointScaling_(0),
108 loadDefaultButton_(0)
109 {
110 }
111
112 //-----------------------------------------------------------------------------------------------------
113
114 void FileBVHPlugin::initializePlugin() {
115 }
116
117 //-----------------------------------------------------------------------------------------------------
118
119 QString FileBVHPlugin::getLoadFilters() {
120 return QString( tr("Biovision Format files ( *.bvh )") );
121 }
122
123 //-----------------------------------------------------------------------------------------------------
124
125 QString FileBVHPlugin::getSaveFilters() {
126 return QString( tr("Biovision Format files ( *.bvh )") );
127 }
128
129 //-----------------------------------------------------------------------------------------------------
130
131 DataType FileBVHPlugin::supportedType() {
132 DataType type = DATA_SKELETON;
133 return type;
134 }
135
136 //-----------------------------------------------------------------------------------------------------
137
138 void trimString( std::string& _string) {
139 // Trim Both leading and trailing spaces
140
141 size_t start = _string.find_first_not_of(" \t\r\n");
142 size_t end = _string.find_last_not_of(" \t\r\n");
143
144 if(( std::string::npos == start ) || ( std::string::npos == end))
145 _string = "";
146 else
147 _string = _string.substr( start, end-start+1 );
148 }
149
150 //-----------------------------------------------------------------------------------------------------
151
152 int FileBVHPlugin::loadObject(QString _filename) {
153
154 if ( checkJointScaling_ != 0 )
155 ignoreJointScaling_ = checkJointScaling_->isChecked();
156 else
157 ignoreJointScaling_ = OpenFlipperSettings().value("FileBVH/Load/JointScaling",true).toBool();
158
159 //setup filestream
160
161 std::fstream input( _filename.toUtf8(), std::ios_base::in );
162
163 if ( !input.is_open() || !input.good() ){
164 emit log(LOGERR, tr("Error: cannot open file %1").arg(_filename) );
165 return -1;
166 }
167
168 //add a skeleton
169 int id = -1;
170 emit addEmptyObject(DATA_SKELETON, id);
171
172 BaseObjectData* object = 0;
173 Skeleton* skeleton = 0;
174
175 if(PluginFunctions::getObject( id, object)){
176 skeleton = PluginFunctions::skeleton( object );
177 object->setFromFileName(_filename);
178 object->setName(object->filename());
179 }
180
181 if (skeleton == 0){
182 emit log(LOGERR, tr("Error: Unable to add skeleton!"));
183 return -1;
184 }
185
186 Skeleton::Joint* currentParent = 0;
187 Skeleton::Pose* refPose = skeleton->referencePose();
188
189
190 std::string line;
191 std::string keyWrd;
192 std::bitset<4> waitingFor = HIERARCHY;
193
194 std::map< Skeleton::Joint* , JointInfo> jointInfos;
195
196 uint dataOffset = 0; //Offset of the current channel in the frame data
197
198 AnimationHandle animHandle;
199 uint currentFrame = 0;
200 uint frameCount = 0;
201
202 while( input && !input.eof() )
203 {
204 std::getline(input,line);
205 if ( input.bad() ){
206 emit log(LOGERR, tr("Error: could not read file properly!"));
207 return -1;
208 }
209
210 // Trim Both leading and trailing spaces
211 trimString(line);
212
213 // ignore empty lines
214 if ( line.size() == 0 )
215 continue;
216
217 std::stringstream stream(line);
218
219 //read keyword from stream
220 stream >> keyWrd;
221
222 //HIERARCHY
223 if ( (waitingFor == HIERARCHY) && (keyWrd == "HIERARCHY") ){
224 waitingFor = ROOT_DEFINITION;
225 continue;
226 }
227
228 //ROOT_DEFINITION
229 if ( (waitingFor == ROOT_DEFINITION) && (keyWrd == "ROOT") ){
230
231 std::string name;
232 stream >> name;
233
234 Skeleton::Joint* rootJoint = new Skeleton::Joint(0, name);
235 skeleton->addJoint(0, rootJoint);
236 JointInfo info; //we found a new Joint, hence we need an ne JointInfo to store the channel inforamtions.
237 jointInfos[rootJoint]=info; //store Joint info for later use in case of CHANNELS
238 currentParent = rootJoint;
239
240 waitingFor = OPENED_BRACKET;
241 continue;
242 }
243
244 //OPENED_BRACKET
245 if ( (waitingFor == OPENED_BRACKET) && (keyWrd == "{") ){
246
247 waitingFor = OFFSET | CHANNELS | JOINT | ENDSITE | CLOSED_BRACKET;
248
249 continue;
250 }
251
252 //CLOSED_BRACKET
253 if ( (!(waitingFor&CLOSED_BRACKET).none()) && (keyWrd == "}") ){
254
255 if ( currentParent->parent() == 0 )
256 waitingFor = MOTION;
257 else{
258 waitingFor = JOINT | CLOSED_BRACKET;
259 }
260
261 currentParent = currentParent->parent();
262 continue;
263 }
264
265 //JOINT
266 if ( (!(waitingFor&JOINT).none()) && (keyWrd == "JOINT") ){
267
268 std::string name;
269 stream >> name;
270
271 Skeleton::Joint* newJoint = new Skeleton::Joint(currentParent, name);
272 skeleton->addJoint(currentParent, newJoint);
273 JointInfo info; //we found a new Joint, hence we need an ne JointInfo to store the channel inforamtions.
274 jointInfos[newJoint]=info; //store Joint info for later use in case of CHANNELS
275 currentParent = newJoint;
276
277 waitingFor = OPENED_BRACKET;
278 continue;
279 }
280
281 //OFFSET
282 if ( (!(waitingFor&OFFSET).none()) && (keyWrd == "OFFSET") ){
283
284 ACG::Vec3d translation;
285
286 stream >> translation[0];
287 stream >> translation[1];
288 stream >> translation[2];
289
290 refPose->setLocalTranslation(currentParent->id(), translation );
291
292 continue;
293 }
294
295 //CHANNELS
296 if ( (!(waitingFor&CHANNELS).none()) && (keyWrd == "CHANNELS") ){
297
298 uint channelCount;
299 stream >> channelCount;
300
301 JointInfo& info=jointInfos[ currentParent ];
302
303 if(channelCount>6) //well somethings wrong here...
304 std::cerr << "Error: channel count to big, will crash very soon" << std::endl;
305
306 for (uint i=0; i < channelCount; i++){ //parse channel informations
307 std::string channelType;
308 stream >> channelType;
309
310 //extract Channel position info and store in info.dataChannels
311 if (channelType == "Xposition")
312 info.dataChannels[info.channelOffset]=XP;
313 else if (channelType == "Yposition")
314 info.dataChannels[info.channelOffset]=YP;
315 else if (channelType == "Zposition")
316 info.dataChannels[info.channelOffset]=ZP;
317 else if (channelType == "Xrotation")
318 info.dataChannels[info.channelOffset]=XR;
319 else if (channelType == "Yrotation")
320 info.dataChannels[info.channelOffset]=YR;
321 else if (channelType == "Zrotation")
322 info.dataChannels[info.channelOffset]=ZR;
323 else
324 {std::cerr << "Error: Unknown channelType. Ignoring." << std::endl;}
325
326 if(info.dataChannels[info.channelOffset]!=NotGiven){ //if there is a channel assigned
327 info.dataOffset[info.channelOffset]=dataOffset; //the value for this channel will be found this data position
328 info.channelOffset++; //write next info into the next index
329 }
330 dataOffset++; // the data will be read even if there is no channel assigned to this data (e.g. unknown channel type)
331 }
332 continue;
333 }
334
335 // ENDSITE
336 if ( (!(waitingFor&ENDSITE).none()) && (keyWrd == "End") ){
337
338 std::string site;
339 stream >> site;
340
341 std::string name = "End";
342
343 Skeleton::Joint* newJoint = new Skeleton::Joint(currentParent, currentParent->name() + name);
344 skeleton->addJoint(currentParent, newJoint);
345 currentParent = newJoint;
346
347 waitingFor = OPENED_BRACKET;
348 continue;
349 }
350
351 //MOTION
352 if ( (waitingFor == MOTION) && (keyWrd == "MOTION") ){
353 waitingFor = FRAMES;
354 continue;
355 }
356
357 //Frames
358 if ( (waitingFor == FRAMES) && (keyWrd == "Frames:") ){
359
360 stream >> frameCount;
361
362 if (frameCount > 0){
363 FrameAnimationT<ACG::Vec3d>* animation = new FrameAnimationT<ACG::Vec3d>(skeleton, frameCount);
364 animHandle = skeleton->addAnimation(object->filename().toStdString(), animation);
365 }
366
367 waitingFor = FRAME_TIME;
368 continue;
369 }
370
371 //Frame Time
372 if ( (waitingFor == FRAME_TIME) && (keyWrd == "Frame") ){
373
374 std::string time;
375 stream >> time;
376
377 double frameTime;
378 stream >> frameTime;
379
380 if (frameCount > 0)
381 skeleton->animation(animHandle)->setFps( frameTime * 1000 );
382
383 waitingFor = CHANNEL_DATA;
384 continue;
385 }
386
387 //Channel Data
388 if ( (waitingFor == CHANNEL_DATA) ){
389
390 // a vector to store all the data for this frame
391 std::vector<double> data(dataOffset,0.0);
392
393 Skeleton::Pose* pose = 0;
394
395 if ( currentFrame < frameCount ){
396 animHandle.setFrame( currentFrame );
397 pose = skeleton->pose(animHandle);
398 }
399 else
400 std::cerr << "Warning: Too many frames specified in file." << std::endl;
401
402 //since we dont have a keyWrd here
403 // keyWrd is already the first data
404 data[0] = QString( keyWrd.c_str() ).toDouble();
405 //read the data for this frame
406 for (uint i=1; i < data.size(); i++){
407 stream >> data[i];
408 }
409
410 //now the channel for this timeFrame is complete
411 //apply them to the joints
412
413 if ( currentFrame < frameCount )
414 for (unsigned long jointID=0; jointID < skeleton->jointCount(); jointID++ ){
415
416 Skeleton::Joint* joint = skeleton->joint( jointID );
417
418 // special case: end-effector joints
419 // they don't have animation data
420 if ( jointInfos.find(joint) == jointInfos.end() ){
421 ACG::Matrix4x4d matRef = refPose->localMatrix(jointID);
422 pose->setLocalMatrix(jointID, matRef);
423 continue;
424 }
425
426 JointInfo& info=jointInfos[joint]; //get the cahnnels info for the current joint
427
428 ACG::Vec3d translation(0.0,0.0,0.0); //setup translation
429
430 ACG::GLMatrixd matRot; //setup rotation
431 matRot.identity();
432
433 for(int i=0;i<6;i++) //iterate over the cannels, applying the transformations in order
434 {
435 if(info.dataChannels[i]==NotGiven) break; //stop at the first empty channel
436
437 double val=data[info.dataOffset[i]]; //read one value from the data
438
439 switch(info.dataChannels[i]){ //apply the transformation
440 case XP: translation[0]=val; break; //translation (order doesnt matter)
441 case YP: translation[1]=val; break;
442 case ZP: translation[2]=val; break;
443 case XR: matRot.rotateX(val); break; //rotation (order does matter)
444 case YR: matRot.rotateY(val); break;
445 case ZR: matRot.rotateZ(val); break;
446 default: break; //stop at the first empty channel
447 }
448 }
449
450 ACG::GLMatrixd matTrans;
451 matTrans.identity();
452
453 if ( (!ignoreJointScaling_) || //translate only if there is no need to preserve the scale
454 (joint->parent() == 0) ) //or if the joint is the rootjoint
455 matTrans.translate(translation);
456
457 ACG::Matrix4x4d matRef = refPose->localMatrix(jointID);
458 pose->setLocalMatrix(jointID, matRef * matTrans * matRot);
459 }
460
461 currentFrame++;
462
463 continue;
464
465 }
466
467 std::cerr << "Error: No match for keyword '" << keyWrd << "' ";
468 std::cerr << "waiting for : " << waitingFor.to_string<char,std::char_traits<char>,std::allocator<char> >() << std::endl;
469 }
470
471
472 //general stuff
473 object->source( PluginFunctions::objectCount() > 4 );
474 emit updatedObject( object->id(), UPDATE_ALL );
475 emit openedFile( object->id() );
476
477 return object->id();
478 }
479
480 //-----------------------------------------------------------------------------------------------------
481
482 bool FileBVHPlugin::saveObject(int _id, QString _filename)
483 {
484
485 BaseObjectData* object;
486 PluginFunctions::getObject(_id,object);
487
488
489 //open output stream
490 std::string filename = std::string( _filename.toUtf8() );
491
492 std::fstream stream( filename.c_str(), std::ios_base::out );
493
494 if ( !stream ){
495 emit log(LOGERR, tr("saveObject : cannot not open file %1").arg(_filename) );
496 QFile( QString(filename.c_str()) ).remove();
497 return false;
498 }
499
500 //write object
501 if ( object->dataType( DATA_SKELETON ) ) {
502
503 object->setFromFileName(_filename);
504 object->setName(object->filename());
505
506 Skeleton* skeleton = PluginFunctions::skeleton(object);
507
508 if ( writeSkeleton( stream, *skeleton ) ){
509
510 emit log(LOGINFO, tr("Saved object to ") + _filename );
511 stream.close();
512 return true;
513
514 } else {
515
516 emit log(LOGERR, tr("Unable to save ") + _filename);
517 stream.close();
518 QFile( QString(filename.c_str()) ).remove();
519 return false;
520 }
521
522 } else {
523
524 emit log(LOGERR, tr("Unable to save (object is not a skeleton)"));
525 stream.close();
526 QFile( QString(filename.c_str()) ).remove();
527 return false;
528 }
529 }
530
531 //-----------------------------------------------------------------------------------------------------
532
533
534 ACG::Vec3d MatrixToEuler(ACG::Matrix4x4d _matrix){
535 ACG::Vec3d v(0.0, 0.0, 0.0);
536
537 if(_matrix(1,0) > 0.998) { // singularity at north pole
538 v[0] = atan2(_matrix(0,2), _matrix(2,2));
539 v[1] = M_PI / 2.0;
540 v[2] = 0;
541 return v;
542 }
543
544 if(_matrix(1,0) < -0.998) { // singularity at south pole
545 v[0] = atan2(_matrix(0,2), _matrix(2,2));
546 v[1] = - M_PI / 2.0;
547 v[2] = 0;
548 return v;
549 }
550
551 v[0] = atan2(-_matrix(2,0), _matrix(0,0));
552 v[1] = atan2(-_matrix(1,2), _matrix(1,1));
553 v[2] = asin(_matrix(1,0));
554 return v;
555 }
556
557 //-----------------------------------------------------------------------------------------------------
558
559 bool FileBVHPlugin::writeSkeleton( std::ostream& _out, Skeleton& _skeleton ) {
560
561 Skeleton::Pose* refPose = _skeleton.referencePose();
562
563 _out << "HIERARCHY" << std::endl;
564
565 std::string indent = "";
566
567 Skeleton::Joint* lastJoint = 0;
568
569 for (Skeleton::Iterator it = _skeleton.begin(); it != _skeleton.end(); ++it )
570 {
571
572 //close brackets
573 while ( (*it)->parent() != lastJoint ){
574 indent = indent.substr(0, indent.size()-1);
575 _out << indent << "}" << std::endl;
576
577 lastJoint = lastJoint->parent();
578 }
579
580 ACG::Vec3d translation;
581
582 if ( (*it)->parent() == 0 ){
583 //ROOT Joint
584 _out << "ROOT " << (*it)->name() << std::endl;
585
586 translation = refPose->globalTranslation( (*it)->id() );
587
588 } else if ( (*it)->size() > 0 ){
589
590 //normal joint
591 _out << indent << "JOINT " << (*it)->name() << std::endl;
592
593 translation = refPose->globalTranslation( (*it)->id() ) - refPose->globalTranslation( (*it)->parent()->id() );
594
595 } else {
596
597 //end-effector
598 _out << indent << "End Site" << std::endl;
599
600 translation = refPose->globalTranslation( (*it)->id() ) - refPose->globalTranslation( (*it)->parent()->id() );
601 }
602
603 _out << indent << "{" << std::endl;
604 indent += "\t";
605
606 _out << indent << "OFFSET " << translation[0] << " " << translation[1] << " " << translation[2] << std::endl;
607
608 if ( (*it)->size() > 0 ){ //end-effectors have no channel
609
610 if ( (*it)->parent() == 0)
611 _out << indent << "CHANNELS 6 Xposition Yposition Zposition Zrotation Yrotation Xrotation" << std::endl;
612 else
613 _out << indent << "CHANNELS 3 Zrotation Yrotation Xrotation" << std::endl;
614
615 lastJoint = *it;
616
617 } else {
618 indent = indent.substr(0, indent.size()-1);
619 _out << indent << "}" << std::endl;
620 lastJoint = (*it)->parent();
621 }
622 }
623
624 //close brackets
625 while ( lastJoint->parent() != 0 ){
626 indent = indent.substr(0, indent.size()-1);
627 _out << indent << "}" << std::endl;
628
629 lastJoint = lastJoint->parent();
630 }
631 _out << "}" << std::endl;
632
633 //now hierarchy is set up
634 // save the motion
635 AnimationT<ACG::Vec3d>* animation = 0;
636 uint iAnimation;
637 //get first animation with name
638 for (uint i = 0; i < _skeleton.animationCount(); i++){
639 animation = _skeleton.animation( AnimationHandle(i, 0 ) );
640
641 if (animation->name() == "")
642 animation = 0;
643 else{
644 iAnimation = i;
645 break;
646 }
647 }
648
649 if (animation == 0){
650
651 _out << "MOTION" << std::endl;
652 _out << "Frames: 0" << std::endl;
653 _out << "Frame Time: 0.1" << std::endl;
654
655 return true;
656 }
657
658 _out << "MOTION" << std::endl;
659 _out << "Frames: " << animation->frameCount() << std::endl;
660 _out << "Frame Time: " << animation->fps() / 1000.0 << std::endl;
661
662 std::string name = _skeleton.animationName(iAnimation);
663 AnimationHandle animHandle = _skeleton.animationHandle(name);
664
665
666 // and every frame of that animation
667 for(unsigned long k = 0; k < animation->frameCount(); ++k)
668 {
669
670 animHandle.setFrame(k);
671
672 Skeleton::Pose* pose = _skeleton.pose( animHandle );
673
674 for (Skeleton::Iterator it = _skeleton.begin(); it != _skeleton.end(); ++it )
675 {
676 //skip end-effectors
677 if ( (*it)->size() == 0)
678 continue;
679
680 if ( (*it)->parent() == 0 ){
681 //root joint
682 ACG::Vec3d translation = pose->globalTranslation( (*it)->id() ) - refPose->globalTranslation( (*it)->id() );
683
684 _out << translation[0] << " " << translation[1] << " " << translation[2];
685 }
686
687 ACG::Matrix4x4d rotMat = _skeleton.referencePose()->localMatrixInv( (*it)->id() ) * pose->localMatrix( (*it)->id() );
688
689 ACG::Vec3d angles = convertToAxisRotation(rotMat);
690
691 _out << " " << angles[2] << " " << angles[1] << " " << angles[0];
692
693 // ACG::GLMatrixd testMat( _skeleton.referencePose()->localMatrix( (*it)->id() ).raw() );
694 //
695 // if ( (*it)->isRoot() )
696 // testMat.translate( pose->globalTranslation( (*it)->id() ) );
697 //
698 // testMat.rotateZ( angles[2] );
699 // testMat.rotateY( angles[1] );
700 // testMat.rotateX( angles[0] );
701 //
702 //
703 // if ( testMat != pose->localMatrix( (*it)->id() ) ){
704 // std::cerr << "Decomposition failed (frame : " << k << " joint: " << (*it)->id() << ")" << std::endl;
705 // std::cerr << "Original:" << pose->localMatrix( (*it)->id() ) << std::endl;
706 // std::cerr << "Test :" << testMat << std::endl;
707 // }
708 }
709 _out << std::endl;
710 }
711
712 return true;
713 }
714
715 //-----------------------------------------------------------------------------------------------------
716
717 ACG::Vec3d FileBVHPlugin::convertToAxisRotation(ACG::Matrix4x4d& _rotationMatrix)
718 {
719 // conversion to quaternion
720 ACG::Quaterniond quat(_rotationMatrix);
721
722 double x,y,z,w;
723 w = quat[0];
724 x = quat[1];
725 y = quat[2];
726 z = quat[3];
727
728 // convert quaternion to euler
729 // create special rotation matrix
730 ACG::GLMatrixT<double> matrix;
731
732 matrix(0,0) = 1.0f - 2.0f * (y * y +z * z);
733 matrix(0,1) = 2.0f * (x * y +z * w);
734 matrix(0,2) = 2.0f * (z * x -y * w);
735
736 matrix(1,0) = 2.0f * (x * y -z * w);
737 matrix(1,1) = 1.0f - 2.0f * (z * z +x * x);
738 matrix(1,2) = 2.0f * (y * z +x * w);
739
740 matrix(2,0) = 2.0f * (z * x +y * w);
741 matrix(2,1) = 2.0f * (y * z -x * w);
742 matrix(2,2) = 1.0f - 2.0f * (y * y +x * x);
743
744 matrix.transpose();
745
746 // decompose the rotation matrix
747 double cosY = sqrt(matrix(0,0)*matrix(0,0)+matrix(1,0)*matrix(1,0));
748
749 ACG::Vec3d result;
750
751 if (cosY > 16 * FLT_EPSILON) {
752 result[0] = atan2( 1.0*matrix(2,1), matrix(2,2));
753 result[1] = atan2(-1.0*matrix(2,0), cosY);
754 result[2] = atan2( 1.0*matrix(1,0), matrix(0,0));
755 } else {
756 result[0] = atan2(-1.0*matrix(1,2), matrix(1,1));
757 result[1] = atan2(-1.0*matrix(2,0), cosY);
758 result[2] = 0.0;
759 }
760
761 // finally convert angles to degree
762 result[0] *= 180/M_PI;
763 result[1] *= 180/M_PI;
764 result[2] *= 180/M_PI;
765
766 return result;
767 }
768
769 //-----------------------------------------------------------------------------------------------------
770
771 QWidget* FileBVHPlugin::saveOptionsWidget(QString /*_currentFilter*/) {
772 return 0;
773 }
774
775 //-----------------------------------------------------------------------------------------------------
776
777 QWidget* FileBVHPlugin::loadOptionsWidget(QString /*_currentFilter*/) {
778
779 if (loadOptions_ == 0){
780 //generate widget
781 loadOptions_ = new QWidget();
782 QVBoxLayout* layout = new QVBoxLayout();
783 layout->setAlignment(Qt::AlignTop);
784
785 checkJointScaling_ = new QCheckBox("Ignore Joint Scaling");
786 layout->addWidget(checkJointScaling_);
787
788 loadDefaultButton_ = new QPushButton("Make Default");
789 layout->addWidget(loadDefaultButton_);
790
791 loadOptions_->setLayout(layout);
792
793 connect(loadDefaultButton_, SIGNAL(clicked()), this, SLOT(slotLoadDefault()));
794
795 checkJointScaling_->setChecked( OpenFlipperSettings().value("FileBVH/Load/JointScaling",true).toBool() );
796 }
797
798 return loadOptions_;
799 }
800
801 //-----------------------------------------------------------------------------------------------------
802
803 void FileBVHPlugin::slotLoadDefault() {
804
805 OpenFlipperSettings().setValue( "FileBVH/Load/JointScaling", checkJointScaling_->isChecked() );
806
807 OpenFlipperSettings().setValue( "Core/File/UseLoadDefaults", true );
808 }
809
810 //-----------------------------------------------------------------------------------------------------
811 #if QT_VERSION < 0x050000
812 Q_EXPORT_PLUGIN2( filebvhplugin , FileBVHPlugin );
813 #endif
814
OpenFlipperSettings
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
Definition: GlobalOptions.cc:938
FileBVHPlugin::name
QString name()
Return a name for the plugin.
Definition: FileBVH.hh:108
FileBVHPlugin
Definition: FileBVH.hh:69
LOGERR
Definition: LoggingInterface.hh:107
BaseObjectData
Definition: BaseObjectData.hh:105
SkeletonT::addJoint
void addJoint(typename SkeletonT< PointT >::Joint *_pParent, typename SkeletonT< PointT >::Joint *_pJoint)
Adds a joint as child of a given parent joint.
Definition: SkeletonT.cc:494
BaseObject::filename
QString filename() const
return the filename of the object
Definition: BaseObject.cc:717
FileBVHPlugin::saveOptionsWidget
QWidget * saveOptionsWidget(QString)
Definition: FileBVH.cc:771
UPDATE_ALL
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
PluginFunctions::getObject
bool getObject(int _identifier, BSplineCurveObject *&_object)
Definition: PluginFunctionsBSplineCurve.cc:75
SkeletonT::pose
Pose * pose(const AnimationHandle &_hAni)
Returns a pointer to the pose with the given animation handle.
Definition: SkeletonT.cc:741
JointT::name
std::string name()
Access the name of the joint.
Definition: JointT.cc:253
SkeletonT::referencePose
Pose * referencePose()
Returns a pointer to the reference pose.
Definition: SkeletonT.cc:761
JointInfo
Definition: FileBVH.cc:80
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::jointCount
unsigned int jointCount()
Returns the number of joints.
Definition: SkeletonT.cc:701
FileBVHPlugin::loadOptionsWidget
QWidget * loadOptionsWidget(QString)
Definition: FileBVH.cc:777
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
BaseObject::dataType
bool dataType(DataType _type) const
Definition: BaseObject.cc:232
SkeletonT::joint
Joint * joint(const unsigned int &_index)
Returns the joint with the given index.
Definition: SkeletonT.cc:642
SkeletonT::animationHandle
AnimationHandle animationHandle(std::string _name)
Get an AnimationHandle to the animation with the given name.
Definition: SkeletonT.cc:843
ACG::GLMatrixT::rotateZ
void rotateZ(Scalar _angle, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with a rotation matrix (angle in degree, z-axis)
Definition: GLMatrixT.hh:205
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
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
PoseT::localMatrix
const Matrix & localMatrix(unsigned int _joint) const
Returns the local matrix for the given joint.
Definition: PoseT.cc:110
FileBVHPlugin::initializePlugin
void initializePlugin()
Initialize Plugin.
Definition: FileBVH.cc:114
ACG::GLMatrixT::rotateX
void rotateX(Scalar _angle, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with a rotation matrix (angle in degree, x-axis)
Definition: GLMatrixT.hh:193
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
FileBVHPlugin::supportedType
DataType supportedType()
Return your supported object type( e.g. DATA_TRIANGLE_MESH )
Definition: FileBVH.cc:131
SkeletonT
Definition: JointT.hh:56
FileBVHPlugin::loadObject
int loadObject(QString _filename)
Loads Object.
Definition: FileBVH.cc:152
PoseT::globalTranslation
Vector globalTranslation(unsigned int _joint)
Returns the global translation vector.
Definition: PoseT.cc:233
FileBVHPlugin::getSaveFilters
QString getSaveFilters()
Definition: FileBVH.cc:125
ACG::GLMatrixT::rotateY
void rotateY(Scalar _angle, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with a rotation matrix (angle in degree, y-axis)
Definition: GLMatrixT.hh:199
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.
LOGINFO
Definition: LoggingInterface.hh:105
ACG::Matrix4x4T::identity
void identity()
setup an identity matrix
Definition: Matrix4x4T.cc:256
PoseT::setLocalMatrix
void setLocalMatrix(unsigned int _joint, const Matrix &_local, bool _keepLocalChildPositions=true)
Sets the local coordinate system.
Definition: PoseT.cc:126
JointT::id
unsigned int id()
returns the joint id
Definition: JointT.cc:103
OpenFlipperQSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Definition: OpenFlipperQSettings.cc:53
AnimationHandle
A handle used to refer to an animation or to a specific frame in an animation.
Definition: AnimationHandle.hh:56
FileBVHPlugin::getLoadFilters
QString getLoadFilters()
Definition: FileBVH.cc:119
FileBVHPlugin::FileBVHPlugin
FileBVHPlugin()
Constructor.
Definition: FileBVH.cc:104
PluginFunctions::objectCount
int objectCount()
Get the number of available objects.
Definition: PluginFunctions.cc:1004
ACG::Matrix4x4T::transpose
void transpose()
transpose matrix
Definition: Matrix4x4T.cc:272
FileBVHPlugin::slotLoadDefault
void slotLoadDefault()
Slot called when user wants to save the given Load options as default.
Definition: FileBVH.cc:803
AnimationT< ACG::Vec3d >
AnimationHandle::setFrame
void setFrame(unsigned int _iFrame)
Sets the current animation frame (not failsafe)
Definition: AnimationHandle.hh:71
PluginFunctions.hh
DataType
Predefined datatypes.
Definition: DataTypes.hh:96
OpenFlipperQSettings::setValue
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
Definition: OpenFlipperQSettings.cc:68
DATA_SKELETON
#define DATA_SKELETON
Definition: Skeleton.hh:70
SkeletonT::animationName
const std::string & animationName(unsigned int _index)
Returns the name of the animation with the given index.
Definition: SkeletonT.cc:984
PluginFunctions::skeleton
Skeleton * skeleton(BaseObjectData *_object)
Get a skeleton from an object.
Definition: PluginFunctionsSkeleton.cc:86
JointT
Represents a single joint in the skeleton.
Definition: JointT.hh:66
ACG::Matrix4x4T< double >
FrameAnimationT
Definition: FrameAnimationT.hh:56
BaseObject::id
int id() const
Definition: BaseObject.cc:201
ACG::QuaternionT< double >