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
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
52 #include <OpenFlipper/BasePlugin/PluginFunctions.hh>
53
54 #include <OpenMesh/Core/IO/IOManager.hh>
55
56 #if QT_VERSION >= 0x050000
57 #else
58 #include <QtGui>
59 #endif
60
61
62 void FileSKLPlugin::initializePlugin() {
63 }
64
65 QString FileSKLPlugin::getLoadFilters() {
66 return QString( "Skeleton files ( *.skl )" );
67 };
68
69 QString FileSKLPlugin::getSaveFilters() {
70 return QString( "Skeleton files ( *.skl )" );
71 };
72
73 DataType FileSKLPlugin::supportedType() {
74 DataType type = DATA_SKELETON;
75 return type;
76 }
77
78 template<typename Skeleton>
79 bool FileSKLPlugin::LoadSkeleton(Skeleton *_pSkeleton, QString _filename)
80 {
81 typedef JointT<typename Skeleton::Point> Joint;
82 typedef PoseT<typename Skeleton::Point> Pose;
83 typedef ACG::Matrix4x4T<typename Skeleton::Scalar> Matrix;
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 {
216 SkeletonObject* skel = PluginFunctions::skeletonObject(obj);
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;
239 typedef ACG::Matrix4x4T<typename Skeleton::Scalar> Matrix;
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 {
330 SkeletonObject *skel = PluginFunctions::skeletonObject(obj);
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
PoseT::setGlobalMatrix
void setGlobalMatrix(unsigned int _joint, const Matrix &_global, bool _keepGlobalChildPositions=true)
Sets the global coordinate system.
Definition: PoseT.cc:217
PluginFunctions::skeletonObject
SkeletonObject * skeletonObject(BaseObjectData *_object)
Cast an BaseObject to a SkeletonObject if possible.
Definition: PluginFunctionsSkeleton.cc:105
FileSKLPlugin::loadIniFile
void loadIniFile(INIFile &_ini, int _id)
Load per object settings.
Definition: FileSkeleton.cc:345
LOGERR
Definition: LoggingInterface.hh:107
BaseObjectData
Definition: BaseObjectData.hh:105
BaseObject::name
QString name() const
return the name of the object. The name defaults to NONAME if unset.
Definition: BaseObject.cc:741
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
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
SkeletonT::referencePose
Pose * referencePose()
Returns a pointer to the reference pose.
Definition: SkeletonT.cc:761
ACG::SceneGraph::MaterialNode::base_color
const Vec4f & base_color() const
get the base color
Definition: MaterialNode.hh:406
SkeletonT::animation
Animation * animation(std::string _name)
Returns a pointer to the animation to the given name.
Definition: SkeletonT.cc:858
BaseObjectData::materialNode
MaterialNode * materialNode()
get a pointer to the materialnode
Definition: BaseObjectData.cc:269
SkeletonObject
Definition: SkeletonObject.hh:82
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
FileSKLPlugin::initializePlugin
void initializePlugin()
Initialize Plugin.
Definition: FileSkeleton.cc:62
FileSKLPlugin::name
QString name()
Return a name for the plugin.
Definition: FileSkeleton.hh:101
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
INIFile::add_entryVec
void add_entryVec(const QString &_section, const QString &_key, const VectorT &_value)
Addition of a Vec_n_something.
Definition: INIFileT.cc:211
ACG::SceneGraph::MaterialNode::set_base_color
void set_base_color(const Vec4f &_c)
set the base color
Definition: MaterialNode.hh:404
SkeletonT::animationHandle
AnimationHandle animationHandle(std::string _name)
Get an AnimationHandle to the animation with the given name.
Definition: SkeletonT.cc:843
INIFile
Class for the handling of simple configuration files.
Definition: INIFile.hh:105
SkeletonT::begin
Iterator begin()
Iterator over joints of the skeletal tree in TOP-DOWN order (from root to leafs)
Definition: SkeletonT.cc:714
FileSKLPlugin::getLoadFilters
QString getLoadFilters()
Definition: FileSkeleton.cc:65
FrameAnimationT::pose
Pose * pose(unsigned int _iFrame)
Returns a pointer to the pose stored in the given frame.
Definition: FrameAnimationT.cc:151
OpenMesh::VectorT
Definition: Vector11T.hh:83
SkeletonT::animationCount
unsigned int animationCount()
Returns the number of animations stored in this skeleton.
Definition: SkeletonT.cc:971
SkeletonT
Definition: JointT.hh:56
SkeletonObject::skeleton
Skeleton * skeleton()
Returns a pointer to the skeleton.
Definition: SkeletonObject.cc:210
FileSKLPlugin::saveIniFile
void saveIniFile(INIFile &_ini, int _id)
Save per object settings.
Definition: FileSkeleton.cc:361
FileSKLPlugin::supportedType
DataType supportedType()
Return your supported object type( e.g. DATA_TRIANGLE_MESH )
Definition: FileSkeleton.cc:73
AnimationHandle
A handle used to refer to an animation or to a specific frame in an animation.
Definition: AnimationHandle.hh:56
PluginFunctions::objectCount
int objectCount()
Get the number of available objects.
Definition: PluginFunctions.cc:1004
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
PoseT::globalMatrix
const Matrix & globalMatrix(unsigned int _joint) const
Returns the global matrix for the given joint.
Definition: PoseT.cc:199
DATA_SKELETON
#define DATA_SKELETON
Definition: Skeleton.hh:70
JointT
Represents a single joint in the skeleton.
Definition: JointT.hh:66
ACG::Matrix4x4T
Definition: Matrix4x4T.hh:98
FrameAnimationT
Definition: FrameAnimationT.hh:56
FileSKLPlugin
Definition: FileSkeleton.hh:65
INIFile::get_entryVecf
bool get_entryVecf(VectorT &_val, const QString &_section, const QString &_key) const
Get a Vec_n_i (int)
Definition: INIFileT.cc:169
FileSKLPlugin::getSaveFilters
QString getSaveFilters()
Definition: FileSkeleton.cc:69