mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-07 05:15:34 +00:00
Port EffectManager
This commit is contained in:
parent
fcc7aa02ab
commit
68f93294da
21 changed files with 261 additions and 172 deletions
|
@ -21,11 +21,11 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
|
||||||
|
|
||||||
add_openmw_dir (mwrender
|
add_openmw_dir (mwrender
|
||||||
actors objects renderingmanager animation sky npcanimation vismask
|
actors objects renderingmanager animation sky npcanimation vismask
|
||||||
creatureanimation
|
creatureanimation effectmanager util
|
||||||
# debugging camera activatoranimation
|
# debugging camera activatoranimation
|
||||||
# renderinginterface localmap occlusionquery water shadows
|
# renderinginterface localmap occlusionquery water shadows
|
||||||
# characterpreview globalmap ripplesimulation refraction
|
# characterpreview globalmap ripplesimulation refraction
|
||||||
# terrainstorage renderconst effectmanager weaponanimation
|
# terrainstorage renderconst weaponanimation
|
||||||
)
|
)
|
||||||
|
|
||||||
#add_openmw_dir (mwinput
|
#add_openmw_dir (mwinput
|
||||||
|
|
|
@ -17,6 +17,11 @@ namespace Ogre
|
||||||
class Image;
|
class Image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace osg
|
||||||
|
{
|
||||||
|
class Vec3f;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Loading
|
namespace Loading
|
||||||
{
|
{
|
||||||
class Listener;
|
class Listener;
|
||||||
|
@ -546,9 +551,9 @@ namespace MWBase
|
||||||
virtual void spawnRandomCreature(const std::string& creatureList) = 0;
|
virtual void spawnRandomCreature(const std::string& creatureList) = 0;
|
||||||
|
|
||||||
/// Spawn a blood effect for \a ptr at \a worldPosition
|
/// Spawn a blood effect for \a ptr at \a worldPosition
|
||||||
virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const Ogre::Vector3& worldPosition) = 0;
|
virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition) = 0;
|
||||||
|
|
||||||
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const Ogre::Vector3& worldPos) = 0;
|
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos) = 0;
|
||||||
|
|
||||||
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects,
|
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects,
|
||||||
const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName) = 0;
|
const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName) = 0;
|
||||||
|
|
|
@ -319,7 +319,7 @@ namespace MWClass
|
||||||
damage = 0;
|
damage = 0;
|
||||||
|
|
||||||
if (damage > 0)
|
if (damage > 0)
|
||||||
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
|
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, osg::Vec3f(hitPosition.x, hitPosition.y, hitPosition.z));
|
||||||
|
|
||||||
MWMechanics::diseaseContact(victim, ptr);
|
MWMechanics::diseaseContact(victim, ptr);
|
||||||
|
|
||||||
|
|
|
@ -583,7 +583,7 @@ namespace MWClass
|
||||||
damage = 0;
|
damage = 0;
|
||||||
|
|
||||||
if (healthdmg && damage > 0)
|
if (healthdmg && damage > 0)
|
||||||
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
|
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, osg::Vec3f(hitPosition.x, hitPosition.y, hitPosition.z));
|
||||||
|
|
||||||
MWMechanics::diseaseContact(victim, ptr);
|
MWMechanics::diseaseContact(victim, ptr);
|
||||||
|
|
||||||
|
|
|
@ -218,7 +218,7 @@ namespace MWMechanics
|
||||||
appliedEnchantment = applyEnchantment(attacker, victim, projectile, hitPosition);
|
appliedEnchantment = applyEnchantment(attacker, victim, projectile, hitPosition);
|
||||||
|
|
||||||
if (damage > 0)
|
if (damage > 0)
|
||||||
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, hitPosition);
|
MWBase::Environment::get().getWorld()->spawnBloodEffect(victim, osg::Vec3f(hitPosition.x, hitPosition.y, hitPosition.z));
|
||||||
|
|
||||||
// Non-enchanted arrows shot at enemies have a chance to turn up in their inventory
|
// Non-enchanted arrows shot at enemies have a chance to turn up in their inventory
|
||||||
if (victim != MWBase::Environment::get().getWorld()->getPlayerPtr()
|
if (victim != MWBase::Environment::get().getWorld()->getPlayerPtr()
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace MWMechanics
|
||||||
.search("VFX_Summon_End");
|
.search("VFX_Summon_End");
|
||||||
if (fx)
|
if (fx)
|
||||||
MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + fx->mModel,
|
MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + fx->mModel,
|
||||||
"", Ogre::Vector3(ptr.getRefData().getPosition().pos));
|
"", ptr.getRefData().getPosition().asVec3());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -190,7 +190,7 @@ namespace MWMechanics
|
||||||
.search("VFX_Summon_End");
|
.search("VFX_Summon_End");
|
||||||
if (fx)
|
if (fx)
|
||||||
MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + fx->mModel,
|
MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + fx->mModel,
|
||||||
"", Ogre::Vector3(ptr.getRefData().getPosition().pos));
|
"", ptr.getRefData().getPosition().asVec3());
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->deleteObject(ptr);
|
MWBase::Environment::get().getWorld()->deleteObject(ptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
#include "vismask.hpp"
|
#include "vismask.hpp"
|
||||||
|
#include "util.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -70,30 +71,6 @@ namespace
|
||||||
std::vector<osg::ref_ptr<osg::Texture2D> > mTextures;
|
std::vector<osg::ref_ptr<osg::Texture2D> > mTextures;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FindMaxControllerLengthVisitor : public SceneUtil::ControllerVisitor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FindMaxControllerLengthVisitor()
|
|
||||||
: SceneUtil::ControllerVisitor()
|
|
||||||
, mMaxLength(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void visit(osg::Node& , SceneUtil::Controller& ctrl)
|
|
||||||
{
|
|
||||||
if (ctrl.mFunction)
|
|
||||||
mMaxLength = std::max(mMaxLength, ctrl.mFunction->getMaximum());
|
|
||||||
}
|
|
||||||
|
|
||||||
float getMaxLength() const
|
|
||||||
{
|
|
||||||
return mMaxLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
float mMaxLength;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
|
@ -246,7 +223,7 @@ namespace MWRender
|
||||||
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->createInstance(model, parentNode);
|
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->createInstance(model, parentNode);
|
||||||
params.mObjects = PartHolderPtr(new PartHolder(node));
|
params.mObjects = PartHolderPtr(new PartHolder(node));
|
||||||
|
|
||||||
FindMaxControllerLengthVisitor findMaxLengthVisitor;
|
SceneUtil::FindMaxControllerLengthVisitor findMaxLengthVisitor;
|
||||||
node->accept(findMaxLengthVisitor);
|
node->accept(findMaxLengthVisitor);
|
||||||
|
|
||||||
params.mMaxControllerLength = findMaxLengthVisitor.getMaxLength();
|
params.mMaxControllerLength = findMaxLengthVisitor.getMaxLength();
|
||||||
|
@ -262,22 +239,7 @@ namespace MWRender
|
||||||
SceneUtil::AssignControllerSourcesVisitor assignVisitor(boost::shared_ptr<SceneUtil::ControllerSource>(params.mAnimTime));
|
SceneUtil::AssignControllerSourcesVisitor assignVisitor(boost::shared_ptr<SceneUtil::ControllerSource>(params.mAnimTime));
|
||||||
node->accept(assignVisitor);
|
node->accept(assignVisitor);
|
||||||
|
|
||||||
if (!texture.empty())
|
overrideTexture(texture, mResourceSystem, node);
|
||||||
{
|
|
||||||
std::string correctedTexture = Misc::ResourceHelpers::correctTexturePath(texture, mResourceSystem->getVFS());
|
|
||||||
// Not sure if wrap settings should be pulled from the overridden texture?
|
|
||||||
osg::ref_ptr<osg::Texture2D> tex = mResourceSystem->getTextureManager()->getTexture2D(correctedTexture, osg::Texture2D::CLAMP,
|
|
||||||
osg::Texture2D::CLAMP);
|
|
||||||
osg::ref_ptr<osg::StateSet> stateset;
|
|
||||||
if (node->getStateSet())
|
|
||||||
stateset = static_cast<osg::StateSet*>(node->getStateSet()->clone(osg::CopyOp::SHALLOW_COPY));
|
|
||||||
else
|
|
||||||
stateset = new osg::StateSet;
|
|
||||||
|
|
||||||
stateset->setTextureAttribute(0, tex, osg::StateAttribute::OVERRIDE);
|
|
||||||
|
|
||||||
node->setStateSet(stateset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: in vanilla morrowind the effect is scaled based on the host object's bounding box.
|
// TODO: in vanilla morrowind the effect is scaled based on the host object's bounding box.
|
||||||
|
|
||||||
|
@ -330,22 +292,22 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float Animation::EffectAnimationTime::getValue(osg::NodeVisitor*)
|
float EffectAnimationTime::getValue(osg::NodeVisitor*)
|
||||||
{
|
{
|
||||||
return mTime;
|
return mTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::EffectAnimationTime::addTime(float duration)
|
void EffectAnimationTime::addTime(float duration)
|
||||||
{
|
{
|
||||||
mTime += duration;
|
mTime += duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Animation::EffectAnimationTime::resetTime(float time)
|
void EffectAnimationTime::resetTime(float time)
|
||||||
{
|
{
|
||||||
mTime = time;
|
mTime = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Animation::EffectAnimationTime::getTime() const
|
float EffectAnimationTime::getTime() const
|
||||||
{
|
{
|
||||||
return mTime;
|
return mTime;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,20 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
class Camera;
|
class Camera;
|
||||||
|
|
||||||
|
class EffectAnimationTime : public SceneUtil::ControllerSource
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float mTime;
|
||||||
|
public:
|
||||||
|
virtual float getValue(osg::NodeVisitor* nv);
|
||||||
|
|
||||||
|
void addTime(float duration);
|
||||||
|
void resetTime(float time);
|
||||||
|
float getTime() const;
|
||||||
|
|
||||||
|
EffectAnimationTime() : mTime(0) { }
|
||||||
|
};
|
||||||
|
|
||||||
class Animation
|
class Animation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -61,20 +75,6 @@ protected:
|
||||||
virtual void setValue(Ogre::Real value);
|
virtual void setValue(Ogre::Real value);
|
||||||
};
|
};
|
||||||
|
|
||||||
class EffectAnimationTime : public SceneUtil::ControllerSource
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
float mTime;
|
|
||||||
public:
|
|
||||||
virtual float getValue(osg::NodeVisitor* nv);
|
|
||||||
|
|
||||||
void addTime(float duration);
|
|
||||||
void resetTime(float time);
|
|
||||||
float getTime() const;
|
|
||||||
|
|
||||||
EffectAnimationTime() : mTime(0) { }
|
|
||||||
};
|
|
||||||
|
|
||||||
class NullAnimationTime : public SceneUtil::ControllerSource
|
class NullAnimationTime : public SceneUtil::ControllerSource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,102 +1,83 @@
|
||||||
#include "effectmanager.hpp"
|
#include "effectmanager.hpp"
|
||||||
|
|
||||||
|
#include <osg/PositionAttitudeTransform>
|
||||||
|
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
|
|
||||||
#include <OgreSceneManager.h>
|
#include <components/resource/resourcesystem.hpp>
|
||||||
#include <OgreParticleSystem.h>
|
#include <components/resource/scenemanager.hpp>
|
||||||
#include <OgreSceneNode.h>
|
|
||||||
#include <OgreTechnique.h>
|
#include <components/sceneutil/controller.hpp>
|
||||||
|
|
||||||
#include "animation.hpp"
|
#include "animation.hpp"
|
||||||
#include "renderconst.hpp"
|
#include "vismask.hpp"
|
||||||
|
#include "util.hpp"
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
EffectManager::EffectManager(Ogre::SceneManager *sceneMgr)
|
EffectManager::EffectManager(osg::ref_ptr<osg::Group> parent, Resource::ResourceSystem* resourceSystem)
|
||||||
: mSceneMgr(sceneMgr)
|
: mParentNode(parent)
|
||||||
|
, mResourceSystem(resourceSystem)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectManager::addEffect(const std::string &model, std::string textureOverride, const Ogre::Vector3 &worldPosition, float scale)
|
EffectManager::~EffectManager()
|
||||||
{
|
{
|
||||||
Ogre::SceneNode* sceneNode = mSceneMgr->getRootSceneNode()->createChildSceneNode(worldPosition);
|
clear();
|
||||||
sceneNode->setScale(scale,scale,scale);
|
|
||||||
|
|
||||||
NifOgre::ObjectScenePtr scene = NifOgre::Loader::createObjects(sceneNode, model);
|
|
||||||
|
|
||||||
MWRender::Animation::setRenderProperties(scene, RV_Effects,
|
|
||||||
RQG_Main, RQG_Alpha, 0.f, false, NULL);
|
|
||||||
|
|
||||||
for(size_t i = 0;i < scene->mControllers.size();i++)
|
|
||||||
{
|
|
||||||
if(scene->mControllers[i].getSource().isNull())
|
|
||||||
scene->mControllers[i].setSource(Ogre::SharedPtr<EffectAnimationTime> (new EffectAnimationTime()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!textureOverride.empty())
|
void EffectManager::addEffect(const std::string &model, const std::string& textureOverride, const osg::Vec3f &worldPosition, float scale)
|
||||||
{
|
{
|
||||||
std::string correctedTexture = Misc::ResourceHelpers::correctTexturePath(textureOverride);
|
osg::ref_ptr<osg::Node> node = mResourceSystem->getSceneManager()->createInstance(model);
|
||||||
for(size_t i = 0;i < scene->mParticles.size(); ++i)
|
|
||||||
{
|
|
||||||
Ogre::ParticleSystem* partSys = scene->mParticles[i];
|
|
||||||
|
|
||||||
Ogre::MaterialPtr mat = scene->mMaterialControllerMgr.getWritableMaterial(partSys);
|
node->setNodeMask(Mask_Effect);
|
||||||
|
|
||||||
for (int t=0; t<mat->getNumTechniques(); ++t)
|
Effect effect;
|
||||||
{
|
effect.mAnimTime.reset(new EffectAnimationTime);
|
||||||
Ogre::Technique* tech = mat->getTechnique(t);
|
|
||||||
for (int p=0; p<tech->getNumPasses(); ++p)
|
SceneUtil::FindMaxControllerLengthVisitor findMaxLengthVisitor;
|
||||||
{
|
node->accept(findMaxLengthVisitor);
|
||||||
Ogre::Pass* pass = tech->getPass(p);
|
effect.mMaxControllerLength = findMaxLengthVisitor.getMaxLength();
|
||||||
for (int tex=0; tex<pass->getNumTextureUnitStates(); ++tex)
|
|
||||||
{
|
osg::ref_ptr<osg::PositionAttitudeTransform> trans = new osg::PositionAttitudeTransform;
|
||||||
Ogre::TextureUnitState* tus = pass->getTextureUnitState(tex);
|
trans->setPosition(worldPosition);
|
||||||
tus->setTextureName(correctedTexture);
|
trans->setScale(osg::Vec3f(scale, scale, scale));
|
||||||
}
|
trans->addChild(node);
|
||||||
}
|
|
||||||
}
|
SceneUtil::AssignControllerSourcesVisitor assignVisitor(effect.mAnimTime);
|
||||||
}
|
node->accept(assignVisitor);
|
||||||
|
|
||||||
|
overrideTexture(textureOverride, mResourceSystem, node);
|
||||||
|
|
||||||
|
mParentNode->addChild(trans);
|
||||||
|
|
||||||
|
mEffects[trans] = effect;
|
||||||
}
|
}
|
||||||
|
|
||||||
mEffects.push_back(std::make_pair(sceneNode, scene));
|
void EffectManager::update(float dt)
|
||||||
}
|
{
|
||||||
|
for (EffectMap::iterator it = mEffects.begin(); it != mEffects.end(); )
|
||||||
|
{
|
||||||
|
it->second.mAnimTime->addTime(dt);
|
||||||
|
|
||||||
void EffectManager::update(float dt, Ogre::Camera* camera)
|
if (it->second.mAnimTime->getTime() >= it->second.mMaxControllerLength)
|
||||||
{
|
{
|
||||||
for (std::vector<std::pair<Ogre::SceneNode*, NifOgre::ObjectScenePtr> >::iterator it = mEffects.begin(); it != mEffects.end(); )
|
mParentNode->removeChild(it->first);
|
||||||
{
|
mEffects.erase(it++);
|
||||||
NifOgre::ObjectScenePtr objects = it->second;
|
|
||||||
for(size_t i = 0; i < objects->mControllers.size() ;i++)
|
|
||||||
{
|
|
||||||
EffectAnimationTime* value = dynamic_cast<EffectAnimationTime*>(objects->mControllers[i].getSource().get());
|
|
||||||
if (value)
|
|
||||||
value->addTime(dt);
|
|
||||||
|
|
||||||
objects->mControllers[i].update();
|
|
||||||
}
|
|
||||||
objects->rotateBillboardNodes(camera);
|
|
||||||
|
|
||||||
// Finished playing?
|
|
||||||
if (objects->mControllers[0].getSource()->getValue() >= objects->mMaxControllerLength)
|
|
||||||
{
|
|
||||||
Ogre::SceneNode* node = it->first;
|
|
||||||
it = mEffects.erase(it);
|
|
||||||
mSceneMgr->destroySceneNode(node);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EffectManager::clear()
|
void EffectManager::clear()
|
||||||
{
|
{
|
||||||
for (std::vector<std::pair<Ogre::SceneNode*, NifOgre::ObjectScenePtr> >::iterator it = mEffects.begin(); it != mEffects.end(); )
|
for (EffectMap::iterator it = mEffects.begin(); it != mEffects.end(); ++it)
|
||||||
{
|
{
|
||||||
Ogre::SceneNode* node = it->first;
|
mParentNode->removeChild(it->first);
|
||||||
it = mEffects.erase(it);
|
|
||||||
mSceneMgr->destroySceneNode(node);
|
|
||||||
}
|
}
|
||||||
|
mEffects.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +1,60 @@
|
||||||
#ifndef OPENMW_MWRENDER_EFFECTMANAGER_H
|
#ifndef OPENMW_MWRENDER_EFFECTMANAGER_H
|
||||||
#define OPENMW_MWRENDER_EFFECTMANAGER_H
|
#define OPENMW_MWRENDER_EFFECTMANAGER_H
|
||||||
|
|
||||||
#include <components/nifogre/ogrenifloader.hpp>
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
|
||||||
|
namespace osg
|
||||||
|
{
|
||||||
|
class Group;
|
||||||
|
class Vec3f;
|
||||||
|
class PositionAttitudeTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
class ResourceSystem;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
class EffectAnimationTime;
|
||||||
class EffectAnimationTime : public Ogre::ControllerValue<Ogre::Real>
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
float mTime;
|
|
||||||
public:
|
|
||||||
EffectAnimationTime() : mTime(0) { }
|
|
||||||
void addTime(float time) { mTime += time; }
|
|
||||||
|
|
||||||
virtual Ogre::Real getValue() const { return mTime; }
|
|
||||||
virtual void setValue(Ogre::Real value) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Note: effects attached to another object should be managed by MWRender::Animation::addEffect.
|
// Note: effects attached to another object should be managed by MWRender::Animation::addEffect.
|
||||||
// This class manages "free" effects, i.e. attached to a dedicated scene node in the world.
|
// This class manages "free" effects, i.e. attached to a dedicated scene node in the world.
|
||||||
class EffectManager
|
class EffectManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EffectManager(Ogre::SceneManager* sceneMgr);
|
EffectManager(osg::ref_ptr<osg::Group> parent, Resource::ResourceSystem* resourceSystem);
|
||||||
~EffectManager() { clear(); }
|
~EffectManager();
|
||||||
|
|
||||||
/// Add an effect. When it's finished playing, it will be removed automatically.
|
/// Add an effect. When it's finished playing, it will be removed automatically.
|
||||||
void addEffect (const std::string& model, std::string textureOverride, const Ogre::Vector3& worldPosition, float scale);
|
void addEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPosition, float scale);
|
||||||
|
|
||||||
void update(float dt, Ogre::Camera* camera);
|
void update(float dt);
|
||||||
|
|
||||||
/// Remove all effects
|
/// Remove all effects
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::pair<Ogre::SceneNode*, NifOgre::ObjectScenePtr> > mEffects;
|
struct Effect
|
||||||
Ogre::SceneManager* mSceneMgr;
|
{
|
||||||
|
float mMaxControllerLength;
|
||||||
|
boost::shared_ptr<EffectAnimationTime> mAnimTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<osg::ref_ptr<osg::PositionAttitudeTransform>, Effect> EffectMap;
|
||||||
|
EffectMap mEffects;
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Group> mParentNode;
|
||||||
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
|
|
||||||
|
EffectManager(const EffectManager&);
|
||||||
|
void operator=(const EffectManager&);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
#include "../mwworld/ptr.hpp"
|
#include "../mwworld/ptr.hpp"
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
#include "../mwworld/cellstore.hpp"
|
|
||||||
|
|
||||||
#include "renderconst.hpp"
|
#include "renderconst.hpp"
|
||||||
#include "animation.hpp"
|
#include "animation.hpp"
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <components/esm/loadcell.hpp>
|
#include <components/esm/loadcell.hpp>
|
||||||
|
|
||||||
#include "sky.hpp"
|
#include "sky.hpp"
|
||||||
|
#include "effectmanager.hpp"
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
@ -60,6 +61,8 @@ namespace MWRender
|
||||||
|
|
||||||
mSky.reset(new SkyManager(mRootNode, resourceSystem->getSceneManager()));
|
mSky.reset(new SkyManager(mRootNode, resourceSystem->getSceneManager()));
|
||||||
|
|
||||||
|
mEffectManager.reset(new EffectManager(mRootNode, mResourceSystem));
|
||||||
|
|
||||||
mViewer.setLightingMode(osgViewer::View::NO_LIGHT);
|
mViewer.setLightingMode(osgViewer::View::NO_LIGHT);
|
||||||
|
|
||||||
osg::ref_ptr<osg::LightSource> source = new osg::LightSource;
|
osg::ref_ptr<osg::LightSource> source = new osg::LightSource;
|
||||||
|
@ -163,6 +166,24 @@ namespace MWRender
|
||||||
void RenderingManager::update(float dt, bool paused)
|
void RenderingManager::update(float dt, bool paused)
|
||||||
{
|
{
|
||||||
mObjects->update(dt);
|
mObjects->update(dt);
|
||||||
|
mEffectManager->update(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingManager::spawnEffect(const std::string &model, const std::string &texture, const osg::Vec3f &worldPosition, float scale)
|
||||||
|
{
|
||||||
|
mEffectManager->addEffect(model, texture, worldPosition, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingManager::notifyWorldSpaceChanged()
|
||||||
|
{
|
||||||
|
mEffectManager->clear();
|
||||||
|
//mWater->clearRipples();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingManager::clear()
|
||||||
|
{
|
||||||
|
//mLocalMap->clear();
|
||||||
|
notifyWorldSpaceChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ namespace MWRender
|
||||||
|
|
||||||
class StateUpdater;
|
class StateUpdater;
|
||||||
|
|
||||||
|
class EffectManager;
|
||||||
class SkyManager;
|
class SkyManager;
|
||||||
|
|
||||||
class RenderingManager : public MWRender::RenderingInterface
|
class RenderingManager : public MWRender::RenderingInterface
|
||||||
|
@ -63,6 +64,14 @@ namespace MWRender
|
||||||
|
|
||||||
osg::Vec3f getEyePos();
|
osg::Vec3f getEyePos();
|
||||||
|
|
||||||
|
void spawnEffect(const std::string &model, const std::string &texture, const osg::Vec3f &worldPosition, float scale = 1.f);
|
||||||
|
|
||||||
|
/// Clear all savegame-specific data
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
/// Clear all worldspace-specific data
|
||||||
|
void notifyWorldSpaceChanged();
|
||||||
|
|
||||||
void update(float dt, bool paused);
|
void update(float dt, bool paused);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -74,6 +83,7 @@ namespace MWRender
|
||||||
|
|
||||||
std::auto_ptr<Objects> mObjects;
|
std::auto_ptr<Objects> mObjects;
|
||||||
std::auto_ptr<SkyManager> mSky;
|
std::auto_ptr<SkyManager> mSky;
|
||||||
|
std::auto_ptr<EffectManager> mEffectManager;
|
||||||
|
|
||||||
osg::ref_ptr<StateUpdater> mStateUpdater;
|
osg::ref_ptr<StateUpdater> mStateUpdater;
|
||||||
|
|
||||||
|
|
31
apps/openmw/mwrender/util.cpp
Normal file
31
apps/openmw/mwrender/util.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "util.hpp"
|
||||||
|
|
||||||
|
#include <osg/Node>
|
||||||
|
|
||||||
|
#include <components/resource/resourcesystem.hpp>
|
||||||
|
#include <components/resource/texturemanager.hpp>
|
||||||
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
|
||||||
|
void overrideTexture(const std::string &texture, Resource::ResourceSystem *resourceSystem, osg::ref_ptr<osg::Node> node)
|
||||||
|
{
|
||||||
|
if (texture.empty())
|
||||||
|
return;
|
||||||
|
std::string correctedTexture = Misc::ResourceHelpers::correctTexturePath(texture, resourceSystem->getVFS());
|
||||||
|
// Not sure if wrap settings should be pulled from the overridden texture?
|
||||||
|
osg::ref_ptr<osg::Texture2D> tex = resourceSystem->getTextureManager()->getTexture2D(correctedTexture, osg::Texture2D::CLAMP,
|
||||||
|
osg::Texture2D::CLAMP);
|
||||||
|
osg::ref_ptr<osg::StateSet> stateset;
|
||||||
|
if (node->getStateSet())
|
||||||
|
stateset = static_cast<osg::StateSet*>(node->getStateSet()->clone(osg::CopyOp::SHALLOW_COPY));
|
||||||
|
else
|
||||||
|
stateset = new osg::StateSet;
|
||||||
|
|
||||||
|
stateset->setTextureAttribute(0, tex, osg::StateAttribute::OVERRIDE);
|
||||||
|
|
||||||
|
node->setStateSet(stateset);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
24
apps/openmw/mwrender/util.hpp
Normal file
24
apps/openmw/mwrender/util.hpp
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef OPENMW_MWRENDER_UTIL_H
|
||||||
|
#define OPENMW_MWRENDER_UTIL_H
|
||||||
|
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace osg
|
||||||
|
{
|
||||||
|
class Node;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
class ResourceSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
|
||||||
|
void overrideTexture(const std::string& texture, Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Node> node);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
#include "../mwscript/locals.hpp"
|
#include "../mwscript/locals.hpp"
|
||||||
|
|
||||||
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
namespace Ogre
|
namespace Ogre
|
||||||
{
|
{
|
||||||
class SceneNode;
|
class SceneNode;
|
||||||
|
|
|
@ -276,7 +276,7 @@ namespace MWWorld
|
||||||
void World::clear()
|
void World::clear()
|
||||||
{
|
{
|
||||||
mWeatherManager->clear();
|
mWeatherManager->clear();
|
||||||
//mRendering->clear();
|
mRendering->clear();
|
||||||
#if 0
|
#if 0
|
||||||
mProjectileManager->clear();
|
mProjectileManager->clear();
|
||||||
#endif
|
#endif
|
||||||
|
@ -991,8 +991,9 @@ namespace MWWorld
|
||||||
// changed worldspace
|
// changed worldspace
|
||||||
#if 0
|
#if 0
|
||||||
mProjectileManager->clear();
|
mProjectileManager->clear();
|
||||||
mRendering->notifyWorldSpaceChanged();
|
|
||||||
#endif
|
#endif
|
||||||
|
mRendering->notifyWorldSpaceChanged();
|
||||||
|
|
||||||
mCurrentWorldSpace = cellName;
|
mCurrentWorldSpace = cellName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1010,8 +1011,8 @@ namespace MWWorld
|
||||||
// changed worldspace
|
// changed worldspace
|
||||||
#if 0
|
#if 0
|
||||||
mProjectileManager->clear();
|
mProjectileManager->clear();
|
||||||
mRendering->notifyWorldSpaceChanged();
|
|
||||||
#endif
|
#endif
|
||||||
|
mRendering->notifyWorldSpaceChanged();
|
||||||
}
|
}
|
||||||
removeContainerScripts(getPlayerPtr());
|
removeContainerScripts(getPlayerPtr());
|
||||||
mWorldScene->changeToExteriorCell(position, true);
|
mWorldScene->changeToExteriorCell(position, true);
|
||||||
|
@ -3203,7 +3204,7 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::spawnBloodEffect(const Ptr &ptr, const Vector3 &worldPosition)
|
void World::spawnBloodEffect(const Ptr &ptr, const osg::Vec3f &worldPosition)
|
||||||
{
|
{
|
||||||
if (ptr == getPlayerPtr() && Settings::Manager::getBool("hit fader", "GUI"))
|
if (ptr == getPlayerPtr() && Settings::Manager::getBool("hit fader", "GUI"))
|
||||||
return;
|
return;
|
||||||
|
@ -3230,12 +3231,12 @@ namespace MWWorld
|
||||||
modelName << roll;
|
modelName << roll;
|
||||||
std::string model = "meshes\\" + getFallback()->getFallbackString(modelName.str());
|
std::string model = "meshes\\" + getFallback()->getFallbackString(modelName.str());
|
||||||
|
|
||||||
//mRendering->spawnEffect(model, texture, worldPosition);
|
mRendering->spawnEffect(model, texture, worldPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::spawnEffect(const std::string &model, const std::string &textureOverride, const Vector3 &worldPos)
|
void World::spawnEffect(const std::string &model, const std::string &textureOverride, const osg::Vec3f &worldPos)
|
||||||
{
|
{
|
||||||
//mRendering->spawnEffect(model, textureOverride, worldPos);
|
mRendering->spawnEffect(model, textureOverride, worldPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::explodeSpell(const Vector3 &origin, const ESM::EffectList &effects, const Ptr &caster, ESM::RangeType rangeType,
|
void World::explodeSpell(const Vector3 &origin, const ESM::EffectList &effects, const Ptr &caster, ESM::RangeType rangeType,
|
||||||
|
@ -3251,15 +3252,13 @@ namespace MWWorld
|
||||||
continue; // Not an area effect
|
continue; // Not an area effect
|
||||||
|
|
||||||
// Spawn the explosion orb effect
|
// Spawn the explosion orb effect
|
||||||
/*
|
|
||||||
const ESM::Static* areaStatic;
|
const ESM::Static* areaStatic;
|
||||||
if (!effect->mCasting.empty())
|
if (!effect->mCasting.empty())
|
||||||
areaStatic = getStore().get<ESM::Static>().find (effect->mArea);
|
areaStatic = getStore().get<ESM::Static>().find (effect->mArea);
|
||||||
else
|
else
|
||||||
areaStatic = getStore().get<ESM::Static>().find ("VFX_DefaultArea");
|
areaStatic = getStore().get<ESM::Static>().find ("VFX_DefaultArea");
|
||||||
|
|
||||||
mRendering->spawnEffect("meshes\\" + areaStatic->mModel, "", origin, static_cast<float>(effectIt->mArea));
|
mRendering->spawnEffect("meshes\\" + areaStatic->mModel, "", osg::Vec3f(origin.x, origin.y, origin.z), static_cast<float>(effectIt->mArea));
|
||||||
*/
|
|
||||||
|
|
||||||
// Play explosion sound (make sure to use NoTrack, since we will delete the projectile now)
|
// Play explosion sound (make sure to use NoTrack, since we will delete the projectile now)
|
||||||
static const std::string schools[] = {
|
static const std::string schools[] = {
|
||||||
|
|
|
@ -650,9 +650,9 @@ namespace MWWorld
|
||||||
virtual void spawnRandomCreature(const std::string& creatureList);
|
virtual void spawnRandomCreature(const std::string& creatureList);
|
||||||
|
|
||||||
/// Spawn a blood effect for \a ptr at \a worldPosition
|
/// Spawn a blood effect for \a ptr at \a worldPosition
|
||||||
virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const Ogre::Vector3& worldPosition);
|
virtual void spawnBloodEffect (const MWWorld::Ptr& ptr, const osg::Vec3f& worldPosition);
|
||||||
|
|
||||||
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const Ogre::Vector3& worldPos);
|
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const osg::Vec3f& worldPos);
|
||||||
|
|
||||||
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects,
|
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects,
|
||||||
const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName);
|
const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName);
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <osg/Vec3f>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -37,6 +39,11 @@ struct Position
|
||||||
{
|
{
|
||||||
float pos[3];
|
float pos[3];
|
||||||
float rot[3];
|
float rot[3];
|
||||||
|
|
||||||
|
osg::Vec3f asVec3() const
|
||||||
|
{
|
||||||
|
return osg::Vec3f(pos[0], pos[1], pos[2]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
|
|
@ -89,4 +89,21 @@ namespace SceneUtil
|
||||||
ctrl.mSource = mToAssign;
|
ctrl.mSource = mToAssign;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FindMaxControllerLengthVisitor::FindMaxControllerLengthVisitor()
|
||||||
|
: SceneUtil::ControllerVisitor()
|
||||||
|
, mMaxLength(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FindMaxControllerLengthVisitor::visit(osg::Node &, Controller &ctrl)
|
||||||
|
{
|
||||||
|
if (ctrl.mFunction)
|
||||||
|
mMaxLength = std::max(mMaxLength, ctrl.mFunction->getMaximum());
|
||||||
|
}
|
||||||
|
|
||||||
|
float FindMaxControllerLengthVisitor::getMaxLength() const
|
||||||
|
{
|
||||||
|
return mMaxLength;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,20 @@ namespace SceneUtil
|
||||||
boost::shared_ptr<ControllerSource> mToAssign;
|
boost::shared_ptr<ControllerSource> mToAssign;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Finds the maximum of all controller functions in the given scene graph
|
||||||
|
class FindMaxControllerLengthVisitor : public ControllerVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FindMaxControllerLengthVisitor();
|
||||||
|
|
||||||
|
virtual void visit(osg::Node& , Controller& ctrl);
|
||||||
|
|
||||||
|
float getMaxLength() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float mMaxLength;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue