mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 20:26:43 +00:00 
			
		
		
		
	Use an array of objectlists, instead of one base objectlist and an array of 'animation sources'
This commit is contained in:
		
							parent
							
								
									f9dee25fd1
								
							
						
					
					
						commit
						69084139aa
					
				
					 5 changed files with 75 additions and 133 deletions
				
			
		|  | @ -27,9 +27,9 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr) | |||
|         std::string mesh = "meshes\\" + ref->mBase->mModel; | ||||
| 
 | ||||
|         createObjectList(mPtr.getRefData().getBaseNode(), mesh); | ||||
|         for(size_t i = 0;i < mObjectList.mEntities.size();i++) | ||||
|         for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++) | ||||
|         { | ||||
|             Ogre::Entity *ent = mObjectList.mEntities[i]; | ||||
|             Ogre::Entity *ent = mObjectLists[0].mEntities[i]; | ||||
|             ent->setVisibilityFlags(RV_Misc); | ||||
| 
 | ||||
|             for(unsigned int j=0; j < ent->getNumSubEntities(); ++j) | ||||
|  | @ -38,14 +38,12 @@ ActivatorAnimation::ActivatorAnimation(const MWWorld::Ptr &ptr) | |||
|                 subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); | ||||
|             } | ||||
|         } | ||||
|         for(size_t i = 0;i < mObjectList.mParticles.size();i++) | ||||
|         for(size_t i = 0;i < mObjectLists[0].mParticles.size();i++) | ||||
|         { | ||||
|             Ogre::ParticleSystem *part = mObjectList.mParticles[i]; | ||||
|             Ogre::ParticleSystem *part = mObjectLists[0].mParticles[i]; | ||||
|             part->setVisibilityFlags(RV_Misc); | ||||
| 
 | ||||
|             part->setRenderQueueGroup(RQG_Alpha); | ||||
|         } | ||||
|         setAnimationSource(mesh); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -55,68 +55,45 @@ Animation::~Animation() | |||
|     if(mInsert) | ||||
|     { | ||||
|         Ogre::SceneManager *sceneMgr = mInsert->getCreator(); | ||||
|         destroyObjectList(sceneMgr, mObjectList); | ||||
| 
 | ||||
|         for(size_t i = 0;i < mAnimationSources.size();i++) | ||||
|             destroyObjectList(sceneMgr, mAnimationSources[i]); | ||||
|         mAnimationSources.clear(); | ||||
|         for(size_t i = 0;i < mObjectLists.size();i++) | ||||
|             destroyObjectList(sceneMgr, mObjectLists[i]); | ||||
|         mObjectLists.clear(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void Animation::setAnimationSources(const std::vector<std::string> &names) | ||||
| void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model) | ||||
| { | ||||
|     if(!mSkelBase) | ||||
|         return; | ||||
|     Ogre::SceneManager *sceneMgr = mInsert->getCreator(); | ||||
|     assert(!mInsert); | ||||
|     mInsert = node->createChildSceneNode(); | ||||
|     assert(mInsert); | ||||
| 
 | ||||
|     mCurrentControllers = &mObjectList.mControllers; | ||||
|     mCurrentAnim = NULL; | ||||
|     mCurrentKeys = NULL; | ||||
|     mAnimVelocity = 0.0f; | ||||
|     mAccumRoot = NULL; | ||||
|     mNonAccumRoot = NULL; | ||||
|     mTextKeys.clear(); | ||||
|     for(size_t i = 0;i < mAnimationSources.size();i++) | ||||
|         destroyObjectList(sceneMgr, mAnimationSources[i]); | ||||
|     mAnimationSources.clear(); | ||||
|     mObjectLists.resize(1); | ||||
| 
 | ||||
|     Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this)); | ||||
|     Ogre::SkeletonInstance *skelinst = mSkelBase->getSkeleton(); | ||||
|     std::vector<std::string>::const_iterator nameiter; | ||||
|     for(nameiter = names.begin();nameiter != names.end();nameiter++) | ||||
|     mObjectLists[0] = NifOgre::Loader::createObjects(mInsert, model); | ||||
|     if(mObjectLists[0].mSkelBase) | ||||
|     { | ||||
|         mAnimationSources.push_back(NifOgre::Loader::createObjectBase(sceneMgr, *nameiter)); | ||||
|         if(!mAnimationSources.back().mSkelBase) | ||||
|         mSkelBase = mObjectLists[0].mSkelBase; | ||||
| 
 | ||||
|         Ogre::AnimationStateSet *aset = mObjectLists[0].mSkelBase->getAllAnimationStates(); | ||||
|         Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator(); | ||||
|         while(asiter.hasMoreElements()) | ||||
|         { | ||||
|             std::cerr<< "Failed to get skeleton source "<<*nameiter <<std::endl; | ||||
|             destroyObjectList(sceneMgr, mAnimationSources.back()); | ||||
|             mAnimationSources.pop_back(); | ||||
|             continue; | ||||
|         } | ||||
|         NifOgre::ObjectList &objects = mAnimationSources.back(); | ||||
| 
 | ||||
|         for(size_t i = 0;i < objects.mControllers.size();i++) | ||||
|         { | ||||
|             NifOgre::NodeTargetValue<Ogre::Real> *dstval = dynamic_cast<NifOgre::NodeTargetValue<Ogre::Real>*>(objects.mControllers[i].getDestination().getPointer()); | ||||
|             if(!dstval) continue; | ||||
| 
 | ||||
|             const Ogre::String &trgtname = dstval->getNode()->getName(); | ||||
|             if(!skelinst->hasBone(trgtname)) continue; | ||||
| 
 | ||||
|             Ogre::Bone *bone = skelinst->getBone(trgtname); | ||||
|             dstval->setNode(bone); | ||||
|             Ogre::AnimationState *state = asiter.getNext(); | ||||
|             state->setEnabled(false); | ||||
|             state->setLoop(false); | ||||
|         } | ||||
| 
 | ||||
|         for(size_t i = 0;i < objects.mControllers.size();i++) | ||||
|         { | ||||
|             if(objects.mControllers[i].getSource().isNull()) | ||||
|                 objects.mControllers[i].setSource(ctrlval); | ||||
|         } | ||||
|         // Set the bones as manually controlled since we're applying the
 | ||||
|         // transformations manually (needed if we want to apply an animation
 | ||||
|         // from one skeleton onto another).
 | ||||
|         Ogre::SkeletonInstance *skelinst = mObjectLists[0].mSkelBase->getSkeleton(); | ||||
|         Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator(); | ||||
|         while(boneiter.hasMoreElements()) | ||||
|             boneiter.getNext()->setManuallyControlled(true); | ||||
| 
 | ||||
|         Ogre::Entity *ent = objects.mSkelBase; | ||||
|         Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(ent->getSkeleton()->getName()); | ||||
|         Ogre::Skeleton::BoneIterator boneiter = skel->getBoneIterator(); | ||||
|         Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(skelinst->getName()); | ||||
|         boneiter = skel->getBoneIterator(); | ||||
|         while(boneiter.hasMoreElements()) | ||||
|         { | ||||
|             Ogre::Bone *bone = boneiter.getNext(); | ||||
|  | @ -143,43 +120,14 @@ void Animation::setAnimationSources(const std::vector<std::string> &names) | |||
|             break; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void Animation::createObjectList(Ogre::SceneNode *node, const std::string &model) | ||||
| { | ||||
|     mInsert = node->createChildSceneNode(); | ||||
|     assert(mInsert); | ||||
| 
 | ||||
|     mObjectList = NifOgre::Loader::createObjects(mInsert, model); | ||||
|     if(mObjectList.mSkelBase) | ||||
|     { | ||||
|         mSkelBase = mObjectList.mSkelBase; | ||||
| 
 | ||||
|         Ogre::AnimationStateSet *aset = mSkelBase->getAllAnimationStates(); | ||||
|         Ogre::AnimationStateIterator asiter = aset->getAnimationStateIterator(); | ||||
|         while(asiter.hasMoreElements()) | ||||
|         { | ||||
|             Ogre::AnimationState *state = asiter.getNext(); | ||||
|             state->setEnabled(false); | ||||
|             state->setLoop(false); | ||||
|         } | ||||
| 
 | ||||
|         // Set the bones as manually controlled since we're applying the
 | ||||
|         // transformations manually (needed if we want to apply an animation
 | ||||
|         // from one skeleton onto another).
 | ||||
|         Ogre::SkeletonInstance *skelinst = mSkelBase->getSkeleton(); | ||||
|         Ogre::Skeleton::BoneIterator boneiter = skelinst->getBoneIterator(); | ||||
|         while(boneiter.hasMoreElements()) | ||||
|             boneiter.getNext()->setManuallyControlled(true); | ||||
|     } | ||||
| 
 | ||||
|     Ogre::SharedPtr<Ogre::ControllerValue<Ogre::Real> > ctrlval(OGRE_NEW AnimationValue(this)); | ||||
|     for(size_t i = 0;i < mObjectList.mControllers.size();i++) | ||||
|     for(size_t i = 0;i < mObjectLists[0].mControllers.size();i++) | ||||
|     { | ||||
|         if(mObjectList.mControllers[i].getSource().isNull()) | ||||
|             mObjectList.mControllers[i].setSource(ctrlval); | ||||
|         if(mObjectLists[0].mControllers[i].getSource().isNull()) | ||||
|             mObjectLists[0].mControllers[i].setSource(ctrlval); | ||||
|     } | ||||
|     mCurrentControllers = &mObjectList.mControllers; | ||||
|     mCurrentControllers = &mObjectLists[0].mControllers; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | @ -197,9 +145,9 @@ Ogre::Node *Animation::getNode(const std::string &name) | |||
| 
 | ||||
| bool Animation::hasAnimation(const std::string &anim) | ||||
| { | ||||
|     for(std::vector<NifOgre::ObjectList>::const_iterator iter(mAnimationSources.begin());iter != mAnimationSources.end();iter++) | ||||
|     for(std::vector<NifOgre::ObjectList>::const_iterator iter(mObjectLists.begin());iter != mObjectLists.end();iter++) | ||||
|     { | ||||
|         if(iter->mSkelBase->hasAnimationState(anim)) | ||||
|         if(iter->mSkelBase && iter->mSkelBase->hasAnimationState(anim)) | ||||
|             return true; | ||||
|     } | ||||
|     return false; | ||||
|  | @ -449,7 +397,7 @@ void Animation::play(const std::string &groupname, const std::string &start, con | |||
|     try { | ||||
|         bool found = false; | ||||
|         /* Look in reverse; last-inserted source has priority. */ | ||||
|         for(std::vector<NifOgre::ObjectList>::reverse_iterator iter(mAnimationSources.rbegin());iter != mAnimationSources.rend();iter++) | ||||
|         for(std::vector<NifOgre::ObjectList>::reverse_iterator iter(mObjectLists.rbegin());iter != mObjectLists.rend();iter++) | ||||
|         { | ||||
|             if(iter->mSkelBase->hasAnimationState(groupname)) | ||||
|             { | ||||
|  | @ -513,9 +461,19 @@ Ogre::Vector3 Animation::runAnimation(float timepassed) | |||
| 
 | ||||
|     if(mSkelBase) | ||||
|     { | ||||
|         // HACK: Dirty the animation state set so that Ogre will apply the
 | ||||
|         // transformations to entities this skeleton instance is shared with.
 | ||||
|         mSkelBase->getAllAnimationStates()->_notifyDirty(); | ||||
|         const Ogre::SkeletonInstance *skelsrc = mSkelBase->getSkeleton(); | ||||
|         for(size_t i = 0;i < mObjectLists.size();i++) | ||||
|         { | ||||
|             Ogre::Entity *ent = mObjectLists[i].mSkelBase; | ||||
|             if(!ent) continue; | ||||
| 
 | ||||
|             Ogre::SkeletonInstance *skeldst = ent->getSkeleton(); | ||||
|             if(skelsrc != skeldst) | ||||
|                 updateSkeletonInstance(skelsrc, skeldst); | ||||
|             // HACK: Dirty the animation state set so that Ogre will apply the
 | ||||
|             // transformations to entities this skeleton instance is shared with.
 | ||||
|             ent->getAllAnimationStates()->_notifyDirty(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return movement; | ||||
|  |  | |||
|  | @ -44,15 +44,13 @@ protected: | |||
| 
 | ||||
|     Ogre::SceneNode *mInsert; | ||||
|     Ogre::Entity *mSkelBase; | ||||
|     NifOgre::ObjectList mObjectList; | ||||
|     std::vector<NifOgre::ObjectList> mObjectLists; | ||||
|     std::map<std::string,NifOgre::TextKeyMap> mTextKeys; | ||||
|     Ogre::Node *mAccumRoot; | ||||
|     Ogre::Bone *mNonAccumRoot; | ||||
|     Ogre::Vector3 mAccumulate; | ||||
|     Ogre::Vector3 mLastPosition; | ||||
| 
 | ||||
|     std::vector<NifOgre::ObjectList> mAnimationSources; | ||||
| 
 | ||||
|     std::vector<Ogre::Controller<Ogre::Real> > *mCurrentControllers; | ||||
|     NifOgre::TextKeyMap *mCurrentKeys; | ||||
|     NifOgre::TextKeyMap::const_iterator mNextKey; | ||||
|  | @ -83,16 +81,6 @@ protected: | |||
| 
 | ||||
|     bool handleEvent(float time, const std::string &evt); | ||||
| 
 | ||||
|     /* Specifies a list of skeleton names to use as animation sources. */ | ||||
|     void setAnimationSources(const std::vector<std::string> &names); | ||||
| 
 | ||||
|     /* Specifies a single skeleton name to use as an animation source. */ | ||||
|     void setAnimationSource(const std::string &name) | ||||
|     { | ||||
|         std::vector<std::string> names(1, name); | ||||
|         setAnimationSources(names); | ||||
|     } | ||||
| 
 | ||||
|     void createObjectList(Ogre::SceneNode *node, const std::string &model); | ||||
|     static void destroyObjectList(Ogre::SceneManager *sceneMgr, NifOgre::ObjectList &objects); | ||||
| 
 | ||||
|  |  | |||
|  | @ -26,10 +26,15 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr) | |||
|     { | ||||
|         std::string model = "meshes\\"+ref->mBase->mModel; | ||||
| 
 | ||||
|         createObjectList(mPtr.getRefData().getBaseNode(), model); | ||||
|         for(size_t i = 0;i < mObjectList.mEntities.size();i++) | ||||
|         std::vector<std::string> names; | ||||
|         if((ref->mBase->mFlags&ESM::Creature::Biped)) | ||||
|             names.push_back("meshes\\base_anim.nif"); | ||||
|         names.push_back(model); | ||||
| 
 | ||||
|         createObjectList(mPtr.getRefData().getBaseNode(), model/*names*/); | ||||
|         for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++) | ||||
|         { | ||||
|             Ogre::Entity *ent = mObjectList.mEntities[i]; | ||||
|             Ogre::Entity *ent = mObjectLists[0].mEntities[i]; | ||||
|             ent->setVisibilityFlags(RV_Actors); | ||||
| 
 | ||||
|             for(unsigned int j=0; j < ent->getNumSubEntities(); ++j) | ||||
|  | @ -38,19 +43,13 @@ CreatureAnimation::CreatureAnimation(const MWWorld::Ptr &ptr) | |||
|                 subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); | ||||
|             } | ||||
|         } | ||||
|         for(size_t i = 0;i < mObjectList.mParticles.size();i++) | ||||
|         for(size_t i = 0;i < mObjectLists[0].mParticles.size();i++) | ||||
|         { | ||||
|             Ogre::ParticleSystem *part = mObjectList.mParticles[i]; | ||||
|             Ogre::ParticleSystem *part = mObjectLists[0].mParticles[i]; | ||||
|             part->setVisibilityFlags(RV_Actors); | ||||
| 
 | ||||
|             part->setRenderQueueGroup(RQG_Alpha); | ||||
|         } | ||||
| 
 | ||||
|         std::vector<std::string> names; | ||||
|         if((ref->mBase->mFlags&ESM::Creature::Biped)) | ||||
|             names.push_back("meshes\\base_anim.nif"); | ||||
|         names.push_back(model); | ||||
|         setAnimationSources(names); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -96,10 +96,18 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor | |||
|     bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; | ||||
|     std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif"); | ||||
| 
 | ||||
|     createObjectList(node, smodel); | ||||
|     for(size_t i = 0;i < mObjectList.mEntities.size();i++) | ||||
|     std::vector<std::string> skelnames(1, smodel); | ||||
|     if(!mNpc->isMale() && !isBeast) | ||||
|         skelnames.push_back("meshes\\base_anim_female.nif"); | ||||
|     else if(mBodyPrefix.find("argonian") != std::string::npos) | ||||
|         skelnames.push_back("meshes\\argonian_swimkna.nif"); | ||||
|     if(mNpc->mModel.length() > 0) | ||||
|         skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel)); | ||||
| 
 | ||||
|     createObjectList(node, smodel/*skelnames*/); | ||||
|     for(size_t i = 0;i < mObjectLists[0].mEntities.size();i++) | ||||
|     { | ||||
|         Ogre::Entity *base = mObjectList.mEntities[i]; | ||||
|         Ogre::Entity *base = mObjectLists[0].mEntities[i]; | ||||
| 
 | ||||
|         base->getUserObjectBindings().setUserAny(Ogre::Any(-1)); | ||||
|         if (mVisibilityFlags != 0) | ||||
|  | @ -111,9 +119,9 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor | |||
|             subEnt->setRenderQueueGroup(subEnt->getMaterial()->isTransparent() ? RQG_Alpha : RQG_Main); | ||||
|         } | ||||
|     } | ||||
|     for(size_t i = 0;i < mObjectList.mParticles.size();i++) | ||||
|     for(size_t i = 0;i < mObjectLists[0].mParticles.size();i++) | ||||
|     { | ||||
|         Ogre::ParticleSystem *part = mObjectList.mParticles[i]; | ||||
|         Ogre::ParticleSystem *part = mObjectLists[0].mParticles[i]; | ||||
| 
 | ||||
|         part->getUserObjectBindings().setUserAny(Ogre::Any(-1)); | ||||
|         if(mVisibilityFlags != 0) | ||||
|  | @ -121,15 +129,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor | |||
|         part->setRenderQueueGroup(RQG_Alpha); | ||||
|     } | ||||
| 
 | ||||
|     std::vector<std::string> skelnames(1, smodel); | ||||
|     if(!mNpc->isMale() && !isBeast) | ||||
|         skelnames.push_back("meshes\\base_anim_female.nif"); | ||||
|     else if(mBodyPrefix.find("argonian") != std::string::npos) | ||||
|         skelnames.push_back("meshes\\argonian_swimkna.nif"); | ||||
|     if(mNpc->mModel.length() > 0) | ||||
|         skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel)); | ||||
|     setAnimationSources(skelnames); | ||||
| 
 | ||||
|     forceUpdate(); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue