source: OGRE/trunk/ogrenew/Tools/XMLConverter/src/OgreXMLSkeletonSerializer.cpp @ 657

Revision 657, 21.9 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25
26#include "OgreXMLSkeletonSerializer.h"
27#include "OgreSkeleton.h"
28#include "OgreAnimation.h"
29#include "OgreAnimationTrack.h"
30#include "OgreKeyFrame.h"
31#include "OgreBone.h"
32#include "OgreString.h"
33#include "OgreLogManager.h"
34#include "OgreStringConverter.h"
35#include "Ogre.h"
36
37#include <map>
38
39namespace Ogre {
40
41   
42    //---------------------------------------------------------------------
43    XMLSkeletonSerializer::XMLSkeletonSerializer()
44    {
45    }
46    //---------------------------------------------------------------------
47    XMLSkeletonSerializer::~XMLSkeletonSerializer()
48    {
49    }
50
51    //---------------------------------------------------------------------
52    void XMLSkeletonSerializer::importSkeleton(const String& filename, Skeleton* pSkeleton)
53    {   
54                LogManager::getSingleton().logMessage("XMLSkeletonSerializer: reading XML data from " + filename + "...");
55
56                mXMLDoc = new TiXmlDocument(filename);
57        mXMLDoc->LoadFile();
58
59                TiXmlElement* elem;
60
61        TiXmlElement* rootElem = mXMLDoc->RootElement();
62
63        // Bones
64        elem = rootElem->FirstChildElement("bones");
65        if (elem)
66                {
67            readBones(pSkeleton, elem);                 
68                        elem = rootElem->FirstChildElement("bonehierarchy");
69
70                        if (elem)
71                        {
72                                createHierarchy(pSkeleton, elem) ;
73                                elem = rootElem->FirstChildElement("bones");
74                                if (elem)
75                                {
76                                        readBones2(pSkeleton, elem);
77                                        elem = rootElem->FirstChildElement("animations");
78                                        if (elem)
79                                        {
80                                                readAnimations(pSkeleton, elem);
81                                        }
82                                        elem = rootElem->FirstChildElement("animationlinks");
83                                        if (elem)
84                                        {
85                                                readSkeletonAnimationLinks(pSkeleton, elem);
86                                        }
87                                }
88                        }
89                }
90                LogManager::getSingleton().logMessage("XMLSkeletonSerializer: Finished. Running SkeletonSerializer..." );
91    }
92       
93
94        //---------------------------------------------------------------------
95        // sets names
96        void XMLSkeletonSerializer::readBones(Skeleton* skel, TiXmlElement* mBonesNode)
97    {
98        LogManager::getSingleton().logMessage("XMLSkeletonSerializer: Reading Bones name...");
99               
100                Bone* btmp ;
101                Quaternion quat ;
102
103        for (TiXmlElement* bonElem = mBonesNode->FirstChildElement();
104            bonElem != 0; bonElem = bonElem->NextSiblingElement())
105        {
106            String name = bonElem->Attribute("name");
107                        int id = StringConverter::parseInt(bonElem->Attribute("id"));                           
108                        btmp = skel->createBone(name,id) ;
109
110        }
111    }
112        // ---------------------------------------------------------
113        // set positions and orientations.
114        void XMLSkeletonSerializer::readBones2(Skeleton* skel, TiXmlElement* mBonesNode)
115    {
116        LogManager::getSingleton().logMessage("XMLSkeletonSerializer: Reading Bones data...");
117               
118                Bone* btmp ;
119                Quaternion quat ;
120
121        for (TiXmlElement* bonElem = mBonesNode->FirstChildElement();
122            bonElem != 0; bonElem = bonElem->NextSiblingElement())
123        {
124            String name = bonElem->Attribute("name");
125                        int id = StringConverter::parseInt(bonElem->Attribute("id"));
126
127                        TiXmlElement* posElem = bonElem->FirstChildElement("position");
128                        TiXmlElement* rotElem = bonElem->FirstChildElement("rotation");
129                        TiXmlElement* axisElem = rotElem->FirstChildElement("axis");
130                       
131                        Vector3 pos;
132                        Vector3 axis;
133                        Radian angle ;
134
135                        pos.x = StringConverter::parseReal(posElem->Attribute("x"));
136                        pos.y = StringConverter::parseReal(posElem->Attribute("y"));
137                        pos.z = StringConverter::parseReal(posElem->Attribute("z"));
138                       
139                        angle = Radian(StringConverter::parseReal(rotElem->Attribute("angle")));
140
141                        axis.x = StringConverter::parseReal(axisElem->Attribute("x"));
142                        axis.y = StringConverter::parseReal(axisElem->Attribute("y"));
143                        axis.z = StringConverter::parseReal(axisElem->Attribute("z"));
144                       
145                        /*LogManager::getSingleton().logMessage("bone " + name + " : position("
146                                + StringConverter::toString(pos.x) + "," + StringConverter::toString(pos.y) + "," + StringConverter::toString(pos.z) + ")"
147                                + " - angle: " + StringConverter::toString(angle) +" - axe: "
148                                + StringConverter::toString(axis.x) + "," + StringConverter::toString(axis.y) + "," + StringConverter::toString(axis.z) );
149                        */             
150                       
151                        btmp = skel->getBone(name) ;
152
153                        btmp -> setPosition(pos);
154                        quat.FromAngleAxis(angle,axis);
155                        btmp -> setOrientation(quat) ;
156
157        } // bones
158    }
159        //-------------------------------------------------------------------
160        void XMLSkeletonSerializer::createHierarchy(Skeleton* skel, TiXmlElement* mHierNode) {
161               
162                LogManager::getSingleton().logMessage("XMLSkeletonSerializer: Reading Hierarchy data...");
163               
164                Bone* bone ;
165                Bone* parent ;
166                String boneName ;
167                String parentName ;
168
169                for (TiXmlElement* hierElem = mHierNode->FirstChildElement() ; hierElem != 0; hierElem = hierElem->NextSiblingElement())
170        {
171                        boneName = hierElem->Attribute("bone");
172                        parentName = hierElem->Attribute("parent");
173                        bone = skel->getBone(boneName);
174                        parent = skel->getBone(parentName);
175                        parent ->addChild(bone) ;
176                        //LogManager::getSingleton().logMessage("XMLSkeletonSerialiser: lien: " + parent->getName() + "->" + bone->getName());
177                       
178                }
179        }
180        //---------------------------------------------------------------------
181        void XMLSkeletonSerializer::readAnimations(Skeleton* skel, TiXmlElement* mAnimNode) {
182               
183                Animation * anim ;
184                AnimationTrack * track ;
185                LogManager::getSingleton().logMessage("XMLSkeletonSerializer: Reading Animations data...");
186
187                for (TiXmlElement* animElem = mAnimNode->FirstChildElement("animation"); animElem != 0; animElem = animElem->NextSiblingElement())
188        {
189            String name = animElem->Attribute("name");
190                        Real length = StringConverter::parseReal(animElem->Attribute("length"));
191                        anim = skel->createAnimation(name,length);
192                        anim->setInterpolationMode(Animation::IM_LINEAR) ;
193
194                       
195                        LogManager::getSingleton().logMessage("Animation: nom: " + name + " et longueur: "
196                                + StringConverter::toString(length) );
197                       
198                        // lecture des tracks
199                        int trackIndex = 0;
200                        TiXmlElement* tracksNode = animElem->FirstChildElement("tracks");
201                       
202                        for (TiXmlElement* trackElem = tracksNode->FirstChildElement("track"); trackElem != 0; trackElem = trackElem->NextSiblingElement())
203                        {
204                                String boneName = trackElem->Attribute("bone");
205
206                                //LogManager::getSingleton().logMessage("Track sur le bone: " + boneName );
207
208                                track = anim->createTrack(trackIndex++,skel->getBone(boneName));
209                                readKeyFrames(track, trackElem->FirstChildElement("keyframes"));
210                        }
211                       
212                }
213
214
215        }
216        //---------------------------------------------------------------------
217        void XMLSkeletonSerializer::readKeyFrames(AnimationTrack* track, TiXmlElement* mKeyfNode) {
218               
219                KeyFrame* kf ;
220                Quaternion q ;
221
222                for (TiXmlElement* keyfElem = mKeyfNode->FirstChildElement("keyframe"); keyfElem != 0; keyfElem = keyfElem->NextSiblingElement())
223        {
224                        Vector3 trans;
225                        Vector3 axis;
226                        Radian angle;
227                        Real time;
228
229            // Get time and create keyframe
230                        time = StringConverter::parseReal(keyfElem->Attribute("time"));
231                        kf = track->createKeyFrame(time);
232            // Optional translate
233                        TiXmlElement* transElem = keyfElem->FirstChildElement("translate");
234            if (transElem)
235            {
236                            trans.x = StringConverter::parseReal(transElem->Attribute("x"));
237                            trans.y = StringConverter::parseReal(transElem->Attribute("y"));
238                            trans.z = StringConverter::parseReal(transElem->Attribute("z"));
239                            kf->setTranslate(trans) ;
240            }
241            // Optional rotate
242                        TiXmlElement* rotElem = keyfElem->FirstChildElement("rotate");
243            if (rotElem)
244            {
245                TiXmlElement* axisElem = rotElem->FirstChildElement("axis");
246                if (!axisElem)
247                {
248                    OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Missing 'axis' element "
249                    "expected under parent 'rotate'", "MXLSkeletonSerializer::readKeyFrames");
250                }
251                            angle = Radian(StringConverter::parseReal(rotElem->Attribute("angle")));
252
253                            axis.x = StringConverter::parseReal(axisElem->Attribute("x"));
254                            axis.y = StringConverter::parseReal(axisElem->Attribute("y"));
255                            axis.z = StringConverter::parseReal(axisElem->Attribute("z"));
256
257                            q.FromAngleAxis(angle,axis);
258                            kf->setRotation(q) ;
259
260            }
261            // Optional scale
262                        TiXmlElement* scaleElem = keyfElem->FirstChildElement("scale");
263            if (scaleElem)
264            {
265                // Uniform scale or per axis?
266                                const char* factorAttrib = scaleElem->Attribute("factor");
267                                if (factorAttrib)
268                                {
269                                        // Uniform scale
270                                        Real factor = StringConverter::parseReal(factorAttrib);
271                                        kf->setScale(Vector3(factor, factor, factor));
272                                }
273                                else
274                                {
275                                        // axis scale
276                    Real xs = 1.0f, ys = 1.0f, zs=1.0f;
277                    const char* factorString = scaleElem->Attribute("x");
278                    if(factorString)
279                    {
280                        xs = StringConverter::parseReal(factorString);
281                    }
282                    factorString = scaleElem->Attribute("y");
283                    if(factorString)
284                    {
285                        ys = StringConverter::parseReal(factorString);
286                    }
287                    factorString = scaleElem->Attribute("z");
288                    if(factorString)
289                    {
290                        zs = StringConverter::parseReal(factorString);
291                    }
292                                        kf->setScale(Vector3(xs, ys, zs));
293                                       
294                                }
295            }
296
297                       
298                        /*
299                        LogManager::getSingleton().logMessage("Keyframe: translation("
300                                + StringConverter::toString(trans.x) + "," + StringConverter::toString(trans.y) + "," + StringConverter::toString(trans.z) + ")"
301                                + " - angle: " + StringConverter::toString(angle) +" - axe: "
302                                + StringConverter::toString(axis.x) + "," + StringConverter::toString(axis.y) + "," + StringConverter::toString(axis.z) );
303                        */
304                       
305
306                }
307        }
308
309    //---------------------------------------------------------------------
310    void XMLSkeletonSerializer::exportSkeleton(const Skeleton* pSkeleton,
311        const String& filename)
312    {
313               
314        LogManager::getSingleton().logMessage("XMLSkeletonSerializer writing "
315            " skeleton data to " + filename + "...");
316
317        mXMLDoc = new TiXmlDocument();
318        mXMLDoc->InsertEndChild(TiXmlElement("skeleton"));
319        TiXmlElement* rootNode = mXMLDoc->RootElement();
320
321        LogManager::getSingleton().logMessage("Populating DOM...");
322
323
324        // Write main skeleton data
325        LogManager::getSingleton().logMessage("Exporting bones..");
326        writeSkeleton(pSkeleton);
327        LogManager::getSingleton().logMessage("Bones exported.");
328               
329        // Write all animations
330        unsigned short numAnims = pSkeleton->getNumAnimations();
331                String msg = "Exporting animations, count=" + StringConverter::toString(numAnims);
332        LogManager::getSingleton().logMessage(msg);
333
334        TiXmlElement* animsNode =
335            rootNode->InsertEndChild(TiXmlElement("animations"))->ToElement();
336       
337        for (unsigned short i = 0; i < numAnims; ++i)
338        {
339            Animation* pAnim = pSkeleton->getAnimation(i);
340            msg = "Exporting animation: " + pAnim->getName();
341            LogManager::getSingleton().logMessage(msg);
342            writeAnimation(animsNode, pAnim);
343            LogManager::getSingleton().logMessage("Animation exported.");
344
345        }
346
347                // Write links
348                Skeleton::LinkedSkeletonAnimSourceIterator linkIt =
349                        pSkeleton->getLinkedSkeletonAnimationSourceIterator();
350                if (linkIt.hasMoreElements())
351                {
352                        LogManager::getSingleton().logMessage("Exporting animation links.");
353                        TiXmlElement* linksNode =
354                                rootNode->InsertEndChild(TiXmlElement("animationlinks"))->ToElement();
355                        while(linkIt.hasMoreElements())
356                        {
357                                const LinkedSkeletonAnimationSource& link = linkIt.getNext();
358                                writeSkeletonAnimationLink(linksNode, link);
359                        }
360                }
361
362        LogManager::getSingleton().logMessage("DOM populated, writing XML file..");
363
364        // Write out to a file
365        mXMLDoc->SaveFile(filename);
366
367   
368        delete mXMLDoc;
369
370        LogManager::getSingleton().logMessage("XMLSkeletonSerializer export successful.");
371       
372    }
373    //---------------------------------------------------------------------
374    void XMLSkeletonSerializer::writeSkeleton(const Skeleton* pSkel)
375    {
376        TiXmlElement* rootNode = mXMLDoc->RootElement();
377
378        TiXmlElement* bonesElem =
379            rootNode->InsertEndChild(TiXmlElement("bones"))->ToElement();
380
381        unsigned short numBones = pSkel->getNumBones();
382                LogManager::getSingleton().logMessage("There are " + StringConverter::toString(numBones) + " bones.");
383        unsigned short i;
384        for (i = 0; i < numBones; ++i)
385        {
386                        LogManager::getSingleton().logMessage("   Exporting Bone number " + StringConverter::toString(i));
387            Bone* pBone = pSkel->getBone(i);
388            writeBone(bonesElem, pBone);
389        }
390
391        // Write parents
392        TiXmlElement* hierElem =
393            rootNode->InsertEndChild(TiXmlElement("bonehierarchy"))->ToElement();
394        for (i = 0; i < numBones; ++i)
395        {
396            Bone* pBone = pSkel->getBone(i);
397            unsigned short handle = pBone->getHandle();
398                        String name = pBone->getName() ;
399            /* BEFORE
400                        if (handle != 0) // root bone
401            {
402                Bone* pParent = (Bone*)pBone->getParent();
403                writeBoneParent(hierElem, name, pParent->getName());
404            }
405                        *//* AFTER */
406                        if ((pBone->getParent())!=NULL) // root bone
407            {
408                Bone* pParent = (Bone*)pBone->getParent();
409                writeBoneParent(hierElem, name, pParent->getName());
410            }
411        }
412
413
414    }
415    //---------------------------------------------------------------------
416    void XMLSkeletonSerializer::writeBone(TiXmlElement* bonesElement, const Bone* pBone)
417    {
418        TiXmlElement* boneElem =
419            bonesElement->InsertEndChild(TiXmlElement("bone"))->ToElement();
420
421       
422        // Bone name & handle
423        boneElem->SetAttribute("id",
424            StringConverter::toString(pBone->getHandle()));
425        boneElem->SetAttribute("name", pBone->getName());
426
427        // Position
428        TiXmlElement* subNode =
429            boneElem->InsertEndChild(TiXmlElement("position"))->ToElement();
430        Vector3 pos = pBone->getPosition();
431        subNode->SetAttribute("x", StringConverter::toString(pos.x));
432        subNode->SetAttribute("y", StringConverter::toString(pos.y));
433        subNode->SetAttribute("z", StringConverter::toString(pos.z));
434       
435        // Orientation
436        subNode =
437            boneElem->InsertEndChild(TiXmlElement("rotation"))->ToElement();
438        // Show Quaternion as angle / axis
439        Radian angle;
440        Vector3 axis;
441        pBone->getOrientation().ToAngleAxis(angle, axis);
442        TiXmlElement* axisNode =
443            subNode->InsertEndChild(TiXmlElement("axis"))->ToElement();
444        subNode->SetAttribute("angle", StringConverter::toString(angle.valueRadians()));
445        axisNode->SetAttribute("x", StringConverter::toString(axis.x));
446        axisNode->SetAttribute("y", StringConverter::toString(axis.y));
447        axisNode->SetAttribute("z", StringConverter::toString(axis.z));
448
449
450
451    }
452    //---------------------------------------------------------------------
453        //
454        // Modifications effectuées:
455        //
456        // on stoque les noms et pas les Id. c'est plus lisibles.
457
458
459    void XMLSkeletonSerializer::writeBoneParent(TiXmlElement* boneHierarchyNode,
460        String boneName, String parentName)
461    {
462        TiXmlElement* boneParentNode =
463            boneHierarchyNode->InsertEndChild(TiXmlElement("boneparent"))->ToElement();
464                /*
465            boneParentNode->SetAttribute("boneid", StringConverter::toString(boneId));
466        boneParentNode->SetAttribute("parentid", StringConverter::toString(parentId));
467                */
468                // Modifications: on stoque les noms./
469                boneParentNode->SetAttribute("bone", boneName);
470        boneParentNode->SetAttribute("parent", parentName);
471
472    }
473    //---------------------------------------------------------------------
474    void XMLSkeletonSerializer::writeAnimation(TiXmlElement* animsNode,
475        const Animation* anim)
476    {
477        TiXmlElement* animNode =
478            animsNode->InsertEndChild(TiXmlElement("animation"))->ToElement();
479
480        animNode->SetAttribute("name", anim->getName());
481        animNode->SetAttribute("length", StringConverter::toString(anim->getLength()));
482
483        // Write all tracks
484        TiXmlElement* tracksNode =
485            animNode->InsertEndChild(TiXmlElement("tracks"))->ToElement();
486
487        Animation::TrackIterator trackIt = anim->getTrackIterator();
488        while (trackIt.hasMoreElements())
489        {
490            writeAnimationTrack(tracksNode, trackIt.getNext());
491        }
492
493    }
494    //---------------------------------------------------------------------
495    void XMLSkeletonSerializer::writeAnimationTrack(TiXmlElement* tracksNode,
496        const AnimationTrack* track)
497    {
498        TiXmlElement* trackNode =
499            tracksNode->InsertEndChild(TiXmlElement("track"))->ToElement();
500       
501       
502        // unsigned short boneIndex     : Index of bone to apply to
503        Bone* bone = (Bone*)track->getAssociatedNode();
504        //unsigned short boneid = bone->getHandle();
505                String boneName = bone->getName();
506        trackNode->SetAttribute("bone", boneName);
507
508        // Write all keyframes
509        TiXmlElement* keysNode =
510            trackNode->InsertEndChild(TiXmlElement("keyframes"))->ToElement();
511        for (unsigned short i = 0; i < track->getNumKeyFrames(); ++i)
512        {
513            writeKeyFrame(keysNode, track->getKeyFrame(i));
514        }
515    }
516    //---------------------------------------------------------------------
517    void XMLSkeletonSerializer::writeKeyFrame(TiXmlElement* keysNode, const KeyFrame* key)
518    {
519        TiXmlElement* keyNode =
520            keysNode->InsertEndChild(TiXmlElement("keyframe"))->ToElement();
521
522        keyNode->SetAttribute("time", StringConverter::toString(key->getTime()));
523
524        TiXmlElement* transNode =
525            keyNode->InsertEndChild(TiXmlElement("translate"))->ToElement();
526        Vector3 trans = key->getTranslate();
527        transNode->SetAttribute("x", StringConverter::toString(trans.x));
528        transNode->SetAttribute("y", StringConverter::toString(trans.y));
529        transNode->SetAttribute("z", StringConverter::toString(trans.z));
530
531        TiXmlElement* rotNode =
532            keyNode->InsertEndChild(TiXmlElement("rotate"))->ToElement();
533        // Show Quaternion as angle / axis
534        Radian angle;
535        Vector3 axis;
536        key->getRotation().ToAngleAxis(angle, axis);
537        TiXmlElement* axisNode =
538            rotNode->InsertEndChild(TiXmlElement("axis"))->ToElement();
539        rotNode->SetAttribute("angle", StringConverter::toString(angle.valueRadians()));
540        axisNode->SetAttribute("x", StringConverter::toString(axis.x));
541        axisNode->SetAttribute("y", StringConverter::toString(axis.y));
542        axisNode->SetAttribute("z", StringConverter::toString(axis.z));
543
544       
545        TiXmlElement* scaleNode =
546            keyNode->InsertEndChild(TiXmlElement("scale"))->ToElement();
547
548        scaleNode->SetAttribute("x", StringConverter::toString(key->getScale().x));
549        scaleNode->SetAttribute("y", StringConverter::toString(key->getScale().y));
550        scaleNode->SetAttribute("z", StringConverter::toString(key->getScale().z));
551
552    }
553    //---------------------------------------------------------------------
554        void XMLSkeletonSerializer::writeSkeletonAnimationLink(TiXmlElement* linksNode,
555                const LinkedSkeletonAnimationSource& link)
556        {
557                TiXmlElement* linkNode =
558                        linksNode->InsertEndChild(TiXmlElement("animationlink"))->ToElement();
559                linkNode->SetAttribute("skeletonName", link.skeletonName);
560                linkNode->SetAttribute("scale", StringConverter::toString(link.scale));
561
562        }
563        //---------------------------------------------------------------------
564        void XMLSkeletonSerializer::readSkeletonAnimationLinks(Skeleton* skel,
565                TiXmlElement* linksNode)
566        {
567                LogManager::getSingleton().logMessage("XMLSkeletonSerializer: Reading Animations links...");
568
569                for (TiXmlElement* linkElem = linksNode->FirstChildElement("animationlink");
570                        linkElem != 0; linkElem = linkElem->NextSiblingElement())
571                {
572                        String skelName = linkElem->Attribute("skeletonName");
573                        const char* strScale = linkElem->Attribute("scale");
574                        Real scale;
575                        // Scale optional
576                        if (strScale == 0)
577                        {
578                                scale = 1.0f;
579                        }
580                        else
581                        {
582                                scale = StringConverter::parseReal(strScale);
583                        }
584                        skel->addLinkedSkeletonAnimationSource(skelName, scale);
585
586                }
587        }
588}
589
590
Note: See TracBrowser for help on using the repository browser.