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