Skip to content
Permalink
Browse files

Don't update off-screen animations

Make flying creatures animate in-place when out of processing range
  • Loading branch information...
scrawl
scrawl committed Jan 11, 2018
1 parent 1522bda commit bba9a8dd91f65be732d7e68c47281ea71486e54d
@@ -1213,14 +1213,12 @@ namespace MWMechanics
// AI and magic effects update
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
float distSqr = (player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2();
// AI processing is only done within distance of 7168 units to the player. Note the "AI distance" slider doesn't affect this
// (it only does some throttling for targets beyond the "AI distance", so doesn't give any guarantees as to whether AI will be enabled or not)
// This distance could be made configurable later, but the setting must be marked with a big warning:
// using higher values will make a quest in Bloodmoon harder or impossible to complete (bug #1876)
bool inProcessingRange = (player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2()
<= sqrAiProcessingDistance;

iter->second->getCharacterController()->setActive(inProcessingRange);
bool inProcessingRange = distSqr <= sqrAiProcessingDistance;

if (iter->first == player)
iter->second->getCharacterController()->setAttackingOrSpell(MWBase::Environment::get().getWorld()->getPlayer().getAttackingOrSpell());
@@ -1326,9 +1324,24 @@ namespace MWMechanics
CharacterController* playerCharacter = NULL;
for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter)
{
if (iter->first != player &&
(player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2()
> sqrAiProcessingDistance)
const float animationDistance = aiProcessingDistance + 400; // Slightly larger than AI distance so there is time to switch back to the idle animation.
const float distSqr = (player.getRefData().getPosition().asVec3() - iter->first.getRefData().getPosition().asVec3()).length2();
bool isPlayer = iter->first == player;
bool inAnimationRange = isPlayer || (animationDistance == 0 || distSqr <= animationDistance*animationDistance);
int activeFlag = 1; // Can be changed back to '2' to keep updating bounding boxes off screen (more accurate, but slower)
if (isPlayer)
activeFlag = 2;
int active = inAnimationRange ? activeFlag : 0;
bool canFly = iter->first.getClass().canFly(iter->first);
if (canFly)
{
// Keep animating flying creatures so they don't just hover in-air
inAnimationRange = true;
active = std::max(1, active);
}
iter->second->getCharacterController()->setActive(active);

if (!inAnimationRange)
continue;

if (iter->first.getClass().getCreatureStats(iter->first).isParalyzed())
@@ -2392,7 +2392,7 @@ float CharacterController::getAttackStrength() const
return mAttackStrength;
}

void CharacterController::setActive(bool active)
void CharacterController::setActive(int active)
{
mAnimation->setActive(active);
}
@@ -292,7 +292,7 @@ class CharacterController : public MWRender::Animation::TextKeyListener
float getAttackStrength() const;

/// @see Animation::setActive
void setActive(bool active);
void setActive(int active);

/// Make this character turn its head towards \a target. To turn off head tracking, pass an empty Ptr.
void setHeadTrackTarget(const MWWorld::ConstPtr& target);
@@ -486,10 +486,10 @@ namespace MWRender
return mPtr;
}

void Animation::setActive(bool active)
void Animation::setActive(int active)
{
if (mSkeleton)
mSkeleton->setActive(active);
mSkeleton->setActive(static_cast<SceneUtil::Skeleton::ActiveType>(active));
}

void Animation::updatePtr(const MWWorld::Ptr &ptr)
@@ -347,7 +347,8 @@ class Animation : public osg::Referenced

/// Set active flag on the object skeleton, if one exists.
/// @see SceneUtil::Skeleton::setActive
void setActive(bool active);
/// 0 = Inactive, 1 = Active in place, 2 = Active
void setActive(int active);

osg::Group* getOrCreateObjectRoot();

@@ -36,8 +36,9 @@ class InitBoneCacheVisitor : public osg::NodeVisitor
Skeleton::Skeleton()
: mBoneCacheInit(false)
, mNeedToUpdateBoneMatrices(true)
, mActive(true)
, mActive(Active)
, mLastFrameNumber(0)
, mLastCullFrameNumber(0)
{

}
@@ -48,6 +49,7 @@ Skeleton::Skeleton(const Skeleton &copy, const osg::CopyOp &copyop)
, mNeedToUpdateBoneMatrices(true)
, mActive(copy.mActive)
, mLastFrameNumber(0)
, mLastCullFrameNumber(0)
{

}
@@ -123,14 +125,14 @@ void Skeleton::updateBoneMatrices(unsigned int traversalNumber)
}
}

void Skeleton::setActive(bool active)
void Skeleton::setActive(ActiveType active)
{
mActive = active;
}

bool Skeleton::getActive() const
{
return mActive;
return mActive != Inactive;
}

void Skeleton::markDirty()
@@ -142,8 +144,16 @@ void Skeleton::markDirty()

void Skeleton::traverse(osg::NodeVisitor& nv)
{
if (!getActive() && nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR && mLastFrameNumber != 0)
return;
if (nv.getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
{
if (mActive == Inactive && mLastFrameNumber != 0)
return;
if (mActive == SemiActive && mLastFrameNumber != 0 && mLastCullFrameNumber+3 <= nv.getTraversalNumber())
return;
}
else if (nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
mLastCullFrameNumber = nv.getTraversalNumber();

osg::Group::traverse(nv);
}

@@ -47,9 +47,16 @@ namespace SceneUtil
/// Request an update of bone matrices. May be a no-op if already updated in this frame.
void updateBoneMatrices(unsigned int traversalNumber);

enum ActiveType
{
Inactive=0,
SemiActive, /// Like Active, but don't bother with Update (including new bounding box) if we're off-screen
Active
};

/// Set the skinning active flag. Inactive skeletons will not have their child rigs updated.
/// You should set this flag to false if you know that bones are not currently moving.
void setActive(bool active);
void setActive(ActiveType active);

bool getActive() const;

@@ -71,9 +78,10 @@ namespace SceneUtil

bool mNeedToUpdateBoneMatrices;

bool mActive;
ActiveType mActive;

unsigned int mLastFrameNumber;
unsigned int mLastCullFrameNumber;
};

}

0 comments on commit bba9a8d

Please sign in to comment.
You can’t perform that action at this time.