43 #if (_MSC_VER <= 1916) 44 #define QT_NO_FLOAT16_OPERATORS 57 const std::bitset<4> HIERARCHY (static_cast<int>(0));
58 const std::bitset<4> ROOT_DEFINITION (static_cast<int>(1));
59 const std::bitset<4> OPENED_BRACKET (static_cast<int>(2));
60 const std::bitset<4> CLOSED_BRACKET (static_cast<int>(3));
61 const std::bitset<4> OFFSET (static_cast<int>(4));
62 const std::bitset<4> CHANNELS (static_cast<int>(5));
63 const std::bitset<4> JOINT (static_cast<int>(6));
64 const std::bitset<4> ENDSITE (static_cast<int>(7));
65 const std::bitset<4> MOTION (static_cast<int>(8));
66 const std::bitset<4> FRAMES (static_cast<int>(9));
67 const std::bitset<4> FRAME_TIME (static_cast<int>(10));
68 const std::bitset<4> CHANNEL_DATA (static_cast<int>(11));
72 enum ChannelType{NotGiven,XP,YP,ZP,XR,YR,ZR};
76 ChannelType dataChannels[6];
77 unsigned int dataOffset[6];
79 unsigned int channelOffset;
86 dataChannels[i]=NotGiven;
99 : ignoreJointScaling_(true),
101 checkJointScaling_(0),
102 loadDefaultButton_(0)
114 return QString( tr(
"Biovision Format files ( *.bvh )") );
120 return QString( tr(
"Biovision Format files ( *.bvh )") );
132 void trimString( std::string& _string) {
135 size_t start = _string.find_first_not_of(
" \t\r\n");
136 size_t end = _string.find_last_not_of(
" \t\r\n");
138 if(( std::string::npos == start ) || ( std::string::npos == end))
141 _string = _string.substr( start, end-start+1 );
148 if ( checkJointScaling_ != 0 )
149 ignoreJointScaling_ = checkJointScaling_->isChecked();
155 std::fstream input( _filename.toUtf8(), std::ios_base::in );
157 if ( !input.is_open() || !input.good() ){
158 emit log(
LOGERR, tr(
"Error: cannot open file %1").arg(_filename) );
171 object->setFromFileName(_filename);
172 object->setName(object->
filename());
176 emit log(
LOGERR, tr(
"Error: Unable to add skeleton!"));
186 std::bitset<4> waitingFor = HIERARCHY;
188 std::map< Skeleton::Joint* , JointInfo> jointInfos;
193 uint currentFrame = 0;
196 while( input && !input.eof() )
198 std::getline(input,line);
200 emit log(
LOGERR, tr(
"Error: could not read file properly!"));
208 if ( line.size() == 0 )
211 std::stringstream stream(line);
217 if ( (waitingFor == HIERARCHY) && (keyWrd ==
"HIERARCHY") ){
218 waitingFor = ROOT_DEFINITION;
223 if ( (waitingFor == ROOT_DEFINITION) && (keyWrd ==
"ROOT") ){
231 jointInfos[rootJoint]=info;
232 currentParent = rootJoint;
234 waitingFor = OPENED_BRACKET;
239 if ( (waitingFor == OPENED_BRACKET) && (keyWrd ==
"{") ){
241 waitingFor = OFFSET | CHANNELS | JOINT | ENDSITE | CLOSED_BRACKET;
247 if ( (!(waitingFor&CLOSED_BRACKET).none()) && (keyWrd ==
"}") ){
249 if ( currentParent->
parent() == 0 )
252 waitingFor = JOINT | CLOSED_BRACKET;
255 currentParent = currentParent->
parent();
260 if ( (!(waitingFor&JOINT).none()) && (keyWrd ==
"JOINT") ){
266 skeleton->
addJoint(currentParent, newJoint);
268 jointInfos[newJoint]=info;
269 currentParent = newJoint;
271 waitingFor = OPENED_BRACKET;
276 if ( (!(waitingFor&OFFSET).none()) && (keyWrd ==
"OFFSET") ){
280 stream >> translation[0];
281 stream >> translation[1];
282 stream >> translation[2];
290 if ( (!(waitingFor&CHANNELS).none()) && (keyWrd ==
"CHANNELS") ){
293 stream >> channelCount;
295 JointInfo& info=jointInfos[ currentParent ];
298 std::cerr <<
"Error: channel count to big, will crash very soon" << std::endl;
300 for (uint i=0; i < channelCount; i++){
301 std::string channelType;
302 stream >> channelType;
305 if (channelType ==
"Xposition")
306 info.dataChannels[info.channelOffset]=XP;
307 else if (channelType ==
"Yposition")
308 info.dataChannels[info.channelOffset]=YP;
309 else if (channelType ==
"Zposition")
310 info.dataChannels[info.channelOffset]=ZP;
311 else if (channelType ==
"Xrotation")
312 info.dataChannels[info.channelOffset]=XR;
313 else if (channelType ==
"Yrotation")
314 info.dataChannels[info.channelOffset]=YR;
315 else if (channelType ==
"Zrotation")
316 info.dataChannels[info.channelOffset]=ZR;
318 {std::cerr <<
"Error: Unknown channelType. Ignoring." << std::endl;}
320 if(info.dataChannels[info.channelOffset]!=NotGiven){
321 info.dataOffset[info.channelOffset]=dataOffset;
322 info.channelOffset++;
330 if ( (!(waitingFor&ENDSITE).none()) && (keyWrd ==
"End") ){
335 std::string
name =
"End";
338 skeleton->
addJoint(currentParent, newJoint);
339 currentParent = newJoint;
341 waitingFor = OPENED_BRACKET;
346 if ( (waitingFor == MOTION) && (keyWrd ==
"MOTION") ){
352 if ( (waitingFor == FRAMES) && (keyWrd ==
"Frames:") ){
354 stream >> frameCount;
358 animHandle = skeleton->addAnimation(object->
filename().toStdString(), animation);
361 waitingFor = FRAME_TIME;
366 if ( (waitingFor == FRAME_TIME) && (keyWrd ==
"Frame") ){
375 skeleton->
animation(animHandle)->setFps( frameTime * 1000 );
377 waitingFor = CHANNEL_DATA;
382 if ( (waitingFor == CHANNEL_DATA) ){
385 std::vector<double> data(dataOffset,0.0);
389 if ( currentFrame < frameCount ){
390 animHandle.
setFrame( currentFrame );
391 pose = skeleton->
pose(animHandle);
394 std::cerr <<
"Warning: Too many frames specified in file." << std::endl;
398 data[0] = QString( keyWrd.c_str() ).toDouble();
400 for (uint i=1; i < data.size(); i++){
407 if ( currentFrame < frameCount )
408 for (
unsigned long jointID=0; jointID < skeleton->
jointCount(); jointID++ ){
414 if ( jointInfos.find(joint) == jointInfos.end() ){
429 if(info.dataChannels[i]==NotGiven)
break;
431 double val=data[info.dataOffset[i]];
433 switch(info.dataChannels[i]){
434 case XP: translation[0]=val;
break;
435 case YP: translation[1]=val;
break;
436 case ZP: translation[2]=val;
break;
437 case XR: matRot.
rotateX(val);
break;
438 case YR: matRot.
rotateY(val);
break;
439 case ZR: matRot.
rotateZ(val);
break;
447 if ( (!ignoreJointScaling_) ||
461 std::cerr <<
"Error: No match for keyword '" << keyWrd <<
"' ";
462 std::cerr <<
"waiting for : " << waitingFor.to_string<char,std::char_traits<char>,std::allocator<char> >() << std::endl;
469 emit openedFile( object->
id() );
476 bool FileBVHPlugin::saveObject(
int _id, QString _filename)
484 std::string filename = std::string( _filename.toUtf8() );
486 std::fstream stream( filename.c_str(), std::ios_base::out );
489 emit log(
LOGERR, tr(
"saveObject : cannot not open file %1").arg(_filename) );
490 QFile( QString(filename.c_str()) ).remove();
497 object->setFromFileName(_filename);
498 object->setName(object->
filename());
502 if ( writeSkeleton( stream, *skeleton ) ){
504 emit log(
LOGINFO, tr(
"Saved object to ") + _filename );
510 emit log(
LOGERR, tr(
"Unable to save ") + _filename);
512 QFile( QString(filename.c_str()) ).remove();
518 emit log(
LOGERR, tr(
"Unable to save (object is not a skeleton)"));
520 QFile( QString(filename.c_str()) ).remove();
531 if(_matrix(1,0) > 0.998) {
532 v[0] = atan2(_matrix(0,2), _matrix(2,2));
538 if(_matrix(1,0) < -0.998) {
539 v[0] = atan2(_matrix(0,2), _matrix(2,2));
545 v[0] = atan2(-_matrix(2,0), _matrix(0,0));
546 v[1] = atan2(-_matrix(1,2), _matrix(1,1));
547 v[2] = asin(_matrix(1,0));
553 bool FileBVHPlugin::writeSkeleton( std::ostream& _out,
Skeleton& _skeleton ) {
557 _out <<
"HIERARCHY" << std::endl;
559 std::string indent =
"";
567 while ( (*it)->parent() != lastJoint ){
568 indent = indent.substr(0, indent.size()-1);
569 _out << indent <<
"}" << std::endl;
571 lastJoint = lastJoint->
parent();
576 if ( (*it)->parent() == 0 ){
578 _out <<
"ROOT " << (*it)->name() << std::endl;
582 }
else if ( (*it)->size() > 0 ){
585 _out << indent <<
"JOINT " << (*it)->name() << std::endl;
592 _out << indent <<
"End Site" << std::endl;
597 _out << indent <<
"{" << std::endl;
600 _out << indent <<
"OFFSET " << translation[0] <<
" " << translation[1] <<
" " << translation[2] << std::endl;
602 if ( (*it)->size() > 0 ){
604 if ( (*it)->parent() == 0)
605 _out << indent <<
"CHANNELS 6 Xposition Yposition Zposition Zrotation Yrotation Xrotation" << std::endl;
607 _out << indent <<
"CHANNELS 3 Zrotation Yrotation Xrotation" << std::endl;
612 indent = indent.substr(0, indent.size()-1);
613 _out << indent <<
"}" << std::endl;
614 lastJoint = (*it)->
parent();
619 while ( lastJoint->
parent() != 0 ){
620 indent = indent.substr(0, indent.size()-1);
621 _out << indent <<
"}" << std::endl;
623 lastJoint = lastJoint->
parent();
625 _out <<
"}" << std::endl;
635 if (animation->name() ==
"")
645 _out <<
"MOTION" << std::endl;
646 _out <<
"Frames: 0" << std::endl;
647 _out <<
"Frame Time: 0.1" << std::endl;
652 _out <<
"MOTION" << std::endl;
653 _out <<
"Frames: " << animation->frameCount() << std::endl;
654 _out <<
"Frame Time: " << animation->fps() / 1000.0 << std::endl;
661 for(
unsigned long k = 0; k < animation->frameCount(); ++k)
671 if ( (*it)->size() == 0)
674 if ( (*it)->parent() == 0 ){
678 _out << translation[0] <<
" " << translation[1] <<
" " << translation[2];
683 ACG::Vec3d angles = convertToAxisRotation(rotMat);
685 _out <<
" " << angles[2] <<
" " << angles[1] <<
" " << angles[0];
726 matrix(0,0) = 1.0f - 2.0f * (y * y +z * z);
727 matrix(0,1) = 2.0f * (x * y +z * w);
728 matrix(0,2) = 2.0f * (z * x -y * w);
730 matrix(1,0) = 2.0f * (x * y -z * w);
731 matrix(1,1) = 1.0f - 2.0f * (z * z +x * x);
732 matrix(1,2) = 2.0f * (y * z +x * w);
734 matrix(2,0) = 2.0f * (z * x +y * w);
735 matrix(2,1) = 2.0f * (y * z -x * w);
736 matrix(2,2) = 1.0f - 2.0f * (y * y +x * x);
741 double cosY = sqrt(matrix(0,0)*matrix(0,0)+matrix(1,0)*matrix(1,0));
745 if (cosY > 16 * FLT_EPSILON) {
746 result[0] = atan2( 1.0*matrix(2,1), matrix(2,2));
747 result[1] = atan2(-1.0*matrix(2,0), cosY);
748 result[2] = atan2( 1.0*matrix(1,0), matrix(0,0));
750 result[0] = atan2(-1.0*matrix(1,2), matrix(1,1));
751 result[1] = atan2(-1.0*matrix(2,0), cosY);
756 result[0] *= 180/M_PI;
757 result[1] *= 180/M_PI;
758 result[2] *= 180/M_PI;
773 if (loadOptions_ == 0){
775 loadOptions_ =
new QWidget();
776 QVBoxLayout* layout =
new QVBoxLayout();
777 layout->setAlignment(Qt::AlignTop);
779 checkJointScaling_ =
new QCheckBox(
"Ignore Joint Scaling");
780 layout->addWidget(checkJointScaling_);
782 loadDefaultButton_ =
new QPushButton(
"Make Default");
783 layout->addWidget(loadDefaultButton_);
785 loadOptions_->setLayout(layout);
787 connect(loadDefaultButton_, SIGNAL(clicked()),
this, SLOT(
slotLoadDefault()));
789 checkJointScaling_->setChecked(
OpenFlipperSettings().value(
"FileBVH/Load/JointScaling",
true).toBool() );
void initializePlugin()
Initialize Plugin.
QWidget * loadOptionsWidget(QString)
Iterator end()
Compare an iterator with the return value of this method to test if it is done.
Matrix localMatrixInv(unsigned int _joint) const
Simply returns the inverse of the local matrix.
size_t id() const
returns the joint id
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
void rotateX(Scalar _angle, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with a rotation matrix (angle in degree, x-axis)
size_t jointCount()
Returns the number of joints.
int objectCount()
Get the number of available objects.
void transpose()
transpose matrix
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Joint * joint(const size_t &_index)
Returns the joint with the given index.
void translate(Scalar _x, Scalar _y, Scalar _z, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with translation matrix (x,y,z)
void identity()
setup an identity matrix
FileBVHPlugin()
Constructor.
void rotateZ(Scalar _angle, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with a rotation matrix (angle in degree, z-axis)
A general pose, used to store the frames of the animation.
QString filename() const
return the filename of the object
Iterator begin()
Iterator over joints of the skeletal tree in TOP-DOWN order (from root to leafs)
void setLocalTranslation(unsigned int _joint, const Vector &_position, bool _keepLocalChildPositions=true)
Sets the local translation vector.
bool dataType(DataType _type) const
std::string name() const
Access the name of the joint.
void setFrame(size_t _iFrame)
Sets the current animation frame (not failsafe)
void rotateY(Scalar _angle, MultiplyFrom _mult_from=MULT_FROM_RIGHT)
multiply self with a rotation matrix (angle in degree, y-axis)
Functions for geometric operations related to angles.
Represents a single joint in the skeleton.
Pose * referencePose()
Returns a pointer to the reference pose.
void addJoint(typename SkeletonT< PointT >::Joint *_pParent, typename SkeletonT< PointT >::Joint *_pJoint)
Adds a joint as child of a given parent joint.
const Matrix & localMatrix(unsigned int _joint) const
Returns the local matrix for the given joint.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
Skeleton * skeleton(BaseObjectData *_object)
Get a skeleton from an object.
QString name()
Return a name for the plugin.
const std::string & animationName(size_t _index)
Returns the name of the animation with the given index.
void slotLoadDefault()
Slot called when user wants to save the given Load options as default.
Pose * pose(const AnimationHandle &_hAni)
Returns a pointer to the pose with the given animation handle.
DataType supportedType()
Return your supported object type( e.g. DATA_TRIANGLE_MESH )
Iterator class for the skeleton.
Animation * animation(std::string _name)
Returns a pointer to the animation to the given name.
Joint * parent()
Returns the parent joint.
size_t animationCount()
Returns the number of animations stored in this skeleton.
int loadObject(QString _filename)
Loads Object.
AnimationHandle animationHandle(std::string _name)
Get an AnimationHandle to the animation with the given name.
void setValue(const QString &key, const QVariant &value)
Wrapper function which makes it possible to enable Debugging output with -DOPENFLIPPER_SETTINGS_DEBUG...
DLLEXPORT OpenFlipperQSettings & OpenFlipperSettings()
QSettings object containing all program settings of OpenFlipper.
void setLocalMatrix(unsigned int _joint, const Matrix &_local, bool _keepLocalChildPositions=true)
Sets the local coordinate system.
QWidget * saveOptionsWidget(QString)
A handle used to refer to an animation or to a specific frame in an animation.
Vector globalTranslation(unsigned int _joint)
Returns the global translation vector.