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
44 #include <OpenFlipper/BasePlugin/PluginFunctions.hh>
45
46 #include <OpenMesh/Core/IO/IOManager.hh>
47
48
49
50 void FileSKLPlugin::initializePlugin() {
51 }
52
53 QString FileSKLPlugin::getLoadFilters() {
54 return QString( "Skeleton files ( *.skl )" );
55 };
56
57 QString FileSKLPlugin::getSaveFilters() {
58 return QString( "Skeleton files ( *.skl )" );
59 };
60
61 DataType FileSKLPlugin::supportedType() {
62 DataType type = DATA_SKELETON;
63 return type;
64 }
65
66 template<typename Skeleton>
67 bool FileSKLPlugin::LoadSkeleton(Skeleton *_pSkeleton, QString _filename)
68 {
69 typedef JointT<typename Skeleton::Point> Joint;
70 typedef PoseT<typename Skeleton::Point> Pose;
71 typedef ACG::Matrix4x4T<typename Skeleton::Scalar> Matrix;
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
196 int 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 {
204 SkeletonObject* skel = PluginFunctions::skeletonObject(obj);
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
222 template<typename Skeleton>
223 bool FileSKLPlugin::SaveSkeleton(Skeleton *_pSkeleton, QString _filename)
224 {
225 typedef JointT<typename Skeleton::Point> Joint;
226 typedef PoseT<typename Skeleton::Point> Pose;
227 typedef ACG::Matrix4x4T<typename Skeleton::Scalar> Matrix;
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
313 bool FileSKLPlugin::saveObject(int _id, QString _filename)
314 {
315 BaseObjectData *obj(0);
316 if(PluginFunctions::getObject(_id, obj))
317 {
318 SkeletonObject *skel = PluginFunctions::skeletonObject(obj);
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
333 void 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
349 void 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
FrameAnimationT::pose
Pose * pose(unsigned int _iFrame)
Returns a pointer to the pose stored in the given frame.
Definition: FrameAnimationT_impl.hh:145
UPDATE_ALL
const UpdateType UPDATE_ALL(UpdateTypeSet(1))
Identifier for all updates.
DATA_SKELETON
#define DATA_SKELETON
Definition: Skeleton.hh:64
PoseT::globalMatrix
const Matrix & globalMatrix(unsigned int _joint) const
Returns the global matrix for the given joint.
Definition: PoseT_impl.hh:193
BaseObjectData::materialNode
MaterialNode * materialNode()
get a pointer to the materialnode
Definition: BaseObjectData.cc:263
BaseObject::id
int id() const
Definition: BaseObject.cc:190
PluginFunctions.hh
SkeletonT
Definition: JointT.hh:50
BaseObject::source
bool source()
Definition: BaseObject.cc:291
PoseT::setGlobalMatrix
void setGlobalMatrix(unsigned int _joint, const Matrix &_global, bool _keepGlobalChildPositions=true)
Sets the global coordinate system.
Definition: PoseT_impl.hh:211
BaseObject::setFromFileName
void setFromFileName(const QString &_filename)
Definition: BaseObject.cc:716
PluginFunctions::skeletonObject
SkeletonObject * skeletonObject(BaseObjectData *_object)
Cast an BaseObject to a SkeletonObject if possible.
Definition: PluginFunctionsSkeleton.cc:99
PoseT
A general pose, used to store the frames of the animation.
Definition: PoseT.hh:58
FileSKLPlugin::name
QString name()
Return a name for the plugin.
Definition: FileSkeleton.hh:91
LOGERR
Definition: LoggingInterface.hh:96
SkeletonT::animationCount
size_t animationCount()
Returns the number of animations stored in this skeleton.
Definition: SkeletonT_impl.hh:965
SkeletonT::Iterator
Iterator class for the skeleton.
Definition: SkeletonT.hh:82
SkeletonT::end
Iterator end()
Compare an iterator with the return value of this method to test if it is done.
Definition: SkeletonT_impl.hh:719
BaseObjectData::setName
virtual void setName(QString _name)
path to the file from which the object is loaded ( defaults to "." )
Definition: BaseObjectData.cc:355
PluginFunctions::getObject
bool getObject(const int _identifier, BaseObject *&_object)
Get the object which has the given identifier.
Definition: PluginFunctions.cc:294
BaseObject::name
QString name() const
return the name of the object. The name defaults to NONAME if unset.
Definition: BaseObject.cc:730
FrameAnimationT
Definition: FrameAnimationT.hh:47
INIFile::get_entryVecf
bool get_entryVecf(VectorT &_val, const QString &_section, const QString &_key) const
Get a Vec_n_i (int)
Definition: INIFileT_impl.hh:163
AnimationHandle
A handle used to refer to an animation or to a specific frame in an animation.
Definition: AnimationHandle.hh:47
FileSKLPlugin::supportedType
DataType supportedType()
Return your supported object type( e.g. DATA_TRIANGLE_MESH )
Definition: FileSkeleton.cc:61
FileSKLPlugin::loadIniFile
void loadIniFile(INIFile &_ini, int _id)
Load per object settings.
Definition: FileSkeleton.cc:333
SkeletonT::referencePose
Pose * referencePose()
Returns a pointer to the reference pose.
Definition: SkeletonT_impl.hh:755
BaseObject::filename
QString filename() const
return the filename of the object
Definition: BaseObject.cc:706
SkeletonObject::skeleton
Skeleton * skeleton()
Returns a pointer to the skeleton.
Definition: SkeletonObject.cc:207
SkeletonT::begin
Iterator begin()
Iterator over joints of the skeletal tree in TOP-DOWN order (from root to leafs)
Definition: SkeletonT_impl.hh:708
SkeletonT::pose
Pose * pose(const AnimationHandle &_hAni)
Returns a pointer to the pose with the given animation handle.
Definition: SkeletonT_impl.hh:735
JointT
Represents a single joint in the skeleton.
Definition: JointT.hh:60
ACG::Matrix4x4T
Definition: Matrix4x4T.hh:92
DataType
Predefined datatypes.
Definition: DataTypes.hh:83
ACG::SceneGraph::MaterialNode::base_color
const Vec4f & base_color() const
get the base color ( same as emission() )
Definition: MaterialNode.hh:423
SkeletonT::animationHandle
AnimationHandle animationHandle(std::string _name)
Get an AnimationHandle to the animation with the given name.
Definition: SkeletonT_impl.hh:837
OpenMesh::VectorT
Definition: Vector11T.hh:83
SkeletonT::jointCount
size_t jointCount()
Returns the number of joints.
Definition: SkeletonT_impl.hh:695
AnimationT< ACG::Vec3d >
SkeletonT::animation
Animation * animation(std::string _name)
Returns a pointer to the animation to the given name.
Definition: SkeletonT_impl.hh:852
AnimationHandle::setFrame
void setFrame(size_t _iFrame)
Sets the current animation frame (not failsafe)
Definition: AnimationHandle.hh:62
SkeletonObject
Definition: SkeletonObject.hh:72
PluginFunctions::objectCount
int objectCount()
Get the number of available objects.
Definition: PluginFunctions.cc:1000
INIFile::add_entryVec
void add_entryVec(const QString &_section, const QString &_key, const VectorT &_value)
Addition of a Vec_n_something.
Definition: INIFileT_impl.hh:205
FileSKLPlugin::getLoadFilters
QString getLoadFilters()
Definition: FileSkeleton.cc:53
BaseObjectData
Definition: BaseObjectData.hh:102
ACG::SceneGraph::MaterialNode::set_base_color
void set_base_color(const Vec4f &_c)
set the base color ( Same as set_emission(const Vec4f& _c) )
Definition: MaterialNode.hh:421
FileSKLPlugin::saveIniFile
void saveIniFile(INIFile &_ini, int _id)
Save per object settings.
Definition: FileSkeleton.cc:349
FileSKLPlugin::getSaveFilters
QString getSaveFilters()
Definition: FileSkeleton.cc:57
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_impl.hh:488
FileSKLPlugin::initializePlugin
void initializePlugin()
Initialize Plugin.
Definition: FileSkeleton.cc:50
INIFile
Class for the handling of simple configuration files.
Definition: INIFile.hh:99