Developer Documentation
FileSkeleton.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 "FileSkeleton.hh"
51 
53 
54 #include <OpenMesh/Core/IO/IOManager.hh>
55 
56 #if QT_VERSION >= 0x050000
57 #else
58  #include <QtGui>
59 #endif
60 
61 
63 }
64 
66  return QString( "Skeleton files ( *.skl )" );
67 };
68 
70  return QString( "Skeleton files ( *.skl )" );
71 };
72 
74  DataType type = DATA_SKELETON;
75  return type;
76 }
77 
78 template<typename Skeleton>
79 bool FileSKLPlugin::LoadSkeleton(Skeleton *_pSkeleton, QString _filename)
80 {
84 
85  unsigned int nJoints = 0;
86 
87  std::ifstream in(_filename.toStdString().c_str(), std::ofstream::in);
88 
89  // read number of joints
90  in >> nJoints;
91 
92  Pose *ref = _pSkeleton->referencePose();
93  // remember parent joints
94  std::map<unsigned int, Joint*> parents;
95 
96  std::map<unsigned int, unsigned int> jointMap;
97 
98  for(unsigned int i = 0; i < nJoints; ++i)
99  {
100  // id not stored in skeleton; the read order is increasing for joints
101  unsigned int id;
102 
103  // read joint id
104  in >> id;
105 
106  // read its matrix
107  Matrix mat;
108  mat.identity();
109  for(int y = 0; y < 3; ++y)
110  for(int x = 0; x < 3; ++x)
111  in >> mat(y, x);
112  for(int y = 0; y < 3; ++y)
113  in >> mat(y, 3);
114 
115  // try to find the parent joint
116  Joint *pParent = 0;
117  if(parents.find(id) != parents.end())
118  pParent = parents[id];
119 
120  // setup the new joint
121  Joint *pJoint = new Joint(pParent);
122  _pSkeleton->addJoint(pParent, pJoint);
123 
124  jointMap[ id ] = pJoint->id();
125 
126  // save the joints position
127  ref->setGlobalMatrix(jointMap[ id ], mat);
128 
129  // how many child nodes
130  unsigned int nChildren;
131  in >> nChildren;
132 
133  for(unsigned int j = 0; j < nChildren; ++j)
134  {
135  // remember to attach this child joint once its being load
136  unsigned int idChild;
137  in >> idChild;
138 
139  parents[idChild] = pJoint;
140  }
141  }
142 
143  unsigned int num_anim = 0;
144  while(in.good()) {
145 
146  num_anim++;
147 
148  // Test whether animation name is provided
149  std::string identifier;
150  in >> identifier;
151  std::string animationName = (QString("Animation") + QString::number(num_anim)).toStdString();
152 
153  //read animation
154  unsigned int frameCount = 0;
155 
156 
157  if(identifier == "animation") {
158  std::getline(in, animationName);
159  // Trim string
160  animationName = QString(animationName.c_str()).trimmed().toStdString();
161 
162  in >> frameCount;
163  } else {
164 
165  std::istringstream tmp(identifier);
166  tmp >> frameCount;
167 
168  }
169 
170  if ( frameCount > 0 ){
171 
172  FrameAnimationT<ACG::Vec3d>* animation = new FrameAnimationT<ACG::Vec3d>(_pSkeleton, frameCount);
173  AnimationHandle animHandle = _pSkeleton->addAnimation(animationName, animation);
174 
175  for (unsigned int k = 0; k < frameCount; k++){
176 
177  animHandle.setFrame(k);
178  typename Skeleton::Pose* pose = _pSkeleton->pose( animHandle );
179 
180  for(unsigned int i = 0; i < nJoints; ++i)
181  {
182  unsigned int id; // id not stored in skeleton; the read order is increasing for joints
183 
184  // read joint id
185  in >> id;
186 
187  // read its matrix
188  Matrix mat;
189  mat.identity();
190  for(int y = 0; y < 3; ++y)
191  for(int x = 0; x < 3; ++x)
192  in >> mat(y, x);
193  for(int y = 0; y < 3; ++y)
194  in >> mat(y, 3);
195 
196  //set matrix
197  pose->setGlobalMatrix(jointMap[ id ], mat);
198  }
199  }
200  }
201  }
202 
203  in.close();
204 
205  return true;
206 }
207 
208 int FileSKLPlugin::loadObject(QString _filename)
209 {
210  int id = -1;
211  emit addEmptyObject(DATA_SKELETON, id);
212 
213  BaseObjectData *obj(0);
214  if(PluginFunctions::getObject(id, obj))
215  {
217 
218  LoadSkeleton(skel->skeleton(), _filename);
219 
220  //general stuff
221  obj->source( PluginFunctions::objectCount() > 4 );
222  obj->setFromFileName(_filename);
223  obj->setName(obj->filename());
224  emit updatedObject( obj->id(), UPDATE_ALL );
225  emit openedFile( obj->id() );
226  } else {
227  emit log(LOGERR,tr("Unable to add empty skeleton"));
228  }
229 
230 
231  return id;
232 };
233 
234 template<typename Skeleton>
235 bool FileSKLPlugin::SaveSkeleton(Skeleton *_pSkeleton, QString _filename)
236 {
237  typedef JointT<typename Skeleton::Point> Joint;
238  typedef PoseT<typename Skeleton::Point> Pose;
240 
241  std::ofstream out(_filename.toStdString().c_str(), std::ofstream::out);
242 
243  // write the number of joints
244  out << _pSkeleton->jointCount() << std::endl;
245 
246  Pose *ref = _pSkeleton->referencePose();
247  // write all the joints
248  for (typename Skeleton::Iterator it = _pSkeleton->begin(); it != _pSkeleton->end(); ++it ){
249 
250  unsigned int i = (*it)->id();
251  Joint *pJoint = *it;
252 
253  // write this joints id
254  out << pJoint->id() << " ";
255 
256  // write its position
257  const Matrix &mat = ref->globalMatrix(i);
258  for(int y = 0; y < 3; ++y)
259  for(int x = 0; x < 3; ++x)
260  out << mat(y, x) << " ";
261  for(int y = 0; y < 3; ++y)
262  out << mat(y, 3) << " ";
263 
264  // write this joints number of children
265  out << pJoint->size() << " ";
266 
267  // write the children
268  for(unsigned int j = 0; j < pJoint->size(); ++j)
269  out << pJoint->child(j)->id() << " ";
270 
271  out << std::endl;
272  }
273 
274  // now store animations
275  AnimationT<ACG::Vec3d>* animation = 0;
276 
277  for (unsigned int i = 0; i < _pSkeleton->animationCount(); i++) {
278 
279  animation = _pSkeleton->animation(AnimationHandle(i, 0));
280 
281  if (animation != 0) {
282 
283  std::string name = animation->name();
284 
285  out << "animation " << name << std::endl;
286 
287  out << animation->frameCount() << std::endl;
288 
289  AnimationHandle animHandle = _pSkeleton->animationHandle(name);
290 
291  // every frame of that animation
292  for (unsigned int k = 0; k < animation->frameCount(); ++k) {
293 
294  animHandle.setFrame(k);
295  typename Skeleton::Pose* pose = _pSkeleton->pose(animHandle);
296 
297  for (typename Skeleton::Iterator it = _pSkeleton->begin(); it != _pSkeleton->end(); ++it) {
298 
299  unsigned int i = (*it)->id();
300  Joint *pJoint = *it;
301 
302  // write this joints id
303  out << pJoint->id() << " ";
304 
305  // write its position
306  const Matrix &mat = pose->globalMatrix(i);
307  for (int y = 0; y < 3; ++y)
308  for (int x = 0; x < 3; ++x)
309  out << mat(y, x) << " ";
310  for (int y = 0; y < 3; ++y)
311  out << mat(y, 3) << " ";
312  }
313 
314  out << std::endl;
315  }
316  } else {
317  out << "0" << std::endl;
318  }
319  }
320 
321  out.close();
322  return !out.fail();
323 }
324 
325 bool FileSKLPlugin::saveObject(int _id, QString _filename)
326 {
327  BaseObjectData *obj(0);
328  if(PluginFunctions::getObject(_id, obj))
329  {
331  if(skel)
332  {
333  obj->setFromFileName(_filename);
334  obj->setName(obj->filename());
335  SaveSkeleton(skel->skeleton(), _filename);
336  }
337  } else {
338  emit log(LOGERR, tr("saveObject : cannot get object id %1 for save name %2").arg(_id).arg(_filename) );
339  return false;
340  }
341 
342  return true;
343 }
344 
345 void FileSKLPlugin::loadIniFile( INIFile& _ini ,int _id ) {
346  BaseObjectData* baseObject;
347  if ( !PluginFunctions::getObject(_id,baseObject) ) {
348  emit log(LOGERR,"Cannot find object for id " + QString::number(_id) + " in saveFile" );
349  return;
350  }
351 
352  if ( baseObject->materialNode() != 0 ) {
353  ACG::Vec4f col(0.0,0.0,0.0,0.0);
354 
355  if ( _ini.get_entryVecf( col, baseObject->name() , "BaseColor" ) )
356  baseObject->materialNode()->set_base_color(col);
357  }
358 
359 }
360 
361 void FileSKLPlugin::saveIniFile( INIFile& _ini ,int _id) {
362  BaseObjectData* baseObject;
363  if ( !PluginFunctions::getObject(_id,baseObject) ) {
364  emit log(LOGERR,"Cannot find object for id " + QString::number(_id) + " in saveFile" );
365  return;
366  }
367 
368 
369  if ( baseObject->materialNode() != 0 ) {
370  _ini.add_entryVec( baseObject->name() ,
371  "BaseColor" ,
372  baseObject->materialNode()->base_color() );
373  }
374 }
375 
376 #if QT_VERSION < 0x050000
377  Q_EXPORT_PLUGIN2( filesklplugin , FileSKLPlugin );
378 #endif
379 
380 
Iterator class for the skeleton.
Definition: SkeletonT.hh:88
Predefined datatypes.
Definition: DataTypes.hh:96
Pose * pose(unsigned int _iFrame)
Returns a pointer to the pose stored in the given frame.
Represents a single joint in the skeleton.
Definition: JointT.hh:66
QString filename() const
return the filename of the object
Definition: BaseObject.cc:717
bool getObject(int _identifier, BSplineCurveObject *&_object)
unsigned int jointCount()
Returns the number of joints.
Definition: SkeletonT.cc:701
void add_entryVec(const QString &_section, const QString &_key, const VectorT &_value)
Addition of a Vec_n_something.
Definition: INIFileT.cc:211
void loadIniFile(INIFile &_ini, int _id)
Load per object settings.
bool get_entryVecf(VectorT &_val, const QString &_section, const QString &_key) const
Get a Vec_n_i (int)
Definition: INIFileT.cc:169
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 setFrame(unsigned int _iFrame)
Sets the current animation frame (not failsafe)
int id() const
Definition: BaseObject.cc:201
void setFromFileName(const QString &_filename)
Definition: BaseObject.cc:727
MaterialNode * materialNode()
get a pointer to the materialnode
A general pose, used to store the frames of the animation.
Definition: PoseT.hh:68
Skeleton * skeleton()
Returns a pointer to the skeleton.
Animation * animation(std::string _name)
Returns a pointer to the animation to the given name.
Definition: SkeletonT.cc:858
A handle used to refer to an animation or to a specific frame in an animation.
AnimationHandle animationHandle(std::string _name)
Get an AnimationHandle to the animation with the given name.
Definition: SkeletonT.cc:843
int objectCount()
Get the number of available objects.
SkeletonObject * skeletonObject(BaseObjectData *_object)
Cast an BaseObject to a SkeletonObject if possible.
virtual void setName(QString _name)
path to the file from which the object is loaded ( defaults to "." )
void initializePlugin()
Initialize Plugin.
Definition: FileSkeleton.cc:62
Class for the handling of simple configuration files.
Definition: INIFile.hh:105
void saveIniFile(INIFile &_ini, int _id)
Save per object settings.
Iterator end()
Compare an iterator with the return value of this method to test if it is done.
Definition: SkeletonT.cc:725
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
unsigned int animationCount()
Returns the number of animations stored in this skeleton.
Definition: SkeletonT.cc:971
const Vec4f & base_color() const
get the base color
QString name() const
return the name of the object. The name defaults to NONAME if unset.
Definition: BaseObject.cc:741
Pose * pose(const AnimationHandle &_hAni)
Returns a pointer to the pose with the given animation handle.
Definition: SkeletonT.cc:741
DataType supportedType()
Return your supported object type( e.g. DATA_TRIANGLE_MESH )
Definition: FileSkeleton.cc:73
QString name()
Return a name for the plugin.
#define DATA_SKELETON
Definition: Skeleton.hh:70
QString getSaveFilters()
Definition: FileSkeleton.cc:69
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
QString getLoadFilters()
Definition: FileSkeleton.cc:65
bool source()
Definition: BaseObject.cc:302
void set_base_color(const Vec4f &_c)
set the base color
void setGlobalMatrix(unsigned int _joint, const Matrix &_global, bool _keepGlobalChildPositions=true)
Sets the global coordinate system.
Definition: PoseT.cc:217
Pose * referencePose()
Returns a pointer to the reference pose.
Definition: SkeletonT.cc:761