mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 21:53:51 +00:00
Water ripples
This commit is contained in:
parent
3663511cdb
commit
3da8f6e62e
10 changed files with 355 additions and 14 deletions
|
@ -22,7 +22,7 @@ source_group(game FILES ${GAME} ${GAME_HEADER})
|
||||||
add_openmw_dir (mwrender
|
add_openmw_dir (mwrender
|
||||||
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
|
actors objects renderingmanager animation rotatecontroller sky npcanimation vismask
|
||||||
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
creatureanimation effectmanager util renderinginterface pathgrid rendermode weaponanimation
|
||||||
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage
|
bulletdebugdraw globalmap characterpreview camera localmap water terrainstorage ripplesimulation
|
||||||
)
|
)
|
||||||
|
|
||||||
add_openmw_dir (mwinput
|
add_openmw_dir (mwinput
|
||||||
|
|
|
@ -114,7 +114,7 @@ namespace MWRender
|
||||||
bool mWireframe;
|
bool mWireframe;
|
||||||
};
|
};
|
||||||
|
|
||||||
RenderingManager::RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode, Resource::ResourceSystem* resourceSystem)
|
RenderingManager::RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode, Resource::ResourceSystem* resourceSystem, const MWWorld::Fallback* fallback)
|
||||||
: mViewer(viewer)
|
: mViewer(viewer)
|
||||||
, mRootNode(rootNode)
|
, mRootNode(rootNode)
|
||||||
, mResourceSystem(resourceSystem)
|
, mResourceSystem(resourceSystem)
|
||||||
|
@ -136,7 +136,7 @@ namespace MWRender
|
||||||
|
|
||||||
mEffectManager.reset(new EffectManager(lightRoot, mResourceSystem));
|
mEffectManager.reset(new EffectManager(lightRoot, mResourceSystem));
|
||||||
|
|
||||||
mWater.reset(new Water(lightRoot, mResourceSystem, mViewer->getIncrementalCompileOperation()));
|
mWater.reset(new Water(lightRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback));
|
||||||
|
|
||||||
mTerrain.reset(new Terrain::TerrainGrid(lightRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(),
|
mTerrain.reset(new Terrain::TerrainGrid(lightRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(),
|
||||||
new TerrainStorage(mResourceSystem->getVFS(), false), Mask_Terrain));
|
new TerrainStorage(mResourceSystem->getVFS(), false), Mask_Terrain));
|
||||||
|
@ -265,6 +265,8 @@ namespace MWRender
|
||||||
|
|
||||||
if (store->getCell()->isExterior())
|
if (store->getCell()->isExterior())
|
||||||
mTerrain->unloadCell(store->getCell()->getGridX(), store->getCell()->getGridY());
|
mTerrain->unloadCell(store->getCell()->getGridX(), store->getCell()->getGridY());
|
||||||
|
|
||||||
|
mWater->removeCell(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::setSkyEnabled(bool enabled)
|
void RenderingManager::setSkyEnabled(bool enabled)
|
||||||
|
@ -330,6 +332,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
mEffectManager->update(dt);
|
mEffectManager->update(dt);
|
||||||
mSky->update(dt);
|
mSky->update(dt);
|
||||||
|
mWater->update(dt);
|
||||||
mCamera->update(dt, paused);
|
mCamera->update(dt, paused);
|
||||||
|
|
||||||
osg::Vec3f focal, cameraPos;
|
osg::Vec3f focal, cameraPos;
|
||||||
|
@ -354,6 +357,11 @@ namespace MWRender
|
||||||
mCamera->attachTo(ptr);
|
mCamera->attachTo(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingManager::removePlayer(const MWWorld::Ptr &player)
|
||||||
|
{
|
||||||
|
mWater->removeEmitter(player);
|
||||||
|
}
|
||||||
|
|
||||||
void RenderingManager::rotateObject(const MWWorld::Ptr &ptr, const osg::Quat& rot)
|
void RenderingManager::rotateObject(const MWWorld::Ptr &ptr, const osg::Quat& rot)
|
||||||
{
|
{
|
||||||
if(ptr == mCamera->getTrackingPtr() &&
|
if(ptr == mCamera->getTrackingPtr() &&
|
||||||
|
@ -378,6 +386,7 @@ namespace MWRender
|
||||||
void RenderingManager::removeObject(const MWWorld::Ptr &ptr)
|
void RenderingManager::removeObject(const MWWorld::Ptr &ptr)
|
||||||
{
|
{
|
||||||
mObjects->removeObject(ptr);
|
mObjects->removeObject(ptr);
|
||||||
|
mWater->removeEmitter(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::setWaterEnabled(bool enabled)
|
void RenderingManager::setWaterEnabled(bool enabled)
|
||||||
|
@ -579,7 +588,7 @@ namespace MWRender
|
||||||
void RenderingManager::notifyWorldSpaceChanged()
|
void RenderingManager::notifyWorldSpaceChanged()
|
||||||
{
|
{
|
||||||
mEffectManager->clear();
|
mEffectManager->clear();
|
||||||
//mWater->clearRipples();
|
mWater->clearRipples();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::clear()
|
void RenderingManager::clear()
|
||||||
|
@ -613,6 +622,8 @@ namespace MWRender
|
||||||
mPlayerNode->getUserDataContainer()->addUserObject(new PtrHolder(player));
|
mPlayerNode->getUserDataContainer()->addUserObject(new PtrHolder(player));
|
||||||
|
|
||||||
player.getRefData().setBaseNode(mPlayerNode);
|
player.getRefData().setBaseNode(mPlayerNode);
|
||||||
|
|
||||||
|
mWater->addEmitter(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::renderPlayer(const MWWorld::Ptr &player)
|
void RenderingManager::renderPlayer(const MWWorld::Ptr &player)
|
||||||
|
@ -621,8 +632,6 @@ namespace MWRender
|
||||||
|
|
||||||
mCamera->setAnimation(mPlayerAnimation.get());
|
mCamera->setAnimation(mPlayerAnimation.get());
|
||||||
mCamera->attachTo(player);
|
mCamera->attachTo(player);
|
||||||
//mWater->removeEmitter(ptr);
|
|
||||||
//mWater->addEmitter(ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
|
void RenderingManager::rebuildPtr(const MWWorld::Ptr &ptr)
|
||||||
|
@ -643,6 +652,16 @@ namespace MWRender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderingManager::addWaterRippleEmitter(const MWWorld::Ptr &ptr)
|
||||||
|
{
|
||||||
|
mWater->addEmitter(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderingManager::removeWaterRippleEmitter(const MWWorld::Ptr &ptr)
|
||||||
|
{
|
||||||
|
mWater->removeEmitter(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
void RenderingManager::updateProjectionMatrix()
|
void RenderingManager::updateProjectionMatrix()
|
||||||
{
|
{
|
||||||
double aspect = mViewer->getCamera()->getViewport()->aspectRatio();
|
double aspect = mViewer->getCamera()->getViewport()->aspectRatio();
|
||||||
|
|
|
@ -37,6 +37,11 @@ namespace Terrain
|
||||||
class World;
|
class World;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Fallback;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -52,7 +57,7 @@ namespace MWRender
|
||||||
class RenderingManager : public MWRender::RenderingInterface
|
class RenderingManager : public MWRender::RenderingInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode, Resource::ResourceSystem* resourceSystem);
|
RenderingManager(osgViewer::Viewer* viewer, osg::ref_ptr<osg::Group> rootNode, Resource::ResourceSystem* resourceSystem, const MWWorld::Fallback* fallback);
|
||||||
~RenderingManager();
|
~RenderingManager();
|
||||||
|
|
||||||
MWRender::Objects& getObjects();
|
MWRender::Objects& getObjects();
|
||||||
|
@ -125,8 +130,12 @@ namespace MWRender
|
||||||
Animation* getAnimation(const MWWorld::Ptr& ptr);
|
Animation* getAnimation(const MWWorld::Ptr& ptr);
|
||||||
Animation* getPlayerAnimation();
|
Animation* getPlayerAnimation();
|
||||||
|
|
||||||
|
void addWaterRippleEmitter(const MWWorld::Ptr& ptr);
|
||||||
|
void removeWaterRippleEmitter(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
void updatePlayerPtr(const MWWorld::Ptr &ptr);
|
void updatePlayerPtr(const MWWorld::Ptr &ptr);
|
||||||
|
|
||||||
|
void removePlayer(const MWWorld::Ptr& player);
|
||||||
void setupPlayer(const MWWorld::Ptr& player);
|
void setupPlayer(const MWWorld::Ptr& player);
|
||||||
void renderPlayer(const MWWorld::Ptr& player);
|
void renderPlayer(const MWWorld::Ptr& player);
|
||||||
|
|
||||||
|
|
202
apps/openmw/mwrender/ripplesimulation.cpp
Normal file
202
apps/openmw/mwrender/ripplesimulation.cpp
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
#include "ripplesimulation.hpp"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
|
#include <osg/Geode>
|
||||||
|
#include <osg/Texture2D>
|
||||||
|
#include <osg/Material>
|
||||||
|
#include <osg/Depth>
|
||||||
|
#include <osg/PositionAttitudeTransform>
|
||||||
|
#include <osgParticle/ParticleSystem>
|
||||||
|
#include <osgParticle/ParticleSystemUpdater>
|
||||||
|
|
||||||
|
#include <components/misc/rng.hpp>
|
||||||
|
#include <components/nifosg/controller.hpp>
|
||||||
|
#include <components/resource/texturemanager.hpp>
|
||||||
|
#include <components/resource/resourcesystem.hpp>
|
||||||
|
|
||||||
|
#include "vismask.hpp"
|
||||||
|
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
|
||||||
|
#include "../mwworld/fallback.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void createWaterRippleStateSet(Resource::ResourceSystem* resourceSystem, const MWWorld::Fallback* fallback, osg::Node* node)
|
||||||
|
{
|
||||||
|
int rippleFrameCount = fallback->getFallbackInt("Water_RippleFrameCount");
|
||||||
|
if (rippleFrameCount <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string tex = fallback->getFallbackString("Water_RippleTexture");
|
||||||
|
|
||||||
|
std::vector<osg::ref_ptr<osg::Texture2D> > textures;
|
||||||
|
for (int i=0; i<rippleFrameCount; ++i)
|
||||||
|
{
|
||||||
|
std::ostringstream texname;
|
||||||
|
texname << "textures/water/" << tex << std::setw(2) << std::setfill('0') << i << ".dds";
|
||||||
|
textures.push_back(resourceSystem->getTextureManager()->getTexture2D(texname.str(), osg::Texture::REPEAT, osg::Texture::REPEAT));
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<NifOsg::FlipController> controller (new NifOsg::FlipController(0, 0.3f/rippleFrameCount, textures));
|
||||||
|
controller->setSource(boost::shared_ptr<SceneUtil::ControllerSource>(new SceneUtil::FrameTimeSource));
|
||||||
|
node->addUpdateCallback(controller);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::StateSet> stateset (new osg::StateSet);
|
||||||
|
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||||
|
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||||
|
stateset->setTextureAttributeAndModes(0, textures[0], osg::StateAttribute::ON);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Depth> depth (new osg::Depth);
|
||||||
|
depth->setWriteMask(false);
|
||||||
|
stateset->setAttributeAndModes(depth, osg::StateAttribute::ON);
|
||||||
|
|
||||||
|
stateset->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Material> mat (new osg::Material);
|
||||||
|
mat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 1.f));
|
||||||
|
mat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 1.f));
|
||||||
|
mat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4f(1.f, 1.f, 1.f, 1.f));
|
||||||
|
mat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4f(0.f, 0.f, 0.f, 0.f));
|
||||||
|
mat->setColorMode(osg::Material::DIFFUSE);
|
||||||
|
stateset->setAttributeAndModes(mat, osg::StateAttribute::ON);
|
||||||
|
|
||||||
|
node->setStateSet(stateset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
|
||||||
|
RippleSimulation::RippleSimulation(osg::Group *parent, Resource::ResourceSystem* resourceSystem, const MWWorld::Fallback* fallback)
|
||||||
|
: mParent(parent)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||||
|
|
||||||
|
mParticleSystem = new osgParticle::ParticleSystem;
|
||||||
|
geode->addDrawable(mParticleSystem);
|
||||||
|
|
||||||
|
mParticleSystem->setParticleAlignment(osgParticle::ParticleSystem::FIXED);
|
||||||
|
mParticleSystem->setAlignVectorX(osg::Vec3f(1,0,0));
|
||||||
|
mParticleSystem->setAlignVectorY(osg::Vec3f(0,1,0));
|
||||||
|
|
||||||
|
osgParticle::Particle& particleTemplate = mParticleSystem->getDefaultParticleTemplate();
|
||||||
|
particleTemplate.setSizeRange(osgParticle::rangef(15, 180));
|
||||||
|
particleTemplate.setColorRange(osgParticle::rangev4(osg::Vec4f(1,1,1,0.7), osg::Vec4f(1,1,1,0.7)));
|
||||||
|
particleTemplate.setAlphaRange(osgParticle::rangef(1.f, 0.f));
|
||||||
|
particleTemplate.setAngularVelocity(osg::Vec3f(0,0,fallback->getFallbackFloat("Water_RippleRotSpeed")));
|
||||||
|
particleTemplate.setLifeTime(fallback->getFallbackFloat("Water_RippleLifetime"));
|
||||||
|
|
||||||
|
osg::ref_ptr<osgParticle::ParticleSystemUpdater> updater (new osgParticle::ParticleSystemUpdater);
|
||||||
|
updater->addParticleSystem(mParticleSystem);
|
||||||
|
|
||||||
|
mParticleNode = new osg::PositionAttitudeTransform;
|
||||||
|
mParticleNode->addChild(updater);
|
||||||
|
mParticleNode->addChild(geode);
|
||||||
|
mParticleNode->setNodeMask(Mask_Effect);
|
||||||
|
|
||||||
|
createWaterRippleStateSet(resourceSystem, fallback, mParticleNode);
|
||||||
|
|
||||||
|
mParent->addChild(mParticleNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
RippleSimulation::~RippleSimulation()
|
||||||
|
{
|
||||||
|
mParent->removeChild(mParticleNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RippleSimulation::update(float dt)
|
||||||
|
{
|
||||||
|
for (std::vector<Emitter>::iterator it=mEmitters.begin(); it !=mEmitters.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->mPtr == MWBase::Environment::get().getWorld ()->getPlayerPtr())
|
||||||
|
{
|
||||||
|
// fetch a new ptr (to handle cell change etc)
|
||||||
|
// for non-player actors this is done in updateObjectCell
|
||||||
|
it->mPtr = MWBase::Environment::get().getWorld ()->getPlayerPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Vec3f currentPos (it->mPtr.getRefData().getPosition().asVec3());
|
||||||
|
currentPos.z() = 0; // Z is set by the Scene Node
|
||||||
|
|
||||||
|
if ( (currentPos - it->mLastEmitPosition).length() > 10
|
||||||
|
// Only emit when close to the water surface, not above it and not too deep in the water
|
||||||
|
&& MWBase::Environment::get().getWorld ()->isUnderwater (it->mPtr.getCell(), it->mPtr.getRefData().getPosition().asVec3())
|
||||||
|
&& !MWBase::Environment::get().getWorld()->isSubmerged(it->mPtr))
|
||||||
|
{
|
||||||
|
it->mLastEmitPosition = currentPos;
|
||||||
|
|
||||||
|
if (mParticleSystem->numParticles()-mParticleSystem->numDeadParticles() > 500)
|
||||||
|
continue; // TODO: remove the oldest particle to make room?
|
||||||
|
|
||||||
|
osgParticle::Particle* p = mParticleSystem->createParticle(NULL);
|
||||||
|
p->setPosition(currentPos);
|
||||||
|
p->setAngle(osg::Vec3f(0,0, Misc::Rng::rollProbability() * osg::PI * 2 - osg::PI));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RippleSimulation::addEmitter(const MWWorld::Ptr& ptr, float scale, float force)
|
||||||
|
{
|
||||||
|
Emitter newEmitter;
|
||||||
|
newEmitter.mPtr = ptr;
|
||||||
|
newEmitter.mScale = scale;
|
||||||
|
newEmitter.mForce = force;
|
||||||
|
newEmitter.mLastEmitPosition = osg::Vec3f(0,0,0);
|
||||||
|
mEmitters.push_back (newEmitter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RippleSimulation::removeEmitter (const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
for (std::vector<Emitter>::iterator it = mEmitters.begin(); it != mEmitters.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->mPtr == ptr)
|
||||||
|
{
|
||||||
|
mEmitters.erase(it);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RippleSimulation::updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr)
|
||||||
|
{
|
||||||
|
for (std::vector<Emitter>::iterator it = mEmitters.begin(); it != mEmitters.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->mPtr == old)
|
||||||
|
{
|
||||||
|
it->mPtr = ptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RippleSimulation::removeCell(const MWWorld::CellStore *store)
|
||||||
|
{
|
||||||
|
for (std::vector<Emitter>::iterator it = mEmitters.begin(); it != mEmitters.end();)
|
||||||
|
{
|
||||||
|
if (it->mPtr.getCell() == store && it->mPtr != MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||||
|
{
|
||||||
|
it = mEmitters.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RippleSimulation::setWaterHeight(float height)
|
||||||
|
{
|
||||||
|
mParticleNode->setPosition(osg::Vec3f(0,0,height));
|
||||||
|
}
|
||||||
|
|
||||||
|
void RippleSimulation::clear()
|
||||||
|
{
|
||||||
|
for (int i=0; i<mParticleSystem->numParticles(); ++i)
|
||||||
|
mParticleSystem->destroyParticle(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
76
apps/openmw/mwrender/ripplesimulation.hpp
Normal file
76
apps/openmw/mwrender/ripplesimulation.hpp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#ifndef OPENMW_MWRENDER_RIPPLESIMULATION_H
|
||||||
|
#define OPENMW_MWRENDER_RIPPLESIMULATION_H
|
||||||
|
|
||||||
|
#include <osg/ref_ptr>
|
||||||
|
|
||||||
|
#include "../mwworld/ptr.hpp"
|
||||||
|
|
||||||
|
namespace osg
|
||||||
|
{
|
||||||
|
class Group;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace osgParticle
|
||||||
|
{
|
||||||
|
class ParticleSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Resource
|
||||||
|
{
|
||||||
|
class ResourceSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWRender
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Emitter
|
||||||
|
{
|
||||||
|
MWWorld::Ptr mPtr;
|
||||||
|
osg::Vec3f mLastEmitPosition;
|
||||||
|
float mScale;
|
||||||
|
float mForce;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RippleSimulation
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RippleSimulation(osg::Group* parent, Resource::ResourceSystem* resourceSystem, const MWWorld::Fallback* fallback);
|
||||||
|
~RippleSimulation();
|
||||||
|
|
||||||
|
/// @param dt Time since the last frame
|
||||||
|
void update(float dt);
|
||||||
|
|
||||||
|
/// adds an emitter, position will be tracked automatically
|
||||||
|
void addEmitter (const MWWorld::Ptr& ptr, float scale = 1.f, float force = 1.f);
|
||||||
|
void removeEmitter (const MWWorld::Ptr& ptr);
|
||||||
|
void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr);
|
||||||
|
void removeCell(const MWWorld::CellStore* store);
|
||||||
|
|
||||||
|
/// Change the height of the water surface, thus moving all ripples with it
|
||||||
|
void setWaterHeight(float height);
|
||||||
|
|
||||||
|
/// Remove all active ripples
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
osg::ref_ptr<osg::Group> mParent;
|
||||||
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
|
|
||||||
|
osg::ref_ptr<osgParticle::ParticleSystem> mParticleSystem;
|
||||||
|
osg::ref_ptr<osg::PositionAttitudeTransform> mParticleNode;
|
||||||
|
|
||||||
|
std::vector<Emitter> mEmitters;
|
||||||
|
|
||||||
|
float mRippleLifeTime;
|
||||||
|
float mRippleRotSpeed;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -18,6 +18,7 @@
|
||||||
#include <components/sceneutil/controller.hpp>
|
#include <components/sceneutil/controller.hpp>
|
||||||
|
|
||||||
#include "vismask.hpp"
|
#include "vismask.hpp"
|
||||||
|
#include "ripplesimulation.hpp"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -107,13 +108,15 @@ namespace MWRender
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
Water::Water(osg::Group *parent, Resource::ResourceSystem *resourceSystem, osgUtil::IncrementalCompileOperation *ico)
|
Water::Water(osg::Group *parent, Resource::ResourceSystem *resourceSystem, osgUtil::IncrementalCompileOperation *ico, const MWWorld::Fallback* fallback)
|
||||||
: mParent(parent)
|
: mParent(parent)
|
||||||
, mResourceSystem(resourceSystem)
|
, mResourceSystem(resourceSystem)
|
||||||
, mEnabled(true)
|
, mEnabled(true)
|
||||||
, mToggled(true)
|
, mToggled(true)
|
||||||
, mTop(0)
|
, mTop(0)
|
||||||
{
|
{
|
||||||
|
mSimulation.reset(new RippleSimulation(parent, resourceSystem, fallback));
|
||||||
|
|
||||||
osg::ref_ptr<osg::Geometry> waterGeom = createWaterGeometry(CELL_SIZE*150, 40, 900);
|
osg::ref_ptr<osg::Geometry> waterGeom = createWaterGeometry(CELL_SIZE*150, 40, 900);
|
||||||
|
|
||||||
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
osg::ref_ptr<osg::Geode> geode (new osg::Geode);
|
||||||
|
@ -161,6 +164,11 @@ void Water::setHeight(const float height)
|
||||||
mWaterNode->setPosition(pos);
|
mWaterNode->setPosition(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Water::update(float dt)
|
||||||
|
{
|
||||||
|
mSimulation->update(dt);
|
||||||
|
}
|
||||||
|
|
||||||
void Water::updateVisible()
|
void Water::updateVisible()
|
||||||
{
|
{
|
||||||
mWaterNode->setNodeMask(mEnabled && mToggled ? ~0 : 0);
|
mWaterNode->setNodeMask(mEnabled && mToggled ? ~0 : 0);
|
||||||
|
@ -183,7 +191,6 @@ osg::Vec3f Water::getSceneNodeCoordinates(int gridX, int gridY)
|
||||||
return osg::Vec3f(static_cast<float>(gridX * CELL_SIZE + (CELL_SIZE / 2)), static_cast<float>(gridY * CELL_SIZE + (CELL_SIZE / 2)), mTop);
|
return osg::Vec3f(static_cast<float>(gridX * CELL_SIZE + (CELL_SIZE / 2)), static_cast<float>(gridY * CELL_SIZE + (CELL_SIZE / 2)), mTop);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
void Water::addEmitter (const MWWorld::Ptr& ptr, float scale, float force)
|
void Water::addEmitter (const MWWorld::Ptr& ptr, float scale, float force)
|
||||||
{
|
{
|
||||||
mSimulation->addEmitter (ptr, scale, force);
|
mSimulation->addEmitter (ptr, scale, force);
|
||||||
|
@ -198,6 +205,15 @@ void Water::updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr)
|
||||||
{
|
{
|
||||||
mSimulation->updateEmitterPtr(old, ptr);
|
mSimulation->updateEmitterPtr(old, ptr);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
void Water::removeCell(const MWWorld::CellStore *store)
|
||||||
|
{
|
||||||
|
mSimulation->removeCell(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Water::clearRipples()
|
||||||
|
{
|
||||||
|
mSimulation->clear();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,16 @@ namespace Resource
|
||||||
class ResourceSystem;
|
class ResourceSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Fallback;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class RippleSimulation;
|
||||||
|
|
||||||
/// Water rendering
|
/// Water rendering
|
||||||
class Water
|
class Water
|
||||||
{
|
{
|
||||||
|
@ -34,6 +41,8 @@ namespace MWRender
|
||||||
Resource::ResourceSystem* mResourceSystem;
|
Resource::ResourceSystem* mResourceSystem;
|
||||||
osg::ref_ptr<osgUtil::IncrementalCompileOperation> mIncrementalCompileOperation;
|
osg::ref_ptr<osgUtil::IncrementalCompileOperation> mIncrementalCompileOperation;
|
||||||
|
|
||||||
|
std::auto_ptr<RippleSimulation> mSimulation;
|
||||||
|
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
bool mToggled;
|
bool mToggled;
|
||||||
float mTop;
|
float mTop;
|
||||||
|
@ -42,7 +51,7 @@ namespace MWRender
|
||||||
void updateVisible();
|
void updateVisible();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Water(osg::Group* parent, Resource::ResourceSystem* resourceSystem, osgUtil::IncrementalCompileOperation* ico);
|
Water(osg::Group* parent, Resource::ResourceSystem* resourceSystem, osgUtil::IncrementalCompileOperation* ico, const MWWorld::Fallback* fallback);
|
||||||
~Water();
|
~Water();
|
||||||
|
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
|
@ -51,16 +60,19 @@ namespace MWRender
|
||||||
|
|
||||||
bool isUnderwater(const osg::Vec3f& pos) const;
|
bool isUnderwater(const osg::Vec3f& pos) const;
|
||||||
|
|
||||||
/*
|
|
||||||
/// adds an emitter, position will be tracked automatically using its scene node
|
/// adds an emitter, position will be tracked automatically using its scene node
|
||||||
void addEmitter (const MWWorld::Ptr& ptr, float scale = 1.f, float force = 1.f);
|
void addEmitter (const MWWorld::Ptr& ptr, float scale = 1.f, float force = 1.f);
|
||||||
void removeEmitter (const MWWorld::Ptr& ptr);
|
void removeEmitter (const MWWorld::Ptr& ptr);
|
||||||
void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr);
|
void updateEmitterPtr (const MWWorld::Ptr& old, const MWWorld::Ptr& ptr);
|
||||||
*/
|
void removeCell(const MWWorld::CellStore* store); ///< remove all emitters in this cell
|
||||||
|
|
||||||
|
void clearRipples();
|
||||||
|
|
||||||
void changeCell(const MWWorld::CellStore* store);
|
void changeCell(const MWWorld::CellStore* store);
|
||||||
void setHeight(const float height);
|
void setHeight(const float height);
|
||||||
|
|
||||||
|
void update(float dt);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,4 +58,5 @@ namespace MWWorld
|
||||||
return osg::Vec4f(boost::lexical_cast<int>(ret[0])/255.f,boost::lexical_cast<int>(ret[1])/255.f,boost::lexical_cast<int>(ret[2])/255.f, 1.f);
|
return osg::Vec4f(boost::lexical_cast<int>(ret[0])/255.f,boost::lexical_cast<int>(ret[1])/255.f,boost::lexical_cast<int>(ret[2])/255.f, 1.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,9 @@ namespace
|
||||||
model = ""; // marker objects that have a hardcoded function in the game logic, should be hidden from the player
|
model = ""; // marker objects that have a hardcoded function in the game logic, should be hidden from the player
|
||||||
ptr.getClass().insertObjectRendering(ptr, model, rendering);
|
ptr.getClass().insertObjectRendering(ptr, model, rendering);
|
||||||
ptr.getClass().insertObject (ptr, model, physics);
|
ptr.getClass().insertObject (ptr, model, physics);
|
||||||
|
|
||||||
|
if (ptr.getClass().isActor())
|
||||||
|
rendering.addWaterRippleEmitter(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateObjectLocalRotation (const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics,
|
void updateObjectLocalRotation (const MWWorld::Ptr& ptr, MWPhysics::PhysicsSystem& physics,
|
||||||
|
@ -570,6 +573,8 @@ namespace MWWorld
|
||||||
MWBase::Environment::get().getSoundManager()->stopSound3D (ptr);
|
MWBase::Environment::get().getSoundManager()->stopSound3D (ptr);
|
||||||
mPhysics->remove(ptr);
|
mPhysics->remove(ptr);
|
||||||
mRendering.removeObject (ptr);
|
mRendering.removeObject (ptr);
|
||||||
|
if (ptr.getClass().isActor())
|
||||||
|
mRendering.removeWaterRippleEmitter(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Scene::isCellActive(const CellStore &cell)
|
bool Scene::isCellActive(const CellStore &cell)
|
||||||
|
|
|
@ -161,7 +161,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode);
|
mPhysics = new MWPhysics::PhysicsSystem(resourceSystem, rootNode);
|
||||||
mProjectileManager.reset(new ProjectileManager(rootNode, resourceSystem, mPhysics));
|
mProjectileManager.reset(new ProjectileManager(rootNode, resourceSystem, mPhysics));
|
||||||
mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem);
|
mRendering = new MWRender::RenderingManager(viewer, rootNode, resourceSystem, &mFallback);
|
||||||
|
|
||||||
mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback);
|
mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback);
|
||||||
|
|
||||||
|
@ -2064,6 +2064,7 @@ namespace MWWorld
|
||||||
// Remove the old CharacterController
|
// Remove the old CharacterController
|
||||||
MWBase::Environment::get().getMechanicsManager()->remove(getPlayerPtr());
|
MWBase::Environment::get().getMechanicsManager()->remove(getPlayerPtr());
|
||||||
mPhysics->remove(getPlayerPtr());
|
mPhysics->remove(getPlayerPtr());
|
||||||
|
mRendering->removePlayer(getPlayerPtr());
|
||||||
|
|
||||||
mPlayer->set(player);
|
mPlayer->set(player);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue