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