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

OgreSkeleton.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 #include "OgreSkeleton.h"
00027 #include "OgreBone.h"
00028 #include "OgreAnimation.h"
00029 #include "OgreAnimationState.h"
00030 #include "OgreException.h"
00031 #include "OgreLogManager.h"
00032 #include "OgreSkeletonManager.h"
00033 #include "OgreSkeletonSerializer.h"
00034 // Just for logging
00035 #include "OgreAnimationTrack.h"
00036 #include "OgreKeyFrame.h"
00037 
00038 
00039 namespace Ogre {
00040 
00041     //---------------------------------------------------------------------
00042     Skeleton::Skeleton(const String& name) 
00043     {
00044         mName = name;
00045 
00046         // Start next handle
00047         mNextAutoHandle = 0;
00048 
00049         // set animation blending to weighted, not cumulative
00050         mBlendState = ANIMBLEND_AVERAGE;
00051 
00052     }
00053     //---------------------------------------------------------------------
00054     Skeleton::~Skeleton()
00055     {
00056         unload();
00057     }
00058     //---------------------------------------------------------------------
00059     void Skeleton::load(void)
00060     {
00061         // Load from specified 'name'
00062         if (mIsLoaded)
00063         {
00064             unload();
00065         }
00066 
00067         SkeletonSerializer serializer;
00068         char msg[100];
00069         sprintf(msg, "Skeleton: Loading %s .", mName.c_str());
00070         LogManager::getSingleton().logMessage(msg);
00071 
00072         DataChunk chunk;
00073         SkeletonManager::getSingleton()._findResourceData(mName, chunk);
00074 
00075         // Determine file type
00076         std::vector<String> extVec = mName.split(".");
00077 
00078         String& ext = extVec[extVec.size() - 1];
00079         ext.toLowerCase();
00080 
00081         if (ext == "skeleton")
00082         {
00083             serializer.importSkeleton(chunk, this);
00084         }
00085         else
00086         {
00087             // Unsupported format
00088             chunk.clear();
00089             Except(999, "Unsupported skeleton file format.",
00090                 "Skeleton::load");
00091         }
00092 
00093         chunk.clear();
00094 
00095         // Mark resource as loaded
00096         mIsLoaded = true;
00097 
00098     }
00099     //---------------------------------------------------------------------
00100     void Skeleton::unload(void)
00101     {
00102         // destroy bones
00103         BoneList::iterator i;
00104         for (i = mBoneList.begin(); i != mBoneList.end(); ++i)
00105         {
00106             delete *i;
00107         }
00108         mBoneList.clear();
00109 
00110 
00111         // Destroy animations
00112         AnimationList::iterator ai;
00113         for (ai = mAnimationsList.begin(); ai != mAnimationsList.end(); ++ai)
00114         {
00115             delete ai->second;
00116         }
00117         mAnimationsList.clear();
00118 
00119         // Mark resource as not loaded
00120         mIsLoaded = false;
00121     }
00122     //---------------------------------------------------------------------
00123     Bone* Skeleton::createBone(void)
00124     {
00125         // use autohandle
00126         return createBone(mNextAutoHandle++);
00127     }
00128     //---------------------------------------------------------------------
00129     Bone* Skeleton::createBone(const String& name)
00130     {
00131         return createBone(name, mNextAutoHandle++);
00132     }
00133     //---------------------------------------------------------------------
00134     Bone* Skeleton::createBone(unsigned short handle)
00135     {
00136         if (mBoneList.size() == OGRE_MAX_NUM_BONES)
00137         {
00138             Except(Exception::ERR_INVALIDPARAMS, "Exceeded the maximum number of bones per skeleton.",
00139                 "Skeleton::createBone");
00140         }
00141         Bone* ret = new Bone(handle, this);
00142         if (mBoneList.size() <= handle)
00143         {
00144             mBoneList.resize(handle+1);
00145         }
00146         mBoneList[handle] = ret;
00147         mBoneListByName[ret->getName()] = ret;
00148         return ret;
00149 
00150     }
00151     //---------------------------------------------------------------------
00152     Bone* Skeleton::createBone(const String& name, unsigned short handle)
00153     {
00154         if (mBoneList.size() == OGRE_MAX_NUM_BONES)
00155         {
00156             Except(Exception::ERR_INVALIDPARAMS, "Exceeded the maximum number of bones per skeleton.",
00157                 "Skeleton::createBone");
00158         }
00159         Bone* ret = new Bone(name, handle, this);
00160         if (mBoneList.size() <= handle)
00161         {
00162             mBoneList.resize(handle+1);
00163         }
00164         mBoneList[handle] = ret;
00165         mBoneListByName[name] = ret;
00166         return ret;
00167     }
00168 
00169 
00170 
00171     //---------------------------------------------------------------------
00172     Bone* Skeleton::getRootBone(void) const
00173     {
00174         if (mRootBones.empty())
00175         {
00176             deriveRootBone();
00177         }
00178 
00179         return mRootBones[0];
00180     }
00181     //---------------------------------------------------------------------
00182     void Skeleton::setAnimationState(const AnimationStateSet& animSet)
00183     {
00184         /* 
00185         Algorithm:
00186           1. Check if animation state is any different from last, if not do nothing
00187           2. Reset all bone positions
00188           3. Iterate per AnimationState, if enabled get Animation and call Animation::apply
00189         */
00190 
00191         if (mLastAnimationState.size() == animSet.size())
00192         {
00193             // Same size, may be able to skip update
00194             bool different = false;
00195             AnimationStateSet::iterator i;
00196             AnimationStateSet::const_iterator j;
00197             i = mLastAnimationState.begin();
00198             j = animSet.begin();
00199             for (; i != mLastAnimationState.end(); ++i, ++j)
00200             {
00201                 if (i->second != j->second)
00202                 {
00203                     different = true;
00204                     break;
00205                 }
00206             }
00207             // Check any differences?
00208             if (!different)
00209             {
00210                 // No, no need to update
00211                 return;
00212             }
00213         }
00214 
00215         // Ok, we've established the animation state is different
00216 
00217         // Reset bones
00218         reset();
00219 
00220         // Per animation state
00221         AnimationStateSet::const_iterator istate;
00222         for (istate = animSet.begin(); istate != animSet.end(); ++istate)
00223         {
00224             // Apply if enabled
00225             const AnimationState& animState = istate->second;
00226             if (animState.getEnabled())
00227             {
00228                 Animation* anim = getAnimation(animState.getAnimationName());
00229                 anim->apply(this, animState.getTimePosition(), animState.getWeight(), mBlendState == ANIMBLEND_CUMULATIVE);
00230             }
00231         }
00232 
00233         mLastAnimationState = animSet;
00234 
00235 
00236     }
00237     //---------------------------------------------------------------------
00238     void Skeleton::setBindingPose(void)
00239     {
00240         // Update the derived transforms
00241         _updateTransforms();
00242 
00243 
00244         BoneList::iterator i;
00245         for (i = mBoneList.begin(); i != mBoneList.end(); ++i)
00246         {            
00247             (*i)->setBindingPose();
00248         }
00249     }
00250     //---------------------------------------------------------------------
00251     void Skeleton::reset(bool resetManualBones)
00252     {
00253         BoneList::iterator i;
00254         for (i = mBoneList.begin(); i != mBoneList.end(); ++i)
00255         {
00256             if(!(*i)->isManuallyControlled() || resetManualBones)
00257                 (*i)->reset();
00258         }
00259     }
00260     //---------------------------------------------------------------------
00261     Animation* Skeleton::createAnimation(const String& name, Real length)
00262     {
00263         Animation* ret = new Animation(name, length);
00264 
00265         // Add to list
00266         mAnimationsList[name] = ret;
00267 
00268         // Also add to state
00269         mLastAnimationState[name] = AnimationState(name, 0, length);
00270 
00271         return ret;
00272 
00273     }
00274     //---------------------------------------------------------------------
00275     Animation* Skeleton::getAnimation(const String& name) const
00276     {
00277         AnimationList::const_iterator i = mAnimationsList.find(name);
00278 
00279         if (i == mAnimationsList.end())
00280         {
00281             Except(Exception::ERR_ITEM_NOT_FOUND, "No animation entry found named " + name, 
00282             "Skeleton::getAnimation");
00283         }
00284 
00285         return i->second;
00286     }
00287     //---------------------------------------------------------------------
00288     void Skeleton::removeAnimation(const String& name)
00289     {
00290         AnimationList::iterator i = mAnimationsList.find(name);
00291 
00292         if (i == mAnimationsList.end())
00293         {
00294             Except(Exception::ERR_ITEM_NOT_FOUND, "No animation entry found named " + name, 
00295             "Skeleton::getAnimation");
00296         }
00297 
00298         delete i->second;
00299 
00300         mAnimationsList.erase(i);
00301 
00302     }
00303     //---------------------------------------------------------------------
00304     const AnimationStateSet& Skeleton::getAnimationState(void) const
00305     {
00306         return mLastAnimationState;
00307     }
00308     //-----------------------------------------------------------------------
00309     void Skeleton::_initAnimationState(AnimationStateSet* animSet)
00310     {
00311         animSet->clear();
00312            
00313         AnimationList::iterator i;
00314         for (i = mAnimationsList.begin(); i != mAnimationsList.end(); ++i)
00315         {
00316             Animation* anim = i->second;
00317             // Create animation at time index 0, default params mean this has weight 1 and is disabled
00318             String animName = anim->getName();
00319             (*animSet)[animName] = AnimationState(animName, 0.0, anim->getLength());
00320         }
00321     }
00322     //-----------------------------------------------------------------------
00323     unsigned short Skeleton::getNumBones(void) const
00324     {
00325         return (unsigned short)mBoneList.size();
00326     }
00327     //-----------------------------------------------------------------------
00328     void Skeleton::_getBoneMatrices(Matrix4* pMatrices)
00329     {
00330         // Update derived transforms
00331         _updateTransforms();
00332 
00333         /* 
00334             Calculating the bone matrices
00335             -----------------------------
00336             Now that we have the derived orientations & positions in the Bone nodes, we have
00337             to compute the Matrix4 to apply to the vertices of a mesh.
00338             Because any modification of a vertex has to be relative to the bone, we must first
00339             reverse transform by the Bone's original derived position/orientation, then transform
00340             by the new derived position / orientation.
00341         */
00342 
00343         BoneList::iterator i, boneend;
00344         boneend = mBoneList.end();
00345         
00346        
00347         for(i = mBoneList.begin();i != boneend; ++i)
00348         {
00349             Bone* pBone = *i;
00350             *pMatrices = pBone->_getFullTransform() *  pBone->_getBindingPoseInverseTransform();
00351             pMatrices++;
00352         }
00353 
00354     }
00355     //---------------------------------------------------------------------
00356     unsigned short Skeleton::getNumAnimations(void) const
00357     {
00358         return (unsigned short)mAnimationsList.size();
00359     }
00360     //---------------------------------------------------------------------
00361     Animation* Skeleton::getAnimation(unsigned short index) const
00362     {
00363         // If you hit this assert, then the index is out of bounds.
00364         assert( index < mAnimationsList.size() );
00365 
00366         AnimationList::const_iterator i = mAnimationsList.begin();
00367 
00368         while (index--)
00369             ++i;
00370 
00371         return i->second;
00372     }
00373     //---------------------------------------------------------------------
00374     Bone* Skeleton::getBone(unsigned short handle) const
00375     {
00376         assert(handle < mBoneList.size() && "Index out of bounds");
00377         return mBoneList[handle];
00378     }
00379     //---------------------------------------------------------------------
00380     Bone* Skeleton::getBone(const String& name) const
00381     {
00382         BoneListByName::const_iterator i = mBoneListByName.find(name);
00383 
00384         if (i == mBoneListByName.end())
00385         {
00386             Except(Exception::ERR_ITEM_NOT_FOUND, "Bone named '" + name + "' not found.", 
00387                 "Skeleton::getBone");
00388         }
00389 
00390         return i->second;
00391 
00392     }
00393     //---------------------------------------------------------------------
00394     void Skeleton::deriveRootBone(void) const
00395     {
00396         // Start at the first bone and work up
00397         if (mBoneList.empty())
00398         {
00399             Except(Exception::ERR_INVALIDPARAMS, "Cannot derive root bone as this "
00400                 "skeleton has no bones!", "Skeleton::deriveRootBone");
00401         }
00402 
00403         mRootBones.empty();
00404 
00405         Bone* currentBone;
00406         BoneList::const_iterator i;
00407         BoneList::const_iterator iend = mBoneList.end();
00408         for (i = mBoneList.begin(); i != iend; ++i)
00409         {
00410             currentBone = *i;
00411             if (currentBone->getParent() == 0)
00412             {
00413                 // This is a root
00414                 mRootBones.push_back(currentBone);
00415             }
00416         }
00417     }
00418     //---------------------------------------------------------------------
00419     void Skeleton::_dumpContents(const String& filename)
00420     {
00421         std::ofstream of;
00422 
00423         Quaternion q;
00424         Real angle;
00425         Vector3 axis;
00426         of.open(filename);
00427 
00428         of << "-= Debug output of skeleton " << mName << " =-" << std::endl << std::endl;
00429         of << "== Bones ==" << std::endl;
00430         of << "Number of bones: " << (unsigned int)mBoneList.size() << std::endl;
00431         
00432         BoneList::iterator bi;
00433         for (bi = mBoneList.begin(); bi != mBoneList.end(); ++bi)
00434         {
00435             Bone* bone = *bi;
00436 
00437             of << "-- Bone " << bone->getHandle() << " --" << std::endl;
00438             of << "Position: " << bone->getPosition();
00439             q = bone->getOrientation();
00440             of << "Rotation: " << q;
00441             q.ToAngleAxis(angle, axis);
00442             of << " = " << angle << " radians around axis " << axis << std::endl << std::endl;
00443         }
00444 
00445         of << "== Animations ==" << std::endl;
00446         of << "Number of animations: " << (unsigned int)mAnimationsList.size() << std::endl;
00447 
00448         AnimationList::iterator ai;
00449         for (ai = mAnimationsList.begin(); ai != mAnimationsList.end(); ++ai)
00450         {
00451             Animation* anim = ai->second;
00452 
00453             of << "-- Animation '" << anim->getName() << "' (length " << anim->getLength() << ") --" << std::endl;
00454             of << "Number of tracks: " << anim->getNumTracks() << std::endl;
00455 
00456             int ti;
00457             for (ti = 0; ti < anim->getNumTracks(); ++ti)
00458             {
00459                 AnimationTrack* track = anim->getTrack(ti);
00460                 of << "  -- AnimationTrack " << ti << " --" << std::endl;
00461                 of << "  Affects bone: " << ((Bone*)track->getAssociatedNode())->getHandle() << std::endl;
00462                 of << "  Number of keyframes: " << track->getNumKeyFrames() << std::endl;
00463 
00464                 int ki;
00465                 
00466                 for (ki = 0; ki < track->getNumKeyFrames(); ++ki)
00467                 {
00468                     KeyFrame* key = track->getKeyFrame(ki);
00469                     of << "    -- KeyFrame " << ki << " --" << std::endl;
00470                     of << "    Time index: " << key->getTime(); 
00471                     of << "    Translation: " << key->getTranslate() << std::endl;
00472                     q = key->getRotation();
00473                     of << "    Rotation: " << q;
00474                     q.ToAngleAxis(angle, axis);
00475                     of << " = " << angle << " radians around axis " << axis << std::endl;
00476                 }
00477 
00478             }
00479 
00480 
00481 
00482         }
00483 
00484     }
00485     //---------------------------------------------------------------------
00486     SkeletonAnimationBlendMode Skeleton::getBlendMode() 
00487     {
00488         return mBlendState;
00489     }
00490     //---------------------------------------------------------------------
00491     void Skeleton::setBlendMode(SkeletonAnimationBlendMode state) 
00492     {
00493         mBlendState = state;
00494     }
00495     //---------------------------------------------------------------------
00496     Skeleton::BoneIterator Skeleton::getRootBoneIterator(void)
00497     {
00498         if (mRootBones.empty())
00499         {
00500             deriveRootBone();
00501         }
00502         return BoneIterator(mRootBones.begin(), mRootBones.end());
00503     }
00504     //---------------------------------------------------------------------
00505     Skeleton::BoneIterator Skeleton::getBoneIterator(void)
00506     {
00507         return BoneIterator(mBoneList.begin(), mBoneList.end());
00508     }
00509     //---------------------------------------------------------------------
00510     void Skeleton::_updateTransforms(void)
00511     {
00512         BoneList::iterator i, iend;
00513         iend = mRootBones.end();
00514         for (i = mRootBones.begin(); i != iend; ++i)
00515         {
00516             (*i)->_update(true, false);
00517         }
00518     }
00519 }
00520 

Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:48 2004