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