Set alpha value of character animations according to Invisibility / Chameleon effects.

actorid
scrawl 11 years ago
parent 9fcb4fad5c
commit 37a7ee8fcd

@ -727,6 +727,8 @@ void CharacterController::update(float duration)
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
Ogre::Vector3 movement(0.0f);
updateVisibility();
if(!cls.isActor())
{
if(mAnimQueue.size() > 1)
@ -1130,4 +1132,25 @@ void CharacterController::updateContinuousVfx()
}
}
void CharacterController::updateVisibility()
{
if (!mPtr.getClass().isActor())
return;
float alpha = 1.f;
if (mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Invisibility).mMagnitude)
{
if (mPtr.getRefData().getHandle() == "player")
alpha = 0.4f;
else
alpha = 0.f;
}
float chameleon = mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Chameleon).mMagnitude;
if (chameleon)
{
alpha *= std::max(0.2f, (100.f - chameleon)/100.f);
}
mAnimation->setAlpha(alpha);
}
}

@ -173,6 +173,8 @@ class CharacterController
bool updateNpcState(bool onground, bool inwater, bool isrunning, bool sneak);
void updateVisibility();
public:
CharacterController(const MWWorld::Ptr &ptr, MWRender::Animation *anim);
virtual ~CharacterController();

@ -215,6 +215,8 @@ public:
void addEffect (const std::string& model, int effectId, bool loop = false, const std::string& bonename = "", std::string texture = "");
void removeEffect (int effectId);
void getLoopingEffects (std::vector<int>& out);
virtual void setAlpha(float alpha) {}
private:
void updateEffects(float duration);

@ -5,6 +5,8 @@
#include <OgreParticleSystem.h>
#include <OgreSubEntity.h>
#include <extern/shiny/Main/Factory.hpp>
#include "../mwworld/esmstore.hpp"
#include "../mwworld/inventorystore.hpp"
#include "../mwworld/class.hpp"
@ -116,7 +118,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v
mViewMode(viewMode),
mShowWeapons(false),
mShowShield(true),
mFirstPersonOffset(0.f, 0.f, 0.f)
mFirstPersonOffset(0.f, 0.f, 0.f),
mAlpha(1.f)
{
mNpc = mPtr.get<ESM::NPC>()->mBase;
@ -219,6 +222,7 @@ void NpcAnimation::updateNpcBase()
void NpcAnimation::updateParts()
{
mAlpha = 1.f;
const MWWorld::Class &cls = MWWorld::Class::get(mPtr);
MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr);
@ -647,6 +651,7 @@ void NpcAnimation::showWeapons(bool showWeapon)
{
removeIndividualPart(ESM::PRT_Weapon);
}
mAlpha = 1.f;
}
void NpcAnimation::showShield(bool show)
@ -705,4 +710,56 @@ void NpcAnimation::permanentEffectAdded(const ESM::MagicEffect *magicEffect, boo
}
}
void NpcAnimation::setAlpha(float alpha)
{
if (alpha == mAlpha)
return;
mAlpha = alpha;
for (int i=0; i<ESM::PRT_Count; ++i)
{
if (mObjectParts[i].isNull())
continue;
for (unsigned int j=0; j<mObjectParts[i]->mEntities.size(); ++j)
{
Ogre::Entity* ent = mObjectParts[i]->mEntities[j];
if (ent != mObjectParts[i]->mSkelBase)
applyAlpha(alpha, ent, mObjectParts[i]);
}
}
}
void NpcAnimation::applyAlpha(float alpha, Ogre::Entity *ent, NifOgre::ObjectScenePtr scene)
{
ent->getSubEntity(0)->setRenderQueueGroup(alpha != 1.f || ent->getSubEntity(0)->getMaterial()->isTransparent()
? RQG_Alpha : RQG_Main);
Ogre::MaterialPtr mat = scene->mMaterialControllerMgr.getWritableMaterial(ent);
if (mAlpha == 1.f)
{
// Don't bother remembering what the original values were. Just remove the techniques and let the factory restore them.
mat->removeAllTechniques();
sh::Factory::getInstance()._ensureMaterial(mat->getName(), "Default");
return;
}
Ogre::Material::TechniqueIterator techs = mat->getTechniqueIterator();
while(techs.hasMoreElements())
{
Ogre::Technique *tech = techs.getNext();
Ogre::Technique::PassIterator passes = tech->getPassIterator();
while(passes.hasMoreElements())
{
Ogre::Pass *pass = passes.getNext();
pass->setSceneBlending(Ogre::SBT_TRANSPARENT_ALPHA);
Ogre::ColourValue diffuse = pass->getDiffuse();
diffuse.a = alpha;
pass->setDiffuse(diffuse);
pass->setVertexColourTracking(pass->getVertexColourTracking() &~Ogre::TVC_DIFFUSE);
}
}
}
}

@ -64,6 +64,8 @@ private:
Ogre::SharedPtr<SayAnimationValue> mSayAnimationValue;
float mAlpha;
void updateNpcBase();
NifOgre::ObjectScenePtr insertBoundedPart(const std::string &model, int group, const std::string &bonename,
@ -78,6 +80,8 @@ private:
void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts,
bool enchantedGlow=false, Ogre::Vector3* glowColor=NULL);
void applyAlpha(float alpha, Ogre::Entity* ent, NifOgre::ObjectScenePtr scene);
public:
/**
* @param ptr
@ -109,6 +113,9 @@ public:
/// Rebuilds the NPC, updating their root model, animation sources, and equipment.
void rebuild();
/// Make the NPC only partially visible
virtual void setAlpha(float alpha);
};
}

@ -60,14 +60,14 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
MWWorld::Fallback* fallback)
: mRendering(_rend)
, mFallback(fallback)
, mObjects(mRendering)
, mActors(mRendering, this)
, mPlayerAnimation(NULL)
, mAmbientMode(0)
, mSunEnabled(0)
, mPhysicsEngine(engine)
, mTerrain(NULL)
{
mActors = new MWRender::Actors(mRendering, this);
mObjects = new MWRender::Objects(mRendering);
// select best shader mode
bool openGL = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL") != std::string::npos);
bool glES = (Ogre::Root::getSingleton ().getRenderSystem ()->getName().find("OpenGL ES") != std::string::npos);
@ -162,8 +162,8 @@ RenderingManager::RenderingManager(OEngine::Render::OgreRenderer& _rend, const b
mRootNode = mRendering.getScene()->getRootSceneNode();
mRootNode->createChildSceneNode("player");
mObjects.setRootNode(mRootNode);
mActors.setRootNode(mRootNode);
mObjects->setRootNode(mRootNode);
mActors->setRootNode(mRootNode);
mCamera = new MWRender::Camera(mRendering.getCamera());
@ -201,6 +201,8 @@ RenderingManager::~RenderingManager ()
delete mCompositors;
delete mWater;
delete mVideoPlayer;
delete mActors;
delete mObjects;
delete mFactory;
}
@ -210,10 +212,10 @@ MWRender::SkyManager* RenderingManager::getSkyManager()
}
MWRender::Objects& RenderingManager::getObjects(){
return mObjects;
return *mObjects;
}
MWRender::Actors& RenderingManager::getActors(){
return mActors;
return *mActors;
}
OEngine::Render::Fader* RenderingManager::getFader()
@ -223,8 +225,8 @@ OEngine::Render::Fader* RenderingManager::getFader()
void RenderingManager::removeCell (MWWorld::Ptr::CellStore *store)
{
mObjects.removeCell(store);
mActors.removeCell(store);
mObjects->removeCell(store);
mActors->removeCell(store);
mDebugging->cellRemoved(store);
}
@ -240,7 +242,7 @@ void RenderingManager::toggleWater()
void RenderingManager::cellAdded (MWWorld::Ptr::CellStore *store)
{
mObjects.buildStaticGeometry (*store);
mObjects->buildStaticGeometry (*store);
sh::Factory::getInstance().unloadUnreferencedMaterials();
mDebugging->cellAdded(store);
waterAdded(store);
@ -254,8 +256,8 @@ void RenderingManager::addObject (const MWWorld::Ptr& ptr){
void RenderingManager::removeObject (const MWWorld::Ptr& ptr)
{
if (!mObjects.deleteObject (ptr))
mActors.deleteObject (ptr);
if (!mObjects->deleteObject (ptr))
mActors->deleteObject (ptr);
}
void RenderingManager::moveObject (const MWWorld::Ptr& ptr, const Ogre::Vector3& position)
@ -295,9 +297,9 @@ RenderingManager::updateObjectCell(const MWWorld::Ptr &old, const MWWorld::Ptr &
parent->removeChild(child);
if (MWWorld::Class::get(old).isActor()) {
mActors.updateObjectCell(old, cur);
mActors->updateObjectCell(old, cur);
} else {
mObjects.updateObjectCell(old, cur);
mObjects->updateObjectCell(old, cur);
}
}
@ -315,7 +317,7 @@ void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
if(ptr.getRefData().getHandle() == "player")
anim = mPlayerAnimation;
else if(MWWorld::Class::get(ptr).isActor())
anim = dynamic_cast<NpcAnimation*>(mActors.getAnimation(ptr));
anim = dynamic_cast<NpcAnimation*>(mActors->getAnimation(ptr));
if(anim)
{
anim->rebuild();
@ -380,8 +382,8 @@ void RenderingManager::update (float duration, bool paused)
if(paused)
return;
mActors.update (duration);
mObjects.update (duration);
mActors->update (duration);
mObjects->update (duration);
mSkyManager->update(duration);
@ -657,7 +659,7 @@ void RenderingManager::requestMap(MWWorld::Ptr::CellStore* cell)
{
assert(mTerrain);
Ogre::AxisAlignedBox dims = mObjects.getDimensions(cell);
Ogre::AxisAlignedBox dims = mObjects->getDimensions(cell);
Ogre::Vector2 center(cell->mCell->getGridX() + 0.5, cell->mCell->getGridY() + 0.5);
dims.merge(mTerrain->getWorldBoundingBox(center));
@ -667,7 +669,7 @@ void RenderingManager::requestMap(MWWorld::Ptr::CellStore* cell)
mLocalMap->requestMap(cell, dims.getMinimum().z, dims.getMaximum().z);
}
else
mLocalMap->requestMap(cell, mObjects.getDimensions(cell));
mLocalMap->requestMap(cell, mObjects->getDimensions(cell));
}
void RenderingManager::preCellChange(MWWorld::Ptr::CellStore* cell)
@ -677,13 +679,13 @@ void RenderingManager::preCellChange(MWWorld::Ptr::CellStore* cell)
void RenderingManager::disableLights(bool sun)
{
mObjects.disableLights();
mObjects->disableLights();
sunDisable(sun);
}
void RenderingManager::enableLights(bool sun)
{
mObjects.enableLights();
mObjects->enableLights();
sunEnable(sun);
}
@ -859,7 +861,7 @@ void RenderingManager::processChangedSettings(const Settings::CategorySettingVec
if (rebuild)
{
mObjects.rebuildStaticGeometry();
mObjects->rebuildStaticGeometry();
if (mTerrain)
mTerrain->applyMaterials(Settings::Manager::getBool("enabled", "Shadows"),
Settings::Manager::getBool("split", "Shadows"));
@ -976,13 +978,13 @@ void RenderingManager::setupExternalRendering (MWRender::ExternalRendering& rend
Animation* RenderingManager::getAnimation(const MWWorld::Ptr &ptr)
{
Animation *anim = mActors.getAnimation(ptr);
Animation *anim = mActors->getAnimation(ptr);
if(!anim && ptr.getRefData().getHandle() == "player")
anim = mPlayerAnimation;
if (!anim)
anim = mObjects.getAnimation(ptr);
anim = mObjects->getAnimation(ptr);
return anim;
}

@ -242,8 +242,8 @@ private:
OEngine::Render::OgreRenderer &mRendering;
MWRender::Objects mObjects;
MWRender::Actors mActors;
MWRender::Objects* mObjects;
MWRender::Actors* mActors;
MWRender::NpcAnimation *mPlayerAnimation;

@ -63,11 +63,12 @@ Ogre::MaterialPtr MaterialControllerManager::getWritableMaterial(Ogre::MovableOb
else if (Ogre::ParticleSystem* partSys = dynamic_cast<Ogre::ParticleSystem*>(movable))
mat = Ogre::MaterialManager::getSingleton().getByName(partSys->getMaterialName());
// Make sure techniques are created
sh::Factory::getInstance()._ensureMaterial(mat->getName(), "Default");
static int count=0;
mat = mat->clone(mat->getName() + Ogre::StringConverter::toString(count++));
Ogre::String newName = mat->getName() + Ogre::StringConverter::toString(count++);
sh::Factory::getInstance().createMaterialInstance(newName, mat->getName());
// Make sure techniques are created
sh::Factory::getInstance()._ensureMaterial(newName, "Default");
mat = Ogre::MaterialManager::getSingleton().getByName(newName);
mClonedMaterials[movable] = mat;
@ -84,7 +85,7 @@ MaterialControllerManager::~MaterialControllerManager()
{
for (std::map<Ogre::MovableObject*, Ogre::MaterialPtr>::iterator it = mClonedMaterials.begin(); it != mClonedMaterials.end(); ++it)
{
Ogre::MaterialManager::getSingleton().remove(it->second->getName());
sh::Factory::getInstance().destroyMaterialInstance(it->second->getName());
}
}

@ -98,9 +98,7 @@
#if VERTEXCOLOR_MODE != 2
shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour)
#endif
#if VERTEXCOLOR_MODE != 2
shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour)
#endif
#if VERTEXCOLOR_MODE != 1
shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour)
#endif
@ -234,9 +232,7 @@
lightResult.xyz += lightAmbient.xyz * materialAmbient.xyz + materialEmissive.xyz;
#endif
#if VERTEXCOLOR_MODE != 2
lightResult.a *= materialDiffuse.a;
#endif
#endif
}
@ -339,9 +335,7 @@
#if VERTEXCOLOR_MODE != 2
shUniform(float4, materialAmbient) @shAutoConstant(materialAmbient, surface_ambient_colour)
#endif
#if VERTEXCOLOR_MODE != 2
shUniform(float4, materialDiffuse) @shAutoConstant(materialDiffuse, surface_diffuse_colour)
#endif
#if VERTEXCOLOR_MODE != 1
shUniform(float4, materialEmissive) @shAutoConstant(materialEmissive, surface_emissive_colour)
#endif
@ -434,9 +428,7 @@
lightResult.xyz += lightAmbient.xyz * materialAmbient.xyz + materialEmissive.xyz;
#endif
#if VERTEXCOLOR_MODE != 2
lightResult.a *= materialDiffuse.a;
#endif
#endif
// shadows only for the first (directional) light

Loading…
Cancel
Save