source: OGRE/trunk/ogrenew/OgreMain/src/OgreSkeletonSerializer.cpp @ 692

Revision 692, 19.2 KB checked in by mattausch, 18 years ago (diff)

adding ogre 1.2 and dependencies

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#include "OgreStableHeaders.h"
26
27#include "OgreSkeletonFileFormat.h"
28#include "OgreSkeletonSerializer.h"
29#include "OgreSkeleton.h"
30#include "OgreAnimation.h"
31#include "OgreAnimationTrack.h"
32#include "OgreKeyFrame.h"
33#include "OgreBone.h"
34#include "OgreString.h"
35#include "OgreDataStream.h"
36#include "OgreLogManager.h"
37
38
39
40
41namespace Ogre {
42    /// stream overhead = ID + size
43    const long STREAM_OVERHEAD_SIZE = sizeof(uint16) + sizeof(uint32);
44    //---------------------------------------------------------------------
45    SkeletonSerializer::SkeletonSerializer()
46    {
47        // Version number
48        // NB changed to include bone names in 1.1
49        mVersion = "[Serializer_v1.10]";
50    }
51    //---------------------------------------------------------------------
52    SkeletonSerializer::~SkeletonSerializer()
53    {
54    }
55    //---------------------------------------------------------------------
56    void SkeletonSerializer::exportSkeleton(const Skeleton* pSkeleton,
57                const String& filename, Endian endianMode)
58    {
59                // Decide on endian mode
60                determineEndianness(endianMode);
61
62        String msg;
63        mpfFile = fopen(filename.c_str(), "wb");
64
65        writeFileHeader();
66
67        // Write main skeleton data
68        LogManager::getSingleton().logMessage("Exporting bones..");
69        writeSkeleton(pSkeleton);
70        LogManager::getSingleton().logMessage("Bones exported.");
71
72        // Write all animations
73        unsigned short numAnims = pSkeleton->getNumAnimations();
74        msg = "Exporting animations, count=";
75                StringUtil::StrStreamType num;
76                num << numAnims;
77        msg += num.str();
78        LogManager::getSingleton().logMessage(msg);
79        for (unsigned short i = 0; i < numAnims; ++i)
80        {
81            Animation* pAnim = pSkeleton->getAnimation(i);
82            msg = "Exporting animation: " + pAnim->getName();
83            LogManager::getSingleton().logMessage(msg);
84            writeAnimation(pSkeleton, pAnim);
85            LogManager::getSingleton().logMessage("Animation exported.");
86
87        }
88
89                // Write links
90                Skeleton::LinkedSkeletonAnimSourceIterator linkIt =
91                        pSkeleton->getLinkedSkeletonAnimationSourceIterator();
92                while(linkIt.hasMoreElements())
93                {
94                        const LinkedSkeletonAnimationSource& link = linkIt.getNext();
95                        writeSkeletonAnimationLink(pSkeleton, link);
96                }
97
98        fclose(mpfFile);
99
100    }
101    //---------------------------------------------------------------------
102    void SkeletonSerializer::importSkeleton(DataStreamPtr& stream, Skeleton* pSkel)
103    {
104                // Determine endianness (must be the first thing we do!)
105                determineEndianness(stream);
106
107                // Check header
108        readFileHeader(stream);
109
110        unsigned short streamID;
111        while(!stream->eof())
112        {
113            streamID = readChunk(stream);
114            switch (streamID)
115            {
116            case SKELETON_BONE:
117                readBone(stream, pSkel);
118                break;
119            case SKELETON_BONE_PARENT:
120                readBoneParent(stream, pSkel);
121                break;
122            case SKELETON_ANIMATION:
123                readAnimation(stream, pSkel);
124                                break;
125                        case SKELETON_ANIMATION_LINK:
126                                readSkeletonAnimationLink(stream, pSkel);
127                                break;
128            }
129        }
130
131        // Assume bones are stored in the binding pose
132        pSkel->setBindingPose();
133
134
135    }
136    //---------------------------------------------------------------------
137    void SkeletonSerializer::writeSkeleton(const Skeleton* pSkel)
138    {
139        // Write each bone
140        unsigned short numBones = pSkel->getNumBones();
141        unsigned short i;
142        for (i = 0; i < numBones; ++i)
143        {
144            Bone* pBone = pSkel->getBone(i);
145            writeBone(pSkel, pBone);
146        }
147        // Write parents
148        for (i = 0; i < numBones; ++i)
149        {
150            Bone* pBone = pSkel->getBone(i);
151            unsigned short handle = pBone->getHandle();
152            Bone* pParent = (Bone*)pBone->getParent();
153            if (pParent != NULL)
154            {
155                writeBoneParent(pSkel, handle, pParent->getHandle());             
156            }
157        }
158    }
159    //---------------------------------------------------------------------
160    void SkeletonSerializer::writeBone(const Skeleton* pSkel, const Bone* pBone)
161    {
162        writeChunkHeader(SKELETON_BONE, calcBoneSize(pSkel, pBone));
163
164        unsigned short handle = pBone->getHandle();
165        // char* name
166        writeString(pBone->getName());
167        // unsigned short handle            : handle of the bone, should be contiguous & start at 0
168        writeShorts(&handle, 1);
169        // Vector3 position                 : position of this bone relative to parent
170        writeObject(pBone->getPosition());
171        // Quaternion orientation           : orientation of this bone relative to parent
172        writeObject(pBone->getOrientation());
173        // Vector3 scale                    : scale of this bone relative to parent
174        if (pBone->getScale() != Vector3::UNIT_SCALE)
175        {
176            writeObject(pBone->getScale());
177        }
178    }
179    //---------------------------------------------------------------------
180    void SkeletonSerializer::writeBoneParent(const Skeleton* pSkel,
181        unsigned short boneId, unsigned short parentId)
182    {
183        writeChunkHeader(SKELETON_BONE_PARENT, calcBoneParentSize(pSkel));
184
185        // unsigned short handle             : child bone
186        writeShorts(&boneId, 1);
187        // unsigned short parentHandle   : parent bone
188        writeShorts(&parentId, 1);
189
190    }
191    //---------------------------------------------------------------------
192    void SkeletonSerializer::writeAnimation(const Skeleton* pSkel,
193        const Animation* anim)
194    {
195        writeChunkHeader(SKELETON_ANIMATION, calcAnimationSize(pSkel, anim));
196
197        // char* name                       : Name of the animation
198        writeString(anim->getName());
199        // float length                      : Length of the animation in seconds
200        float len = anim->getLength();
201        writeFloats(&len, 1);
202
203        // Write all tracks
204        Animation::NodeTrackIterator trackIt = anim->getNodeTrackIterator();
205        while(trackIt.hasMoreElements())
206        {
207            writeAnimationTrack(pSkel, trackIt.getNext());
208        }
209
210    }
211    //---------------------------------------------------------------------
212    void SkeletonSerializer::writeAnimationTrack(const Skeleton* pSkel,
213        const NodeAnimationTrack* track)
214    {
215        writeChunkHeader(SKELETON_ANIMATION_TRACK, calcAnimationTrackSize(pSkel, track));
216
217        // unsigned short boneIndex     : Index of bone to apply to
218        Bone* bone = (Bone*)track->getAssociatedNode();
219        unsigned short boneid = bone->getHandle();
220        writeShorts(&boneid, 1);
221
222        // Write all keyframes
223        for (unsigned short i = 0; i < track->getNumKeyFrames(); ++i)
224        {
225            writeKeyFrame(pSkel, track->getNodeKeyFrame(i));
226        }
227
228    }
229    //---------------------------------------------------------------------
230    void SkeletonSerializer::writeKeyFrame(const Skeleton* pSkel,
231        const TransformKeyFrame* key)
232    {
233
234        writeChunkHeader(SKELETON_ANIMATION_TRACK_KEYFRAME,
235            calcKeyFrameSize(pSkel, key));
236
237        // float time                    : The time position (seconds)
238        float time = key->getTime();
239        writeFloats(&time, 1);
240        // Quaternion rotate            : Rotation to apply at this keyframe
241        writeObject(key->getRotation());
242        // Vector3 translate            : Translation to apply at this keyframe
243        writeObject(key->getTranslate());
244        // Vector3 scale                : Scale to apply at this keyframe
245        if (key->getScale() != Vector3::UNIT_SCALE)
246        {
247            writeObject(key->getScale());
248        }
249    }
250    //---------------------------------------------------------------------
251    size_t SkeletonSerializer::calcBoneSize(const Skeleton* pSkel,
252        const Bone* pBone)
253    {
254        size_t size = STREAM_OVERHEAD_SIZE;
255
256        // handle
257        size += sizeof(unsigned short);
258
259        // position
260        size += sizeof(float) * 3;
261
262        // orientation
263        size += sizeof(float) * 4;
264
265        // scale
266        if (pBone->getScale() != Vector3::UNIT_SCALE)
267        {
268            size += sizeof(float) * 3;
269        }
270
271        return size;
272    }
273    //---------------------------------------------------------------------
274    size_t SkeletonSerializer::calcBoneSizeWithoutScale(const Skeleton* pSkel,
275        const Bone* pBone)
276    {
277        size_t size = STREAM_OVERHEAD_SIZE;
278
279        // handle
280        size += sizeof(unsigned short);
281
282        // position
283        size += sizeof(float) * 3;
284
285        // orientation
286        size += sizeof(float) * 4;
287
288        return size;
289    }
290    //---------------------------------------------------------------------
291    size_t SkeletonSerializer::calcBoneParentSize(const Skeleton* pSkel)
292    {
293        size_t size = STREAM_OVERHEAD_SIZE;
294
295        // handle
296        size += sizeof(unsigned short);
297
298        // parent handle
299        size += sizeof(unsigned short);
300
301        return size;
302    }
303    //---------------------------------------------------------------------
304    size_t SkeletonSerializer::calcAnimationSize(const Skeleton* pSkel,
305        const Animation* pAnim)
306    {
307        size_t size = STREAM_OVERHEAD_SIZE;
308
309        // Name, including terminator
310        size += pAnim->getName().length() + 1;
311        // length
312        size += sizeof(float);
313
314        // Nested animation tracks
315                Animation::NodeTrackIterator trackIt = pAnim->getNodeTrackIterator();
316                while(trackIt.hasMoreElements())
317                {
318            size += calcAnimationTrackSize(pSkel, trackIt.getNext());
319        }
320
321        return size;
322    }
323    //---------------------------------------------------------------------
324    size_t SkeletonSerializer::calcAnimationTrackSize(const Skeleton* pSkel,
325        const NodeAnimationTrack* pTrack)
326    {
327        size_t size = STREAM_OVERHEAD_SIZE;
328
329        // unsigned short boneIndex     : Index of bone to apply to
330        size += sizeof(unsigned short);
331
332        // Nested keyframes
333        for (unsigned short i = 0; i < pTrack->getNumKeyFrames(); ++i)
334        {
335            size += calcKeyFrameSize(pSkel, pTrack->getNodeKeyFrame(i));
336        }
337
338        return size;
339    }
340    //---------------------------------------------------------------------
341    size_t SkeletonSerializer::calcKeyFrameSize(const Skeleton* pSkel,
342        const TransformKeyFrame* pKey)
343    {
344        size_t size = STREAM_OVERHEAD_SIZE;
345
346        // float time                    : The time position (seconds)
347        size += sizeof(float);
348        // Quaternion rotate            : Rotation to apply at this keyframe
349        size += sizeof(float) * 4;
350        // Vector3 translate            : Translation to apply at this keyframe
351        size += sizeof(float) * 3;
352        // Vector3 scale                : Scale to apply at this keyframe
353        if (pKey->getScale() != Vector3::UNIT_SCALE)
354        {
355            size += sizeof(float) * 3;
356        }
357
358        return size;
359    }
360    //---------------------------------------------------------------------
361    size_t SkeletonSerializer::calcKeyFrameSizeWithoutScale(const Skeleton* pSkel,
362        const TransformKeyFrame* pKey)
363    {
364        size_t size = STREAM_OVERHEAD_SIZE;
365
366        // float time                    : The time position (seconds)
367        size += sizeof(float);
368        // Quaternion rotate            : Rotation to apply at this keyframe
369        size += sizeof(float) * 4;
370        // Vector3 translate            : Translation to apply at this keyframe
371        size += sizeof(float) * 3;
372
373        return size;
374    }
375    //---------------------------------------------------------------------
376    void SkeletonSerializer::readBone(DataStreamPtr& stream, Skeleton* pSkel)
377    {
378        // char* name
379        String name = readString(stream);
380        // unsigned short handle            : handle of the bone, should be contiguous & start at 0
381        unsigned short handle;
382        readShorts(stream, &handle, 1);
383
384        // Create new bone
385        Bone* pBone = pSkel->createBone(name, handle);
386
387        // Vector3 position                 : position of this bone relative to parent
388        Vector3 pos;
389        readObject(stream, pos);
390        pBone->setPosition(pos);
391        // Quaternion orientation           : orientation of this bone relative to parent
392        Quaternion q;
393        readObject(stream, q);
394        pBone->setOrientation(q);
395        // Do we have scale?
396        if (mCurrentstreamLen > calcBoneSizeWithoutScale(pSkel, pBone))
397        {
398            Vector3 scale;
399            readObject(stream, scale);
400            pBone->setScale(scale);
401        }
402    }
403    //---------------------------------------------------------------------
404    void SkeletonSerializer::readBoneParent(DataStreamPtr& stream, Skeleton* pSkel)
405    {
406        // All bones have been created by this point
407        Bone *child, *parent;
408        unsigned short childHandle, parentHandle;
409
410        // unsigned short handle             : child bone
411        readShorts(stream, &childHandle, 1);
412        // unsigned short parentHandle   : parent bone
413        readShorts(stream, &parentHandle, 1);
414
415        // Find bones
416        parent = pSkel->getBone(parentHandle);
417        child = pSkel->getBone(childHandle);
418
419        // attach
420        parent->addChild(child);
421
422    }
423    //---------------------------------------------------------------------
424    void SkeletonSerializer::readAnimation(DataStreamPtr& stream, Skeleton* pSkel)
425    {
426        // char* name                       : Name of the animation
427        String name;
428        name = readString(stream);
429        // float length                      : Length of the animation in seconds
430        float len;
431        readFloats(stream, &len, 1);
432
433        Animation *pAnim = pSkel->createAnimation(name, len);
434
435        // Read all tracks
436        if (!stream->eof())
437        {
438            unsigned short streamID = readChunk(stream);
439            while(streamID == SKELETON_ANIMATION_TRACK && !stream->eof())
440            {
441                readAnimationTrack(stream, pAnim, pSkel);
442
443                if (!stream->eof())
444                {
445                    // Get next stream
446                    streamID = readChunk(stream);
447                }
448            }
449            if (!stream->eof())
450            {
451                // Backpedal back to start of this stream if we've found a non-track
452                stream->skip(-STREAM_OVERHEAD_SIZE);
453            }
454
455        }
456
457
458
459    }
460    //---------------------------------------------------------------------
461    void SkeletonSerializer::readAnimationTrack(DataStreamPtr& stream, Animation* anim,
462        Skeleton* pSkel)
463    {
464        // unsigned short boneIndex     : Index of bone to apply to
465        unsigned short boneHandle;
466        readShorts(stream, &boneHandle, 1);
467
468        // Find bone
469        Bone *targetBone = pSkel->getBone(boneHandle);
470
471        // Create track
472        NodeAnimationTrack* pTrack = anim->createNodeTrack(boneHandle, targetBone);
473
474        // Keep looking for nested keyframes
475        if (!stream->eof())
476        {
477            unsigned short streamID = readChunk(stream);
478            while(streamID == SKELETON_ANIMATION_TRACK_KEYFRAME && !stream->eof())
479            {
480                readKeyFrame(stream, pTrack, pSkel);
481
482                if (!stream->eof())
483                {
484                    // Get next stream
485                    streamID = readChunk(stream);
486                }
487            }
488            if (!stream->eof())
489            {
490                // Backpedal back to start of this stream if we've found a non-keyframe
491                stream->skip(-STREAM_OVERHEAD_SIZE);
492            }
493
494        }
495
496
497    }
498    //---------------------------------------------------------------------
499    void SkeletonSerializer::readKeyFrame(DataStreamPtr& stream, NodeAnimationTrack* track,
500        Skeleton* pSkel)
501    {
502        // float time                    : The time position (seconds)
503        float time;
504        readFloats(stream, &time, 1);
505
506        TransformKeyFrame *kf = track->createNodeKeyFrame(time);
507
508        // Quaternion rotate            : Rotation to apply at this keyframe
509        Quaternion rot;
510        readObject(stream, rot);
511        kf->setRotation(rot);
512        // Vector3 translate            : Translation to apply at this keyframe
513        Vector3 trans;
514        readObject(stream, trans);
515        kf->setTranslate(trans);
516        // Do we have scale?
517        if (mCurrentstreamLen > calcKeyFrameSizeWithoutScale(pSkel, kf))
518        {
519            Vector3 scale;
520            readObject(stream, scale);
521            kf->setScale(scale);
522        }
523    }
524        //---------------------------------------------------------------------
525        void SkeletonSerializer::writeSkeletonAnimationLink(const Skeleton* pSkel,
526                const LinkedSkeletonAnimationSource& link)
527        {
528                writeChunkHeader(SKELETON_ANIMATION_LINK,
529                        calcSkeletonAnimationLinkSize(pSkel, link));
530
531                // char* skeletonName
532                writeString(link.skeletonName);
533                // float scale
534                writeFloats(&(link.scale), 1);
535
536        }
537    //---------------------------------------------------------------------
538        size_t SkeletonSerializer::calcSkeletonAnimationLinkSize(const Skeleton* pSkel,
539                const LinkedSkeletonAnimationSource& link)
540        {
541                size_t size = STREAM_OVERHEAD_SIZE;
542
543                // char* skeletonName
544                size += link.skeletonName.length() + 1;
545                // float scale
546                size += sizeof(float);
547
548                return size;
549
550        }
551        //---------------------------------------------------------------------
552        void SkeletonSerializer::readSkeletonAnimationLink(DataStreamPtr& stream,
553                Skeleton* pSkel)
554        {
555                // char* skeletonName
556                String skelName = readString(stream);
557                // float scale
558                float scale;
559                readFloats(stream, &scale, 1);
560
561                pSkel->addLinkedSkeletonAnimationSource(skelName, scale);
562
563        }
564
565
566
567}
568
569
Note: See TracBrowser for help on using the repository browser.