1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-19 20:53:50 +00:00

Use an array of objectlists, instead of one base objectlist and an array of 'animation sources'

This commit is contained in:
Chris Robinson 2013-04-14 17:58:21 -07:00
parent f9dee25fd1
commit 69084139aa
5 changed files with 75 additions and 133 deletions

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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();
}