From 629a6be477b10bd06cbff7bd2e291148c6c4e309 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 7 Feb 2019 19:11:12 +0400 Subject: [PATCH] Handle initial actor's transparency (bug #4860) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/actors.cpp | 52 +++++++++++++++++++++++------- apps/openmw/mwmechanics/actors.hpp | 3 ++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c3eba7e5..cd7be8561 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ Bug #4827: NiUVController is handled incorrectly Bug #4828: Potion looping effects VFX are not shown for NPCs Bug #4837: CTD when a mesh with NiLODNode root node with particles is loaded + Bug #4860: Actors outside of processing range visible for one frame after spawning Feature #2229: Improve pathfinding AI Feature #3442: Default values for fallbacks from ini file Feature #3610: Option to invert X axis diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 83c40f963..e01064f87 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1169,8 +1169,46 @@ namespace MWMechanics if (!anim) return; mActors.insert(std::make_pair(ptr, new Actor(ptr, anim))); + + CharacterController* ctrl = mActors[ptr]->getCharacterController(); if (updateImmediately) - mActors[ptr]->getCharacterController()->update(0); + ctrl->update(0); + + // We should initially hide actors outside of processing range. + // Note: since we update player after other actors, distance will be incorrect during teleportation. + // Do not update visibility if player was teleported, so actors will be visible during teleportation frame. + if (MWBase::Environment::get().getWorld()->getPlayer().wasTeleported()) + return; + + updateVisibility(ptr, ctrl); + } + + void Actors::updateVisibility (const MWWorld::Ptr& ptr, CharacterController* ctrl) + { + MWWorld::Ptr player = MWMechanics::getPlayer(); + if (ptr == player) + return; + + const float dist = (player.getRefData().getPosition().asVec3() - ptr.getRefData().getPosition().asVec3()).length(); + if (dist > mActorsProcessingRange) + { + ptr.getRefData().getBaseNode()->setNodeMask(0); + return; + } + else + ptr.getRefData().getBaseNode()->setNodeMask(MWRender::Mask_Actor); + + // Fade away actors on large distance (>90% of actor's processing distance) + float visibilityRatio = 1.0; + float fadeStartDistance = mActorsProcessingRange*0.9f; + float fadeEndDistance = mActorsProcessingRange; + float fadeRatio = (dist - fadeStartDistance)/(fadeEndDistance - fadeStartDistance); + if (fadeRatio > 0) + visibilityRatio -= std::max(0.f, fadeRatio); + + visibilityRatio = std::min(1.f, visibilityRatio); + + ctrl->setVisibility(visibilityRatio); } void Actors::removeActor (const MWWorld::Ptr& ptr) @@ -1479,17 +1517,7 @@ namespace MWMechanics world->setActorCollisionMode(iter->first, true, !iter->first.getClass().getCreatureStats(iter->first).isDeathAnimationFinished()); ctrl->update(duration); - // Fade away actors on large distance (>90% of actor's processing distance) - float visibilityRatio = 1.0; - float fadeStartDistance = mActorsProcessingRange*0.9f; - float fadeEndDistance = mActorsProcessingRange; - float fadeRatio = (dist - fadeStartDistance)/(fadeEndDistance - fadeStartDistance); - if (fadeRatio > 0) - visibilityRatio -= std::max(0.f, fadeRatio); - - visibilityRatio = std::min(1.f, visibilityRatio); - - ctrl->setVisibility(visibilityRatio); + updateVisibility(iter->first, ctrl); } if (playerCharacter) diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 61879c432..35da3c2d5 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -19,6 +19,7 @@ namespace MWWorld namespace MWMechanics { class Actor; + class CharacterController; class CreatureStats; class Actors @@ -169,6 +170,8 @@ namespace MWMechanics bool isAttackingOrSpell(const MWWorld::Ptr& ptr) const; private: + void updateVisibility (const MWWorld::Ptr& ptr, CharacterController* ctrl); + PtrActorMap mActors; float mTimerDisposeSummonsCorpses; float mActorsProcessingRange;