Main Page Namespace List Class Hierarchy Alphabetical List Compound List File List Namespace Members Compound Members File Members Related Pages

# OgreSkeletonSerializer.cpp

Go to the documentation of this file.

    00001 /*
    00002 -----------------------------------------------------------------------------
    00003 This source file is part of OGRE
    00004     (Object-oriented Graphics Rendering Engine)
    00005 For the latest info, see http://www.ogre3d.org/
    00006
    00007 Copyright © 2000-2002 The OGRE Team
    00008 Also see acknowledgements in Readme.html
    00009
    00010 This program is free software; you can redistribute it and/or modify it under
    00011 the terms of the GNU Lesser General Public License as published by the Free Software
    00012 Foundation; either version 2 of the License, or (at your option) any later
    00013 version.
    00014
    00015 This program is distributed in the hope that it will be useful, but WITHOUT
    00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
    00018
    00019 You should have received a copy of the GNU Lesser General Public License along with
    00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
    00022 http://www.gnu.org/copyleft/lesser.txt.
    00023 -----------------------------------------------------------------------------
    00024 */
    00025 #include "OgreStableHeaders.h"
    00026
    00027 #include "OgreSkeletonFileFormat.h"
    00028 #include "OgreSkeletonSerializer.h"
    00029 #include "OgreSkeleton.h"
    00030 #include "OgreAnimation.h"
    00031 #include "OgreAnimationTrack.h"
    00032 #include "OgreKeyFrame.h"
    00033 #include "OgreBone.h"
    00034 #include "OgreString.h"
    00035 #include "OgreDataChunk.h"
    00036 #include "OgreLogManager.h"
    00037
    00038
    00039
    00040
    00041 namespace Ogre {
    00043     const unsigned long CHUNK_OVERHEAD_SIZE = sizeof(unsigned short) + sizeof(unsigned long);
    00044     //---------------------------------------------------------------------
    00045     SkeletonSerializer::SkeletonSerializer()
    00046     {
    00047         // Version number
    00048         // NB changed to include bone names in 1.1
    00049         mVersion = "[Serializer_v1.10]";
    00050     }
    00051     //---------------------------------------------------------------------
    00052     SkeletonSerializer::~SkeletonSerializer()
    00053     {
    00054     }
    00055     //---------------------------------------------------------------------
    00056     void SkeletonSerializer::exportSkeleton(const Skeleton* pSkeleton, const String& filename)
    00057     {
    00058         String msg;
    00059         mpfFile = fopen(filename.c_str(), "wb");
    00060
    00061         writeFileHeader();
    00062
    00063         // Write main skeleton data
    00064         LogManager::getSingleton().logMessage("Exporting bones..");
    00065         writeSkeleton(pSkeleton);
    00066         LogManager::getSingleton().logMessage("Bones exported.");
    00067
    00068         // Write all animations
    00069         unsigned short numAnims = pSkeleton->getNumAnimations();
    00070         msg = "Exporting animations, count=";
    00071         StringUtil::StrStreamType num;
    00072         num << numAnims;
    00073         msg += num.str();
    00074         LogManager::getSingleton().logMessage(msg);
    00075         for (unsigned short i = 0; i < numAnims; ++i)
    00076         {
    00077             Animation* pAnim = pSkeleton->getAnimation(i);
    00078             msg = "Exporting animation: " + pAnim->getName();
    00079             LogManager::getSingleton().logMessage(msg);
    00080             writeAnimation(pAnim);
    00081             LogManager::getSingleton().logMessage("Animation exported.");
    00082
    00083         }
    00084         fclose(mpfFile);
    00085
    00086     }
    00087     //---------------------------------------------------------------------
    00088     void SkeletonSerializer::importSkeleton(DataChunk& chunk, Skeleton* pDest)
    00089     {
    00090         mpSkeleton = pDest;
    00091
    00092         // Check header
    00093         readFileHeader(chunk);
    00094
    00095         unsigned short chunkID;
    00096         while(!chunk.isEOF())
    00097         {
    00098             chunkID = readChunk(chunk);
    00099             switch (chunkID)
    00100             {
    00101             case SKELETON_BONE:
    00102                 readBone(chunk);
    00103                 break;
    00104             case SKELETON_BONE_PARENT:
    00105                 readBoneParent(chunk);
    00106                 break;
    00107             case SKELETON_ANIMATION:
    00108                 readAnimation(chunk);
    00109             }
    00110         }
    00111
    00112         // Assume bones are stored in the binding pose
    00113         mpSkeleton->setBindingPose();
    00114
    00115
    00116     }
    00117     //---------------------------------------------------------------------
    00118     void SkeletonSerializer::writeSkeleton(const Skeleton* pSkel)
    00119     {
    00120         // Write each bone
    00121         unsigned short numBones = pSkel->getNumBones();
    00122         unsigned short i;
    00123         for (i = 0; i < numBones; ++i)
    00124         {
    00125             Bone* pBone = pSkel->getBone(i);
    00126             writeBone(pBone);
    00127         }
    00128         // Write parents
    00129         for (i = 0; i < numBones; ++i)
    00130         {
    00131             Bone* pBone = pSkel->getBone(i);
    00132             unsigned short handle = pBone->getHandle();
    00133             Bone* pParent = (Bone*)pBone->getParent();
    00134             if (pParent != NULL)
    00135             {
    00136                 writeBoneParent(handle, pParent->getHandle());
    00137             }
    00138         }
    00139     }
    00140     //---------------------------------------------------------------------
    00141     void SkeletonSerializer::writeBone(const Bone* pBone)
    00142     {
    00143         writeChunkHeader(SKELETON_BONE, calcBoneSize(pBone));
    00144
    00145         unsigned short handle = pBone->getHandle();
    00146         // char* name
    00147         writeString(pBone->getName());
    00148         // unsigned short handle            : handle of the bone, should be contiguous & start at 0
    00149         writeShorts(&handle, 1);
    00150         // Vector3 position                 : position of this bone relative to parent
    00151         writeObject(pBone->getPosition());
    00152         // Quaternion orientation           : orientation of this bone relative to parent
    00153         writeObject(pBone->getOrientation());
    00154     }
    00155     //---------------------------------------------------------------------
    00156     void SkeletonSerializer::writeBoneParent(unsigned short boneId, unsigned short parentId)
    00157     {
    00158         writeChunkHeader(SKELETON_BONE_PARENT, calcBoneParentSize());
    00159
    00160         // unsigned short handle             : child bone
    00161         writeShorts(&boneId, 1);
    00162         // unsigned short parentHandle   : parent bone
    00163         writeShorts(&parentId, 1);
    00164
    00165     }
    00166     //---------------------------------------------------------------------
    00167     void SkeletonSerializer::writeAnimation(const Animation* anim)
    00168     {
    00169         writeChunkHeader(SKELETON_ANIMATION, calcAnimationSize(anim));
    00170
    00171         // char* name                       : Name of the animation
    00172         writeString(anim->getName());
    00173         // Real length                      : Length of the animation in seconds
    00174         Real len = anim->getLength();
    00175         writeReals(&len, 1);
    00176
    00177         // Write all tracks
    00178         Animation::TrackIterator trackIt = anim->getTrackIterator();
    00179         while(trackIt.hasMoreElements())
    00180         {
    00181             writeAnimationTrack(trackIt.getNext());
    00182         }
    00183
    00184     }
    00185     //---------------------------------------------------------------------
    00186     void SkeletonSerializer::writeAnimationTrack(const AnimationTrack* track)
    00187     {
    00188         writeChunkHeader(SKELETON_ANIMATION_TRACK, calcAnimationTrackSize(track));
    00189
    00190         // unsigned short boneIndex     : Index of bone to apply to
    00191         Bone* bone = (Bone*)track->getAssociatedNode();
    00192         unsigned short boneid = bone->getHandle();
    00193         writeShorts(&boneid, 1);
    00194
    00195         // Write all keyframes
    00196         for (unsigned short i = 0; i < track->getNumKeyFrames(); ++i)
    00197         {
    00198             writeKeyFrame(track->getKeyFrame(i));
    00199         }
    00200
    00201     }
    00202     //---------------------------------------------------------------------
    00203     void SkeletonSerializer::writeKeyFrame(const KeyFrame* key)
    00204     {
    00205
    00206         writeChunkHeader(SKELETON_ANIMATION_TRACK_KEYFRAME, calcKeyFrameSize(key));
    00207
    00208         // Real time                    : The time position (seconds)
    00209         Real time = key->getTime();
    00210         writeReals(&time, 1);
    00211         // Quaternion rotate            : Rotation to apply at this keyframe
    00212         writeObject(key->getRotation());
    00213         // Vector3 translate            : Translation to apply at this keyframe
    00214         writeObject(key->getTranslate());
    00215         // Vector3 scale                : Scale to apply at this keyframe
    00216         writeObject(key->getScale());
    00217     }
    00218     //---------------------------------------------------------------------
    00219     unsigned long SkeletonSerializer::calcBoneSize(const Bone* pBone)
    00220     {
    00221         unsigned long size = CHUNK_OVERHEAD_SIZE;
    00222
    00223         // handle
    00224         size += sizeof(unsigned short);
    00225
    00226         // position
    00227         size += sizeof(Real) * 3;
    00228
    00229         // orientation
    00230         size += sizeof(Real) * 4;
    00231
    00232         return size;
    00233
    00234     }
    00235     //---------------------------------------------------------------------
    00236     unsigned long SkeletonSerializer::calcBoneParentSize(void)
    00237     {
    00238         unsigned long size = CHUNK_OVERHEAD_SIZE;
    00239
    00240         // handle
    00241         size += sizeof(unsigned short);
    00242
    00243         // parent handle
    00244         size += sizeof(unsigned short);
    00245
    00246         return size;
    00247
    00248     }
    00249     //---------------------------------------------------------------------
    00250     unsigned long SkeletonSerializer::calcAnimationSize(const Animation* pAnim)
    00251     {
    00252         unsigned long size = CHUNK_OVERHEAD_SIZE;
    00253
    00254         // Name, including terminator
    00255         size += (unsigned long)pAnim->getName().length() + 1;
    00256         // length
    00257         size += sizeof(Real);
    00258
    00259         // Nested animation tracks
    00260         for (unsigned short i = 0; i < pAnim->getNumTracks(); ++i)
    00261         {
    00262             size += calcAnimationTrackSize(pAnim->getTrack(i));
    00263         }
    00264
    00265
    00266         return size;
    00267
    00268     }
    00269     //---------------------------------------------------------------------
    00270     unsigned long SkeletonSerializer::calcAnimationTrackSize(const AnimationTrack* pTrack)
    00271     {
    00272         unsigned long size = CHUNK_OVERHEAD_SIZE;
    00273
    00274         // unsigned short boneIndex     : Index of bone to apply to
    00275         size += sizeof(unsigned short);
    00276
    00277         // Nested keyframes
    00278         for (unsigned short i = 0; i < pTrack->getNumKeyFrames(); ++i)
    00279         {
    00280             size += calcKeyFrameSize(pTrack->getKeyFrame(i));
    00281         }
    00282
    00283
    00284         return size;
    00285     }
    00286     //---------------------------------------------------------------------
    00287     unsigned long SkeletonSerializer::calcKeyFrameSize(const KeyFrame* pKey)
    00288     {
    00289         unsigned long size = CHUNK_OVERHEAD_SIZE;
    00290
    00291         // Real time                    : The time position (seconds)
    00292         size += sizeof(Real);
    00293         // Quaternion rotate            : Rotation to apply at this keyframe
    00294         size += sizeof(Real) * 4;
    00295         // Vector3 translate            : Translation to apply at this keyframe
    00296         size += sizeof(Real) * 3;
    00297         // Vector3 scale                : Scale to apply at this keyframe
    00298         size += sizeof(Real) * 3;
    00299
    00300         return size;
    00301     }
    00302     //---------------------------------------------------------------------
    00303     void SkeletonSerializer::readBone(DataChunk &chunk)
    00304     {
    00305         // char* name
    00306         String name = readString(chunk);
    00307         // unsigned short handle            : handle of the bone, should be contiguous & start at 0
    00308         unsigned short handle;
    00309         readShorts(chunk, &handle, 1);
    00310
    00311         // Create new bone
    00312         Bone* pBone = mpSkeleton->createBone(name, handle);
    00313
    00314         // Vector3 position                 : position of this bone relative to parent
    00315         Vector3 pos;
    00316         readObject(chunk, &pos);
    00317         pBone->setPosition(pos);
    00318         // Quaternion orientation           : orientation of this bone relative to parent
    00319         Quaternion q;
    00320         readObject(chunk, &q);
    00321         pBone->setOrientation(q);
    00322     }
    00323     //---------------------------------------------------------------------
    00324     void SkeletonSerializer::readBoneParent(DataChunk &chunk)
    00325     {
    00326         // All bones have been created by this point
    00327         Bone *child, *parent;
    00328         unsigned short childHandle, parentHandle;
    00329
    00330         // unsigned short handle             : child bone
    00331         readShorts(chunk, &childHandle, 1);
    00332         // unsigned short parentHandle   : parent bone
    00333         readShorts(chunk, &parentHandle, 1);
    00334
    00335         // Find bones
    00336         parent = mpSkeleton->getBone(parentHandle);
    00337         child = mpSkeleton->getBone(childHandle);
    00338
    00339         // attach
    00340         parent->addChild(child);
    00341
    00342     }
    00343     //---------------------------------------------------------------------
    00344     void SkeletonSerializer::readAnimation(DataChunk &chunk)
    00345     {
    00346         // char* name                       : Name of the animation
    00347         String name;
    00348         name = readString(chunk);
    00349         // Real length                      : Length of the animation in seconds
    00350         Real len;
    00351         readReals(chunk, &len, 1);
    00352
    00353         Animation *pAnim = mpSkeleton->createAnimation(name, len);
    00354
    00355         // Read all tracks
    00356         if (!chunk.isEOF())
    00357         {
    00358             unsigned short chunkID = readChunk(chunk);
    00359             while(chunkID == SKELETON_ANIMATION_TRACK && !chunk.isEOF())
    00360             {
    00361                 readAnimationTrack(chunk, pAnim);
    00362
    00363                 if (!chunk.isEOF())
    00364                 {
    00365                     // Get next chunk
    00366                     chunkID = readChunk(chunk);
    00367                 }
    00368             }
    00369             if (!chunk.isEOF())
    00370             {
    00371                 // Backpedal back to start of this chunk if we've found a non-track
    00372                 chunk.skip(-(long)CHUNK_OVERHEAD_SIZE);
    00373             }
    00374
    00375         }
    00376
    00377
    00378
    00379     }
    00380     //---------------------------------------------------------------------
    00381     void SkeletonSerializer::readAnimationTrack(DataChunk &chunk, Animation* anim)
    00382     {
    00383         // unsigned short boneIndex     : Index of bone to apply to
    00384         unsigned short boneHandle;
    00385         readShorts(chunk, &boneHandle, 1);
    00386
    00387         // Find bone
    00388         Bone *targetBone = mpSkeleton->getBone(boneHandle);
    00389
    00390         // Create track
    00391         AnimationTrack* pTrack = anim->createTrack(boneHandle, targetBone);
    00392
    00393         // Keep looking for nested keyframes
    00394         if (!chunk.isEOF())
    00395         {
    00396             unsigned short chunkID = readChunk(chunk);
    00397             while(chunkID == SKELETON_ANIMATION_TRACK_KEYFRAME && !chunk.isEOF())
    00398             {
    00399                 readKeyFrame(chunk, pTrack);
    00400
    00401                 if (!chunk.isEOF())
    00402                 {
    00403                     // Get next chunk
    00404                     chunkID = readChunk(chunk);
    00405                 }
    00406             }
    00407             if (!chunk.isEOF())
    00408             {
    00409                 // Backpedal back to start of this chunk if we've found a non-keyframe
    00410                 chunk.skip(-(long)CHUNK_OVERHEAD_SIZE);
    00411             }
    00412
    00413         }
    00414
    00415
    00416     }
    00417     //---------------------------------------------------------------------
    00418     void SkeletonSerializer::readKeyFrame(DataChunk &chunk, AnimationTrack* track)
    00419     {
    00420         // Real time                    : The time position (seconds)
    00421         Real time;
    00422         readReals(chunk, &time, 1);
    00423
    00424         KeyFrame *kf = track->createKeyFrame(time);
    00425
    00426         // Quaternion rotate            : Rotation to apply at this keyframe
    00427         Quaternion rot;
    00428         readObject(chunk, &rot);
    00429         kf->setRotation(rot);
    00430         // Vector3 translate            : Translation to apply at this keyframe
    00431         Vector3 trans;
    00432         readObject(chunk, &trans);
    00433         kf->setTranslate(trans);
    00434         // Do we have scale?
    00435         if (mCurrentChunkLen == calcKeyFrameSize(kf))
    00436         {
    00437             Vector3 scale;
    00438             readObject(chunk, &scale);
    00439             kf->setScale(scale);
    00440         }
    00441     }
    00442     //---------------------------------------------------------------------
    00443
    00444
    00445
    00446 }
    00447
    00448

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:47 2004