diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index 32ed17c5b..09f2e08fa 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -21,11 +21,11 @@ source_group(game FILES ${GAME} ${GAME_HEADER}) add_openmw_dir (mwrender actors objects renderingmanager animation sky npcanimation vismask - creatureanimation + creatureanimation effectmanager util # debugging camera activatoranimation # renderinginterface localmap occlusionquery water shadows # characterpreview globalmap ripplesimulation refraction -# terrainstorage renderconst effectmanager weaponanimation +# terrainstorage renderconst weaponanimation ) #add_openmw_dir (mwinput diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 9e6c6d9bf..0c1874ce6 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -17,6 +17,11 @@ namespace Ogre class Image; } +namespace osg +{ + class Vec3f; +} + namespace Loading { class Listener; @@ -546,9 +551,9 @@ namespace MWBase virtual void spawnRandomCreature(const std::string& creatureList) = 0; /// 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, const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName) = 0; diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index c1b8177f7..a2451e1a1 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -319,7 +319,7 @@ namespace MWClass 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); diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 506852a90..b5ac8f6c6 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -583,7 +583,7 @@ namespace MWClass 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); diff --git a/apps/openmw/mwmechanics/combat.cpp b/apps/openmw/mwmechanics/combat.cpp index 64456dd11..b80ac8cf9 100644 --- a/apps/openmw/mwmechanics/combat.cpp +++ b/apps/openmw/mwmechanics/combat.cpp @@ -218,7 +218,7 @@ namespace MWMechanics appliedEnchantment = applyEnchantment(attacker, victim, projectile, hitPosition); 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 if (victim != MWBase::Environment::get().getWorld()->getPlayerPtr() diff --git a/apps/openmw/mwmechanics/summoning.cpp b/apps/openmw/mwmechanics/summoning.cpp index daf4424c5..221c67267 100644 --- a/apps/openmw/mwmechanics/summoning.cpp +++ b/apps/openmw/mwmechanics/summoning.cpp @@ -34,7 +34,7 @@ namespace MWMechanics .search("VFX_Summon_End"); if (fx) MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + fx->mModel, - "", Ogre::Vector3(ptr.getRefData().getPosition().pos)); + "", ptr.getRefData().getPosition().asVec3()); } else { @@ -190,7 +190,7 @@ namespace MWMechanics .search("VFX_Summon_End"); if (fx) MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + fx->mModel, - "", Ogre::Vector3(ptr.getRefData().getPosition().pos)); + "", ptr.getRefData().getPosition().asVec3()); MWBase::Environment::get().getWorld()->deleteObject(ptr); } diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index e4c05bc1e..d54e87dc5 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -24,6 +24,7 @@ #include "../mwworld/class.hpp" #include "vismask.hpp" +#include "util.hpp" namespace { @@ -70,30 +71,6 @@ namespace std::vector > 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 @@ -246,7 +223,7 @@ namespace MWRender osg::ref_ptr node = mResourceSystem->getSceneManager()->createInstance(model, parentNode); params.mObjects = PartHolderPtr(new PartHolder(node)); - FindMaxControllerLengthVisitor findMaxLengthVisitor; + SceneUtil::FindMaxControllerLengthVisitor findMaxLengthVisitor; node->accept(findMaxLengthVisitor); params.mMaxControllerLength = findMaxLengthVisitor.getMaxLength(); @@ -262,22 +239,7 @@ namespace MWRender SceneUtil::AssignControllerSourcesVisitor assignVisitor(boost::shared_ptr(params.mAnimTime)); node->accept(assignVisitor); - if (!texture.empty()) - { - std::string correctedTexture = Misc::ResourceHelpers::correctTexturePath(texture, mResourceSystem->getVFS()); - // Not sure if wrap settings should be pulled from the overridden texture? - osg::ref_ptr tex = mResourceSystem->getTextureManager()->getTexture2D(correctedTexture, osg::Texture2D::CLAMP, - osg::Texture2D::CLAMP); - osg::ref_ptr stateset; - if (node->getStateSet()) - stateset = static_cast(node->getStateSet()->clone(osg::CopyOp::SHALLOW_COPY)); - else - stateset = new osg::StateSet; - - stateset->setTextureAttribute(0, tex, osg::StateAttribute::OVERRIDE); - - node->setStateSet(stateset); - } + overrideTexture(texture, mResourceSystem, node); // 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; } - void Animation::EffectAnimationTime::addTime(float duration) + void EffectAnimationTime::addTime(float duration) { mTime += duration; } - void Animation::EffectAnimationTime::resetTime(float time) + void EffectAnimationTime::resetTime(float time) { mTime = time; } - float Animation::EffectAnimationTime::getTime() const + float EffectAnimationTime::getTime() const { return mTime; } diff --git a/apps/openmw/mwrender/animation.hpp b/apps/openmw/mwrender/animation.hpp index 797c215c5..aef4d4b80 100644 --- a/apps/openmw/mwrender/animation.hpp +++ b/apps/openmw/mwrender/animation.hpp @@ -22,6 +22,20 @@ namespace MWRender { 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 { public: @@ -61,20 +75,6 @@ protected: 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 { public: diff --git a/apps/openmw/mwrender/effectmanager.cpp b/apps/openmw/mwrender/effectmanager.cpp index 503a0223e..642909cda 100644 --- a/apps/openmw/mwrender/effectmanager.cpp +++ b/apps/openmw/mwrender/effectmanager.cpp @@ -1,102 +1,83 @@ #include "effectmanager.hpp" +#include + #include -#include -#include -#include -#include +#include +#include + +#include #include "animation.hpp" -#include "renderconst.hpp" +#include "vismask.hpp" +#include "util.hpp" namespace MWRender { -EffectManager::EffectManager(Ogre::SceneManager *sceneMgr) - : mSceneMgr(sceneMgr) +EffectManager::EffectManager(osg::ref_ptr parent, Resource::ResourceSystem* resourceSystem) + : 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); - sceneNode->setScale(scale,scale,scale); + clear(); +} - NifOgre::ObjectScenePtr scene = NifOgre::Loader::createObjects(sceneNode, model); +void EffectManager::addEffect(const std::string &model, const std::string& textureOverride, const osg::Vec3f &worldPosition, float scale) +{ + osg::ref_ptr node = mResourceSystem->getSceneManager()->createInstance(model); - MWRender::Animation::setRenderProperties(scene, RV_Effects, - RQG_Main, RQG_Alpha, 0.f, false, NULL); + node->setNodeMask(Mask_Effect); - for(size_t i = 0;i < scene->mControllers.size();i++) - { - if(scene->mControllers[i].getSource().isNull()) - scene->mControllers[i].setSource(Ogre::SharedPtr (new EffectAnimationTime())); - } + Effect effect; + effect.mAnimTime.reset(new EffectAnimationTime); - if (!textureOverride.empty()) - { - std::string correctedTexture = Misc::ResourceHelpers::correctTexturePath(textureOverride); - for(size_t i = 0;i < scene->mParticles.size(); ++i) - { - Ogre::ParticleSystem* partSys = scene->mParticles[i]; - - Ogre::MaterialPtr mat = scene->mMaterialControllerMgr.getWritableMaterial(partSys); - - for (int t=0; tgetNumTechniques(); ++t) - { - Ogre::Technique* tech = mat->getTechnique(t); - for (int p=0; pgetNumPasses(); ++p) - { - Ogre::Pass* pass = tech->getPass(p); - for (int tex=0; texgetNumTextureUnitStates(); ++tex) - { - Ogre::TextureUnitState* tus = pass->getTextureUnitState(tex); - tus->setTextureName(correctedTexture); - } - } - } - } - } + SceneUtil::FindMaxControllerLengthVisitor findMaxLengthVisitor; + node->accept(findMaxLengthVisitor); + effect.mMaxControllerLength = findMaxLengthVisitor.getMaxLength(); + + osg::ref_ptr trans = new osg::PositionAttitudeTransform; + trans->setPosition(worldPosition); + trans->setScale(osg::Vec3f(scale, scale, scale)); + trans->addChild(node); + + SceneUtil::AssignControllerSourcesVisitor assignVisitor(effect.mAnimTime); + node->accept(assignVisitor); + + overrideTexture(textureOverride, mResourceSystem, node); - mEffects.push_back(std::make_pair(sceneNode, scene)); + mParentNode->addChild(trans); + + mEffects[trans] = effect; } -void EffectManager::update(float dt, Ogre::Camera* camera) +void EffectManager::update(float dt) { - for (std::vector >::iterator it = mEffects.begin(); it != mEffects.end(); ) + for (EffectMap::iterator it = mEffects.begin(); it != mEffects.end(); ) { - NifOgre::ObjectScenePtr objects = it->second; - for(size_t i = 0; i < objects->mControllers.size() ;i++) - { - EffectAnimationTime* value = dynamic_cast(objects->mControllers[i].getSource().get()); - if (value) - value->addTime(dt); - - objects->mControllers[i].update(); - } - objects->rotateBillboardNodes(camera); + it->second.mAnimTime->addTime(dt); - // Finished playing? - if (objects->mControllers[0].getSource()->getValue() >= objects->mMaxControllerLength) + if (it->second.mAnimTime->getTime() >= it->second.mMaxControllerLength) { - Ogre::SceneNode* node = it->first; - it = mEffects.erase(it); - mSceneMgr->destroySceneNode(node); - continue; + mParentNode->removeChild(it->first); + mEffects.erase(it++); } - ++it; + else + ++it; } } void EffectManager::clear() { - for (std::vector >::iterator it = mEffects.begin(); it != mEffects.end(); ) + for (EffectMap::iterator it = mEffects.begin(); it != mEffects.end(); ++it) { - Ogre::SceneNode* node = it->first; - it = mEffects.erase(it); - mSceneMgr->destroySceneNode(node); + mParentNode->removeChild(it->first); } + mEffects.clear(); } } diff --git a/apps/openmw/mwrender/effectmanager.hpp b/apps/openmw/mwrender/effectmanager.hpp index eb6863655..6d7aaaf4f 100644 --- a/apps/openmw/mwrender/effectmanager.hpp +++ b/apps/openmw/mwrender/effectmanager.hpp @@ -1,43 +1,60 @@ #ifndef OPENMW_MWRENDER_EFFECTMANAGER_H #define OPENMW_MWRENDER_EFFECTMANAGER_H -#include +#include +#include -namespace MWRender -{ +#include - class EffectAnimationTime : public Ogre::ControllerValue - { - private: - float mTime; - public: - EffectAnimationTime() : mTime(0) { } - void addTime(float time) { mTime += time; } +#include - virtual Ogre::Real getValue() const { return mTime; } - virtual void setValue(Ogre::Real value) {} - }; +namespace osg +{ + class Group; + class Vec3f; + class PositionAttitudeTransform; +} +namespace Resource +{ + class ResourceSystem; +} + +namespace MWRender +{ + class EffectAnimationTime; // 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. class EffectManager { public: - EffectManager(Ogre::SceneManager* sceneMgr); - ~EffectManager() { clear(); } + EffectManager(osg::ref_ptr parent, Resource::ResourceSystem* resourceSystem); + ~EffectManager(); /// 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 void clear(); private: - std::vector > mEffects; - Ogre::SceneManager* mSceneMgr; + struct Effect + { + float mMaxControllerLength; + boost::shared_ptr mAnimTime; + }; + + typedef std::map, Effect> EffectMap; + EffectMap mEffects; + + osg::ref_ptr mParentNode; + Resource::ResourceSystem* mResourceSystem; + + EffectManager(const EffectManager&); + void operator=(const EffectManager&); }; } diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 1d28291de..4b1fa6d5b 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -19,7 +19,6 @@ #include "../mwworld/ptr.hpp" #include "../mwworld/class.hpp" -#include "../mwworld/cellstore.hpp" #include "renderconst.hpp" #include "animation.hpp" diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 26b86d1b2..becd563b9 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -18,6 +18,7 @@ #include #include "sky.hpp" +#include "effectmanager.hpp" namespace MWRender { @@ -60,6 +61,8 @@ namespace MWRender mSky.reset(new SkyManager(mRootNode, resourceSystem->getSceneManager())); + mEffectManager.reset(new EffectManager(mRootNode, mResourceSystem)); + mViewer.setLightingMode(osgViewer::View::NO_LIGHT); osg::ref_ptr source = new osg::LightSource; @@ -163,6 +166,24 @@ namespace MWRender void RenderingManager::update(float dt, bool paused) { 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(); } } diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index b7aec3786..61f611a8c 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -33,6 +33,7 @@ namespace MWRender class StateUpdater; + class EffectManager; class SkyManager; class RenderingManager : public MWRender::RenderingInterface @@ -63,6 +64,14 @@ namespace MWRender 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); private: @@ -74,6 +83,7 @@ namespace MWRender std::auto_ptr mObjects; std::auto_ptr mSky; + std::auto_ptr mEffectManager; osg::ref_ptr mStateUpdater; diff --git a/apps/openmw/mwrender/util.cpp b/apps/openmw/mwrender/util.cpp new file mode 100644 index 000000000..e1af1c339 --- /dev/null +++ b/apps/openmw/mwrender/util.cpp @@ -0,0 +1,31 @@ +#include "util.hpp" + +#include + +#include +#include +#include + +namespace MWRender +{ + +void overrideTexture(const std::string &texture, Resource::ResourceSystem *resourceSystem, osg::ref_ptr 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 tex = resourceSystem->getTextureManager()->getTexture2D(correctedTexture, osg::Texture2D::CLAMP, + osg::Texture2D::CLAMP); + osg::ref_ptr stateset; + if (node->getStateSet()) + stateset = static_cast(node->getStateSet()->clone(osg::CopyOp::SHALLOW_COPY)); + else + stateset = new osg::StateSet; + + stateset->setTextureAttribute(0, tex, osg::StateAttribute::OVERRIDE); + + node->setStateSet(stateset); +} + +} diff --git a/apps/openmw/mwrender/util.hpp b/apps/openmw/mwrender/util.hpp new file mode 100644 index 000000000..d078f0d98 --- /dev/null +++ b/apps/openmw/mwrender/util.hpp @@ -0,0 +1,24 @@ +#ifndef OPENMW_MWRENDER_UTIL_H +#define OPENMW_MWRENDER_UTIL_H + +#include +#include + +namespace osg +{ + class Node; +} + +namespace Resource +{ + class ResourceSystem; +} + +namespace MWRender +{ + + void overrideTexture(const std::string& texture, Resource::ResourceSystem* resourceSystem, osg::ref_ptr node); + +} + +#endif diff --git a/apps/openmw/mwworld/refdata.hpp b/apps/openmw/mwworld/refdata.hpp index 2099b859f..955913d9c 100644 --- a/apps/openmw/mwworld/refdata.hpp +++ b/apps/openmw/mwworld/refdata.hpp @@ -5,6 +5,8 @@ #include "../mwscript/locals.hpp" +#include + namespace Ogre { class SceneNode; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index c6a1b5477..0628b42d7 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -276,7 +276,7 @@ namespace MWWorld void World::clear() { mWeatherManager->clear(); - //mRendering->clear(); + mRendering->clear(); #if 0 mProjectileManager->clear(); #endif @@ -991,8 +991,9 @@ namespace MWWorld // changed worldspace #if 0 mProjectileManager->clear(); - mRendering->notifyWorldSpaceChanged(); #endif + mRendering->notifyWorldSpaceChanged(); + mCurrentWorldSpace = cellName; } @@ -1010,8 +1011,8 @@ namespace MWWorld // changed worldspace #if 0 mProjectileManager->clear(); - mRendering->notifyWorldSpaceChanged(); #endif + mRendering->notifyWorldSpaceChanged(); } removeContainerScripts(getPlayerPtr()); 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")) return; @@ -3230,12 +3231,12 @@ namespace MWWorld modelName << roll; 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, @@ -3251,15 +3252,13 @@ namespace MWWorld continue; // Not an area effect // Spawn the explosion orb effect - /* const ESM::Static* areaStatic; if (!effect->mCasting.empty()) areaStatic = getStore().get().find (effect->mArea); else areaStatic = getStore().get().find ("VFX_DefaultArea"); - mRendering->spawnEffect("meshes\\" + areaStatic->mModel, "", origin, static_cast(effectIt->mArea)); - */ + mRendering->spawnEffect("meshes\\" + areaStatic->mModel, "", osg::Vec3f(origin.x, origin.y, origin.z), static_cast(effectIt->mArea)); // Play explosion sound (make sure to use NoTrack, since we will delete the projectile now) static const std::string schools[] = { diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 9afda480b..5f79f52dc 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -650,9 +650,9 @@ namespace MWWorld virtual void spawnRandomCreature(const std::string& creatureList); /// 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, const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName); diff --git a/components/esm/defs.hpp b/components/esm/defs.hpp index d261d7247..8ce76a8ea 100644 --- a/components/esm/defs.hpp +++ b/components/esm/defs.hpp @@ -3,6 +3,8 @@ #include +#include + namespace ESM { @@ -37,6 +39,11 @@ struct Position { float pos[3]; float rot[3]; + + osg::Vec3f asVec3() const + { + return osg::Vec3f(pos[0], pos[1], pos[2]); + } }; #pragma pack(pop) diff --git a/components/sceneutil/controller.cpp b/components/sceneutil/controller.cpp index 1f1b95ac8..79a75063a 100644 --- a/components/sceneutil/controller.cpp +++ b/components/sceneutil/controller.cpp @@ -89,4 +89,21 @@ namespace SceneUtil 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; + } + } diff --git a/components/sceneutil/controller.hpp b/components/sceneutil/controller.hpp index 655e02164..a4e209e8c 100644 --- a/components/sceneutil/controller.hpp +++ b/components/sceneutil/controller.hpp @@ -72,6 +72,20 @@ namespace SceneUtil boost::shared_ptr 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