More efficient StateSetController, beginnings of sky rendering

This commit is contained in:
scrawl 2015-04-14 15:55:56 +02:00
parent 8c7c89a4aa
commit 5dd1ab24fe
18 changed files with 610 additions and 762 deletions

View file

@ -20,8 +20,8 @@ set(GAME_HEADER
source_group(game FILES ${GAME} ${GAME_HEADER}) source_group(game FILES ${GAME} ${GAME_HEADER})
add_openmw_dir (mwrender add_openmw_dir (mwrender
actors objects renderingmanager animation actors objects renderingmanager animation sky
# debugging sky camera npcanimation creatureanimation activatoranimation # debugging camera npcanimation creatureanimation 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 effectmanager weaponanimation
@ -68,8 +68,8 @@ add_openmw_dir (mwworld
cells localscripts customdata inventorystore ptr actionopen actionread cells localscripts customdata inventorystore ptr actionopen actionread
actionequip timestamp actionalchemy cellstore actionapply actioneat actionequip timestamp actionalchemy cellstore actionapply actioneat
esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor esmstore store recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
contentloader esmloader actiontrap cellreflist cellref physicssystem contentloader esmloader actiontrap cellreflist cellref physicssystem weather
# weather projectilemanager # projectilemanager
) )
add_openmw_dir (mwclass add_openmw_dir (mwclass

View file

@ -499,9 +499,17 @@ void OMW::Engine::go()
//mViewer.setRealizeOperation(ico); //mViewer.setRealizeOperation(ico);
mViewer.realize(); mViewer.realize();
std::cout << "realize took " << timer.time_m() << std::endl; std::cout << "realize took " << timer.time_m() << std::endl;
osg::Timer frameTimer;
while (!mViewer.done()) while (!mViewer.done())
{ {
MWBase::Environment::get().getWorld()->update(0.f, false); double dt = frameTimer.time_s();
frameTimer.setStartTick();
// frameRenderingQueued(dt);
MWBase::Environment::get().getWorld()->update(dt, false);
MWBase::Environment::get().getWorld()->advanceTime(
dt*MWBase::Environment::get().getWorld()->getTimeScaleFactor()/3600);
mViewer.frame(/*simulationTime*/); mViewer.frame(/*simulationTime*/);
} }

View file

@ -41,7 +41,7 @@ public:
~Objects(); ~Objects();
/// @param animated Attempt to load separate keyframes from a .kf file matching the model file? /// @param animated Attempt to load separate keyframes from a .kf file matching the model file?
/// @param allowLight If false, no lights will be created, and particles systems will be cleared then frozen. /// @param allowLight If false, no lights will be created, and particles systems will be removed.
void insertModel(const MWWorld::Ptr& ptr, const std::string &model, bool animated=false, bool allowLight=true); void insertModel(const MWWorld::Ptr& ptr, const std::string &model, bool animated=false, bool allowLight=true);
void insertNPC(const MWWorld::Ptr& ptr); void insertNPC(const MWWorld::Ptr& ptr);

View file

@ -13,11 +13,39 @@
#include <components/sceneutil/lightmanager.hpp> #include <components/sceneutil/lightmanager.hpp>
#include <components/sceneutil/statesetcontroller.hpp>
#include <components/esm/loadcell.hpp> #include <components/esm/loadcell.hpp>
#include "sky.hpp"
namespace MWRender namespace MWRender
{ {
class StateUpdater : public SceneUtil::StateSetController
{
public:
virtual void setDefaults(osg::StateSet *stateset)
{
osg::LightModel* lightModel = new osg::LightModel;
stateset->setAttribute(lightModel, osg::StateAttribute::ON);
}
virtual void apply(osg::StateSet* stateset, osg::NodeVisitor*)
{
osg::LightModel* lightModel = static_cast<osg::LightModel*>(stateset->getAttribute(osg::StateAttribute::LIGHTMODEL));
lightModel->setAmbientIntensity(mAmbientColor);
}
void setAmbientColor(osg::Vec4f col)
{
mAmbientColor = col;
}
private:
osg::Vec4f mAmbientColor;
};
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)
: mViewer(viewer) : mViewer(viewer)
, mRootNode(rootNode) , mRootNode(rootNode)
@ -30,6 +58,8 @@ namespace MWRender
mObjects.reset(new Objects(mResourceSystem, lightRoot)); mObjects.reset(new Objects(mResourceSystem, lightRoot));
mSky.reset(new SkyManager(mRootNode, resourceSystem->getSceneManager()));
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;
@ -38,17 +68,30 @@ namespace MWRender
mSunLight->setDiffuse(osg::Vec4f(0,0,0,1)); mSunLight->setDiffuse(osg::Vec4f(0,0,0,1));
mSunLight->setAmbient(osg::Vec4f(0,0,0,1)); mSunLight->setAmbient(osg::Vec4f(0,0,0,1));
mSunLight->setConstantAttenuation(1.f); mSunLight->setConstantAttenuation(1.f);
source->setStateSetModes(*rootNode->getOrCreateStateSet(), osg::StateAttribute::ON);
lightRoot->addChild(source); lightRoot->addChild(source);
rootNode->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON); mRootNode->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
rootNode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON); mRootNode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);
rootNode->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); mRootNode->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON);
source->setStateSetModes(*mRootNode->getOrCreateStateSet(), osg::StateAttribute::ON);
mStateUpdater = new StateUpdater;
mRootNode->addUpdateCallback(mStateUpdater);
// for consistent benchmarks against the ogre branch. remove later // for consistent benchmarks against the ogre branch. remove later
osg::CullStack::CullingMode cullingMode = viewer.getCamera()->getCullingMode(); osg::CullStack::CullingMode cullingMode = viewer.getCamera()->getCullingMode();
cullingMode &= ~(osg::CullStack::SMALL_FEATURE_CULLING); cullingMode &= ~(osg::CullStack::SMALL_FEATURE_CULLING);
viewer.getCamera()->setCullingMode( cullingMode ); viewer.getCamera()->setCullingMode( cullingMode );
double fovy, aspect, zNear, zFar;
mViewer.getCamera()->getProjectionMatrixAsPerspective(fovy, aspect, zNear, zFar);
fovy = 55.f;
mViewer.getCamera()->setProjectionMatrixAsPerspective(fovy, aspect, zNear, zFar);
}
RenderingManager::~RenderingManager()
{
} }
MWRender::Objects& RenderingManager::getObjects() MWRender::Objects& RenderingManager::getObjects()
@ -66,21 +109,34 @@ namespace MWRender
return mResourceSystem; return mResourceSystem;
} }
void RenderingManager::setAmbientColour(const osg::Vec4f &colour)
{
mStateUpdater->setAmbientColor(colour);
}
void RenderingManager::configureAmbient(const ESM::Cell *cell) void RenderingManager::configureAmbient(const ESM::Cell *cell)
{ {
osg::ref_ptr<osg::LightModel> lightmodel = new osg::LightModel; setAmbientColour(SceneUtil::colourFromRGB(cell->mAmbi.mAmbient));
lightmodel->setAmbientIntensity(SceneUtil::colourFromRGB(cell->mAmbi.mAmbient));
mRootNode->getOrCreateStateSet()->setAttributeAndModes(lightmodel, osg::StateAttribute::ON);
mSunLight->setDiffuse(SceneUtil::colourFromRGB(cell->mAmbi.mSunlight)); mSunLight->setDiffuse(SceneUtil::colourFromRGB(cell->mAmbi.mSunlight));
mSunLight->setDirection(osg::Vec3f(1.f,-1.f,-1.f)); mSunLight->setDirection(osg::Vec3f(1.f,-1.f,-1.f));
} }
void RenderingManager::setSunColour(const osg::Vec4f &colour)
{
mSunLight->setDiffuse(colour);
}
void RenderingManager::setSunDirection(const osg::Vec3f &direction)
{
mSunLight->setDirection(direction*-1);
mSky->setSunDirection(direction*-1);
}
osg::Vec3f RenderingManager::getEyePos() osg::Vec3f RenderingManager::getEyePos()
{ {
osg::Vec3d eye; osg::Vec3d eye = mViewer.getCameraManipulator()->getMatrix().getTrans();
//mViewer.getCamera()->getViewMatrixAsLookAt(eye, center, up);
eye = mViewer.getCameraManipulator()->getMatrix().getTrans();
return eye; return eye;
} }
@ -89,4 +145,19 @@ namespace MWRender
mObjects->removeCell(store); mObjects->removeCell(store);
} }
void RenderingManager::setSkyEnabled(bool enabled)
{
mSky->setEnabled(enabled);
}
void RenderingManager::configureFog(float fogDepth, const osg::Vec4f &colour)
{
mViewer.getCamera()->setClearColor(colour);
}
SkyManager* RenderingManager::getSkyManager()
{
return mSky.get();
}
} }

View file

@ -31,20 +31,36 @@ namespace ESM
namespace MWRender namespace MWRender
{ {
class StateUpdater;
class SkyManager;
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);
~RenderingManager();
MWRender::Objects& getObjects(); MWRender::Objects& getObjects();
MWRender::Actors& getActors(); MWRender::Actors& getActors();
Resource::ResourceSystem* getResourceSystem(); Resource::ResourceSystem* getResourceSystem();
void setAmbientColour(const osg::Vec4f& colour);
void setSunDirection(const osg::Vec3f& direction);
void setSunColour(const osg::Vec4f& colour);
void configureAmbient(const ESM::Cell* cell); void configureAmbient(const ESM::Cell* cell);
void configureFog(float fogDepth, const osg::Vec4f& colour);
void removeCell(const MWWorld::CellStore* store); void removeCell(const MWWorld::CellStore* store);
void setSkyEnabled(bool enabled);
SkyManager* getSkyManager();
osg::Vec3f getEyePos(); osg::Vec3f getEyePos();
private: private:
@ -55,6 +71,12 @@ namespace MWRender
osg::ref_ptr<osg::Light> mSunLight; osg::ref_ptr<osg::Light> mSunLight;
std::auto_ptr<Objects> mObjects; std::auto_ptr<Objects> mObjects;
std::auto_ptr<SkyManager> mSky;
osg::ref_ptr<StateUpdater> mStateUpdater;
void operator = (const RenderingManager&);
RenderingManager(const RenderingManager&);
}; };
} }

File diff suppressed because it is too large Load diff

View file

@ -1,128 +1,35 @@
#ifndef GAME_RENDER_SKY_H #ifndef OPENMW_MWRENDER_SKY_H
#define GAME_RENDER_SKY_H #define OPENMW_MWRENDER_SKY_H
#include <vector>
#include <OgreVector3.h>
#include <OgreString.h>
#include <OgreMaterial.h>
#include <OgreColourValue.h>
#include <OgreHighLevelGpuProgram.h>
#include <extern/shiny/Main/Factory.hpp>
#include <components/nifogre/ogrenifloader.hpp>
#include <osg/ref_ptr>
#include "../mwworld/weather.hpp" #include "../mwworld/weather.hpp"
namespace Ogre namespace osg
{
class Group;
class Node;
class Material;
}
namespace Resource
{ {
class RenderWindow;
class SceneNode;
class Camera;
class Viewport;
class SceneManager; class SceneManager;
class Entity;
class BillboardSet;
class TextureUnitState;
} }
namespace MWRender namespace MWRender
{ {
class BillboardObject : public sh::MaterialInstanceListener class AtmosphereUpdater;
{
public:
BillboardObject( const Ogre::String& textureName,
const float size,
const Ogre::Vector3& position,
Ogre::SceneNode* rootNode,
const std::string& material
);
void requestedConfiguration (sh::MaterialInstance* m, const std::string& configuration);
void createdConfiguration (sh::MaterialInstance* m, const std::string& configuration);
virtual ~BillboardObject() {}
void setColour(const Ogre::ColourValue& pColour);
void setPosition(const Ogre::Vector3& pPosition);
void setVisible(const bool visible);
void setRenderQueue(unsigned int id);
void setVisibilityFlags(int flags);
void setSize(const float size);
Ogre::Vector3 getPosition() const;
void setVisibility(const float visibility);
Ogre::SceneNode* getNode();
protected:
float mVisibility;
Ogre::ColourValue mColour;
Ogre::SceneNode* mNode;
sh::MaterialInstance* mMaterial;
Ogre::Entity* mEntity;
};
/*
* The moons need a seperate class because of their shader (which allows them to be partially transparent)
*/
class Moon : public BillboardObject
{
public:
Moon( const Ogre::String& textureName,
const float size,
const Ogre::Vector3& position,
Ogre::SceneNode* rootNode,
const std::string& material
);
virtual ~Moon() {}
enum Phase
{
Phase_New = 0,
Phase_WaxingCrescent,
Phase_WaxingHalf,
Phase_WaxingGibbous,
Phase_Full,
Phase_WaningGibbous,
Phase_WaningHalf,
Phase_WaningCrescent
};
enum Type
{
Type_Masser = 0,
Type_Secunda
};
void setPhase(const Phase& phase);
void setType(const Type& type);
unsigned int getPhaseInt() const;
private:
Type mType;
Phase mPhase;
};
class SkyManager class SkyManager
{ {
public: public:
SkyManager(Ogre::SceneNode* root, Ogre::Camera* pCamera); SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager);
~SkyManager(); ~SkyManager();
/// Attach weather particle effects to this scene node (should be the Camera's parent node)
void attachToNode(Ogre::SceneNode* sceneNode);
void update(float duration); void update(float duration);
void enable(); void setEnabled(bool enabled);
void disable();
void setHour (double hour); void setHour (double hour);
///< will be called even when sky is disabled. ///< will be called even when sky is disabled.
@ -143,8 +50,6 @@ namespace MWRender
void setWeather(const MWWorld::WeatherResult& weather); void setWeather(const MWWorld::WeatherResult& weather);
Ogre::SceneNode* getSunNode();
void sunEnable(); void sunEnable();
void sunDisable(); void sunDisable();
@ -153,7 +58,7 @@ namespace MWRender
void setStormDirection(const Ogre::Vector3& direction); void setStormDirection(const Ogre::Vector3& direction);
void setSunDirection(const Ogre::Vector3& direction, bool is_night); void setSunDirection(const osg::Vec3f& direction);
void setMasserDirection(const Ogre::Vector3& direction); void setMasserDirection(const Ogre::Vector3& direction);
@ -173,7 +78,6 @@ namespace MWRender
void setGlare(const float glare); void setGlare(const float glare);
void setGlareEnabled(bool enabled); void setGlareEnabled(bool enabled);
Ogre::Vector3 getRealSunPos();
private: private:
void create(); void create();
@ -182,6 +86,22 @@ namespace MWRender
void updateRain(float dt); void updateRain(float dt);
void clearRain(); void clearRain();
Resource::SceneManager* mSceneManager;
osg::ref_ptr<osg::Group> mRootNode;
osg::ref_ptr<osg::Node> mParticleEffect;
osg::ref_ptr<osg::Node> mCloudNode;
osg::ref_ptr<osg::Node> mAtmosphereDay;
osg::ref_ptr<osg::Node> mAtmosphereNight;
osg::ref_ptr<AtmosphereUpdater> mAtmosphereUpdater;
osg::ref_ptr<osg::PositionAttitudeTransform> mSunTransform;
bool mCreated; bool mCreated;
bool mMoonRed; bool mMoonRed;
@ -194,26 +114,6 @@ namespace MWRender
float mCloudAnimationTimer; float mCloudAnimationTimer;
BillboardObject* mSun;
BillboardObject* mSunGlare;
Moon* mMasser;
Moon* mSecunda;
Ogre::Camera* mCamera;
Ogre::SceneNode* mRootNode;
Ogre::SceneManager* mSceneMgr;
Ogre::SceneNode* mAtmosphereDay;
Ogre::SceneNode* mAtmosphereNight;
Ogre::SceneNode* mCloudNode;
std::vector<NifOgre::ObjectScenePtr> mObjects;
Ogre::SceneNode* mParticleNode;
NifOgre::ObjectScenePtr mParticle;
std::map<Ogre::SceneNode*, NifOgre::ObjectScenePtr> mRainModels;
float mRainTimer; float mRainTimer;
Ogre::Vector3 mStormDirection; Ogre::Vector3 mStormDirection;
@ -225,14 +125,12 @@ namespace MWRender
float mCloudOpacity; float mCloudOpacity;
float mCloudSpeed; float mCloudSpeed;
float mStarsOpacity; float mStarsOpacity;
Ogre::ColourValue mCloudColour; osg::Vec4f mCloudColour;
Ogre::ColourValue mSkyColour; osg::Vec4f mSkyColour;
Ogre::ColourValue mFogColour; osg::Vec4f mFogColour;
std::string mCurrentParticleEffect; std::string mCurrentParticleEffect;
Ogre::Light* mLightning;
float mRemainingTransitionTime; float mRemainingTransitionTime;
float mGlare; // target float mGlare; // target

View file

@ -1,5 +1,7 @@
#include "fallback.hpp" #include "fallback.hpp"
#include "boost/lexical_cast.hpp"
#include <boost/lexical_cast.hpp>
namespace MWWorld namespace MWWorld
{ {
Fallback::Fallback(const std::map<std::string,std::string>& fallback):mFallbackMap(fallback) Fallback::Fallback(const std::map<std::string,std::string>& fallback):mFallbackMap(fallback)
@ -39,11 +41,11 @@ namespace MWWorld
else else
return boost::lexical_cast<bool>(fallback); return boost::lexical_cast<bool>(fallback);
} }
Ogre::ColourValue Fallback::getFallbackColour(const std::string& fall) const osg::Vec4f Fallback::getFallbackColour(const std::string& fall) const
{ {
std::string sum=getFallbackString(fall); std::string sum=getFallbackString(fall);
if(sum.empty()) if(sum.empty())
return Ogre::ColourValue(0,0,0); return osg::Vec4f(0.f,0.f,0.f,1.f);
else else
{ {
std::string ret[3]; std::string ret[3];
@ -53,7 +55,7 @@ namespace MWWorld
else if (sum[i] != ' ') ret[j]+=sum[i]; else if (sum[i] != ' ') ret[j]+=sum[i];
} }
return Ogre::ColourValue(boost::lexical_cast<int>(ret[0])/255.f,boost::lexical_cast<int>(ret[1])/255.f,boost::lexical_cast<int>(ret[2])/255.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);
} }
} }
} }

View file

@ -4,7 +4,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include <OgreColourValue.h> #include <osg/Vec4f>
namespace MWWorld namespace MWWorld
{ {
@ -17,7 +17,7 @@ namespace MWWorld
float getFallbackFloat(const std::string& fall) const; float getFallbackFloat(const std::string& fall) const;
int getFallbackInt(const std::string& fall) const; int getFallbackInt(const std::string& fall) const;
bool getFallbackBool(const std::string& fall) const; bool getFallbackBool(const std::string& fall) const;
Ogre::ColourValue getFallbackColour(const std::string& fall) const; osg::Vec4f getFallbackColour(const std::string& fall) const;
}; };
} }
#endif #endif

View file

@ -13,16 +13,15 @@
#include "../mwsound/sound.hpp" #include "../mwsound/sound.hpp"
//#include "../mwrender/renderingmanager.hpp" #include "../mwrender/renderingmanager.hpp"
#include "../mwrender/sky.hpp"
#include "player.hpp" #include "player.hpp"
#include "esmstore.hpp" #include "esmstore.hpp"
#include "fallback.hpp" #include "fallback.hpp"
#include "cellstore.hpp" #include "cellstore.hpp"
using namespace Ogre;
using namespace MWWorld; using namespace MWWorld;
using namespace MWSound;
namespace namespace
{ {
@ -31,7 +30,7 @@ namespace
return x * (1-factor) + y * factor; return x * (1-factor) + y * factor;
} }
Ogre::ColourValue lerp (const Ogre::ColourValue& x, const Ogre::ColourValue& y, float factor) osg::Vec4f lerp (const osg::Vec4f& x, const osg::Vec4f& y, float factor)
{ {
return x * (1-factor) + y * factor; return x * (1-factor) + y * factor;
} }
@ -196,7 +195,7 @@ WeatherManager::~WeatherManager()
stopSounds(); stopSounds();
} }
void WeatherManager::setWeather(const String& weather, bool instant) void WeatherManager::setWeather(const std::string& weather, bool instant)
{ {
if (weather == mCurrentWeather && mNextWeather == "") if (weather == mCurrentWeather && mNextWeather == "")
{ {
@ -224,7 +223,7 @@ void WeatherManager::setWeather(const String& weather, bool instant)
mFirstUpdate = false; mFirstUpdate = false;
} }
void WeatherManager::setResult(const String& weatherType) void WeatherManager::setResult(const std::string& weatherType)
{ {
const Weather& current = mWeatherSettings[weatherType]; const Weather& current = mWeatherSettings[weatherType];
@ -387,8 +386,8 @@ void WeatherManager::update(float duration, bool paused)
const bool exterior = (world->isCellExterior() || world->isCellQuasiExterior()); const bool exterior = (world->isCellExterior() || world->isCellQuasiExterior());
if (!exterior) if (!exterior)
{ {
mRendering->skyDisable(); mRendering->setSkyEnabled(false);
mRendering->getSkyManager()->setLightningStrength(0.f); //mRendering->getSkyManager()->setLightningStrength(0.f);
stopSounds(); stopSounds();
return; return;
} }
@ -421,16 +420,16 @@ void WeatherManager::update(float duration, bool paused)
mStormDirection = (playerPos - redMountainPos); mStormDirection = (playerPos - redMountainPos);
mStormDirection.z = 0; mStormDirection.z = 0;
mRendering->getSkyManager()->setStormDirection(mStormDirection); //mRendering->getSkyManager()->setStormDirection(mStormDirection);
} }
mRendering->configureFog(mResult.mFogDepth, mResult.mFogColor); mRendering->configureFog(mResult.mFogDepth, mResult.mFogColor);
// disable sun during night // disable sun during night
if (mHour >= mNightStart || mHour <= mSunriseTime) //if (mHour >= mNightStart || mHour <= mSunriseTime)
mRendering->getSkyManager()->sunDisable(); //mRendering->getSkyManager()->sunDisable();
else //else
mRendering->getSkyManager()->sunEnable(); //mRendering->getSkyManager()->sunEnable();
// Update the sun direction. Run it east to west at a fixed angle from overhead. // Update the sun direction. Run it east to west at a fixed angle from overhead.
// The sun's speed at day and night may differ, since mSunriseTime and mNightStart // The sun's speed at day and night may differ, since mSunriseTime and mNightStart
@ -455,11 +454,11 @@ void WeatherManager::update(float duration, bool paused)
theta = M_PI * (adjustedHour - adjustedNightStart) / nightDuration; theta = M_PI * (adjustedHour - adjustedNightStart) / nightDuration;
} }
Vector3 final( osg::Vec3f final(
static_cast<float>(cos(theta)), static_cast<float>(cos(theta)),
-0.268f, // approx tan( -15 degrees ) -0.268f, // approx tan( -15 degrees )
static_cast<float>(sin(theta))); static_cast<float>(sin(theta)));
mRendering->setSunDirection( final, is_night ); mRendering->setSunDirection( final * -1 );
} }
/* /*
@ -484,20 +483,20 @@ void WeatherManager::update(float duration, bool paused)
if (moonHeight != 0) if (moonHeight != 0)
{ {
int facing = (moonHeight <= 1) ? 1 : -1; int facing = (moonHeight <= 1) ? 1 : -1;
Vector3 masser( osg::Vec3f masser(
(moonHeight - 1) * facing, (moonHeight - 1) * facing,
(1 - moonHeight) * facing, (1 - moonHeight) * facing,
moonHeight); moonHeight);
Vector3 secunda( osg::Vec3f secunda(
(moonHeight - 1) * facing * 1.25f, (moonHeight - 1) * facing * 1.25f,
(1 - moonHeight) * facing * 0.8f, (1 - moonHeight) * facing * 0.8f,
moonHeight); moonHeight);
mRendering->getSkyManager()->setMasserDirection(masser); //mRendering->getSkyManager()->setMasserDirection(masser);
mRendering->getSkyManager()->setSecundaDirection(secunda); //mRendering->getSkyManager()->setSecundaDirection(secunda);
mRendering->getSkyManager()->masserEnable(); //mRendering->getSkyManager()->masserEnable();
mRendering->getSkyManager()->secundaEnable(); //mRendering->getSkyManager()->secundaEnable();
float angle = (1-moonHeight) * 90.f * facing; float angle = (1-moonHeight) * 90.f * facing;
float masserHourFade = calculateHourFade("Masser"); float masserHourFade = calculateHourFade("Masser");
@ -508,13 +507,13 @@ void WeatherManager::update(float duration, bool paused)
masserAngleFade *= masserHourFade; masserAngleFade *= masserHourFade;
secundaAngleFade *= secundaHourFade; secundaAngleFade *= secundaHourFade;
mRendering->getSkyManager()->setMasserFade(masserAngleFade); //mRendering->getSkyManager()->setMasserFade(masserAngleFade);
mRendering->getSkyManager()->setSecundaFade(secundaAngleFade); //mRendering->getSkyManager()->setSecundaFade(secundaAngleFade);
} }
else else
{ {
mRendering->getSkyManager()->masserDisable(); //mRendering->getSkyManager()->masserDisable();
mRendering->getSkyManager()->secundaDisable(); //mRendering->getSkyManager()->secundaDisable();
} }
if (!paused) if (!paused)
@ -540,13 +539,13 @@ void WeatherManager::update(float duration, bool paused)
} }
mThunderFlash -= duration; mThunderFlash -= duration;
if (mThunderFlash > 0) //if (mThunderFlash > 0)
mRendering->getSkyManager()->setLightningStrength( mThunderFlash / mThunderThreshold ); //mRendering->getSkyManager()->setLightningStrength( mThunderFlash / mThunderThreshold );
else //else
{ {
mThunderChanceNeeded = static_cast<float>(OEngine::Misc::Rng::rollDice(100)); mThunderChanceNeeded = static_cast<float>(OEngine::Misc::Rng::rollDice(100));
mThunderChance = 0; mThunderChance = 0;
mRendering->getSkyManager()->setLightningStrength( 0.f ); //mRendering->getSkyManager()->setLightningStrength( 0.f );
} }
} }
else else
@ -557,19 +556,19 @@ void WeatherManager::update(float duration, bool paused)
{ {
mThunderFlash = mThunderThreshold; mThunderFlash = mThunderThreshold;
mRendering->getSkyManager()->setLightningStrength( mThunderFlash / mThunderThreshold ); //mRendering->getSkyManager()->setLightningStrength( mThunderFlash / mThunderThreshold );
mThunderSoundDelay = 0.25; mThunderSoundDelay = 0.25;
} }
} }
} }
else //else
mRendering->getSkyManager()->setLightningStrength(0.f); //mRendering->getSkyManager()->setLightningStrength(0.f);
} }
mRendering->setAmbientColour(mResult.mAmbientColor); mRendering->setAmbientColour(mResult.mAmbientColor);
mRendering->sunEnable(false); //mRendering->sunEnable(false);
mRendering->setSunColour(mResult.mSunColor); mRendering->setSunColour(mResult.mSunColor);
mRendering->getSkyManager()->setWeather(mResult); mRendering->getSkyManager()->setWeather(mResult);
@ -850,3 +849,8 @@ Ogre::Vector3 WeatherManager::getStormDirection() const
{ {
return mStormDirection; return mStormDirection;
} }
void WeatherManager::advanceTime(double hours)
{
mTimePassed += hours*3600;
}

View file

@ -6,6 +6,7 @@
#include <OgreColourValue.h> #include <OgreColourValue.h>
#include <OgreVector3.h> #include <OgreVector3.h>
#include <osg/Vec4f>
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
@ -37,15 +38,15 @@ namespace MWWorld
std::string mNextCloudTexture; std::string mNextCloudTexture;
float mCloudBlendFactor; float mCloudBlendFactor;
Ogre::ColourValue mFogColor; osg::Vec4f mFogColor;
Ogre::ColourValue mAmbientColor; osg::Vec4f mAmbientColor;
Ogre::ColourValue mSkyColor; osg::Vec4f mSkyColor;
Ogre::ColourValue mSunColor; osg::Vec4f mSunColor;
Ogre::ColourValue mSunDiscColor; osg::Vec4f mSunDiscColor;
float mFogDepth; float mFogDepth;
@ -80,25 +81,25 @@ namespace MWWorld
std::string mCloudTexture; std::string mCloudTexture;
// Sky (atmosphere) colors // Sky (atmosphere) colors
Ogre::ColourValue mSkySunriseColor, osg::Vec4f mSkySunriseColor,
mSkyDayColor, mSkyDayColor,
mSkySunsetColor, mSkySunsetColor,
mSkyNightColor; mSkyNightColor;
// Fog colors // Fog colors
Ogre::ColourValue mFogSunriseColor, osg::Vec4f mFogSunriseColor,
mFogDayColor, mFogDayColor,
mFogSunsetColor, mFogSunsetColor,
mFogNightColor; mFogNightColor;
// Ambient lighting colors // Ambient lighting colors
Ogre::ColourValue mAmbientSunriseColor, osg::Vec4f mAmbientSunriseColor,
mAmbientDayColor, mAmbientDayColor,
mAmbientSunsetColor, mAmbientSunsetColor,
mAmbientNightColor; mAmbientNightColor;
// Sun (directional) lighting colors // Sun (directional) lighting colors
Ogre::ColourValue mSunSunriseColor, osg::Vec4f mSunSunriseColor,
mSunDayColor, mSunDayColor,
mSunSunsetColor, mSunSunsetColor,
mSunNightColor; mSunNightColor;
@ -108,7 +109,7 @@ namespace MWWorld
mLandFogNightDepth; mLandFogNightDepth;
// Color modulation for the sun itself during sunset (not completely sure) // Color modulation for the sun itself during sunset (not completely sure)
Ogre::ColourValue mSunDiscSunsetColor; osg::Vec4f mSunDiscSunsetColor;
// Duration of weather transition (in days) // Duration of weather transition (in days)
float mTransitionDelta; float mTransitionDelta;
@ -185,10 +186,7 @@ namespace MWWorld
Ogre::Vector3 getStormDirection() const; Ogre::Vector3 getStormDirection() const;
void advanceTime(double hours) void advanceTime(double hours);
{
mTimePassed += hours*3600;
}
unsigned int getWeatherID() const; unsigned int getWeatherID() const;

View file

@ -131,18 +131,16 @@ namespace MWWorld
void World::adjustSky() void World::adjustSky()
{ {
#if 0
if (mSky && (isCellExterior() || isCellQuasiExterior())) if (mSky && (isCellExterior() || isCellQuasiExterior()))
{ {
mRendering->skySetHour (mGlobalVariables["gamehour"].getFloat()); //mRendering->skySetHour (mGlobalVariables["gamehour"].getFloat());
mRendering->skySetDate (mGlobalVariables["day"].getInteger(), //mRendering->skySetDate (mGlobalVariables["day"].getInteger(),
mGlobalVariables["month"].getInteger()); // mGlobalVariables["month"].getInteger());
mRendering->skyEnable(); mRendering->setSkyEnabled(true);
} }
else else
mRendering->skyDisable(); mRendering->setSkyEnabled(false);
#endif
} }
World::World ( World::World (
@ -171,7 +169,7 @@ namespace MWWorld
//mPhysEngine->setSceneManager(renderer.getScene()); //mPhysEngine->setSceneManager(renderer.getScene());
//mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback); mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback);
mEsm.resize(contentFiles.size()); mEsm.resize(contentFiles.size());
Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen(); Loading::Listener* listener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
@ -267,9 +265,9 @@ namespace MWWorld
// mPhysics->toggleCollisionMode(); // mPhysics->toggleCollisionMode();
// we don't want old weather to persist on a new game // we don't want old weather to persist on a new game
//delete mWeatherManager; delete mWeatherManager;
//mWeatherManager = 0; mWeatherManager = 0;
//mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback); mWeatherManager = new MWWorld::WeatherManager(mRendering,&mFallback);
if (!mStartupScript.empty()) if (!mStartupScript.empty())
MWBase::Environment::get().getWindowManager()->executeInConsole(mStartupScript); MWBase::Environment::get().getWindowManager()->executeInConsole(mStartupScript);
@ -277,7 +275,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();
@ -348,7 +346,7 @@ namespace MWWorld
mCells.write (writer, progress); mCells.write (writer, progress);
mGlobalVariables.write (writer, progress); mGlobalVariables.write (writer, progress);
mPlayer->write (writer, progress); mPlayer->write (writer, progress);
//mWeatherManager->write (writer, progress); mWeatherManager->write (writer, progress);
#if 0 #if 0
mProjectileManager->write (writer, progress); mProjectileManager->write (writer, progress);
#endif #endif
@ -378,7 +376,7 @@ namespace MWWorld
if (!mStore.readRecord (reader, type) && if (!mStore.readRecord (reader, type) &&
!mGlobalVariables.readRecord (reader, type) && !mGlobalVariables.readRecord (reader, type) &&
!mPlayer->readRecord (reader, type) && !mPlayer->readRecord (reader, type) &&
//!mWeatherManager->readRecord (reader, type) && !mWeatherManager->readRecord (reader, type) &&
!mCells.readRecord (reader, type, contentFileMap) !mCells.readRecord (reader, type, contentFileMap)
#if 0 #if 0
&& !mProjectileManager->readRecord (reader, type) && !mProjectileManager->readRecord (reader, type)
@ -479,7 +477,7 @@ namespace MWWorld
// Must be cleared before mRendering is destroyed // Must be cleared before mRendering is destroyed
mProjectileManager->clear(); mProjectileManager->clear();
#endif #endif
//delete mWeatherManager; delete mWeatherManager;
delete mWorldScene; delete mWorldScene;
delete mRendering; delete mRendering;
//delete mPhysics; //delete mPhysics;
@ -819,7 +817,7 @@ namespace MWWorld
{ {
MWBase::Environment::get().getMechanicsManager()->advanceTime(static_cast<float>(hours * 3600)); MWBase::Environment::get().getMechanicsManager()->advanceTime(static_cast<float>(hours * 3600));
//mWeatherManager->advanceTime (hours); mWeatherManager->advanceTime (hours);
hours += mGlobalVariables["gamehour"].getFloat(); hours += mGlobalVariables["gamehour"].getFloat();
@ -845,7 +843,7 @@ namespace MWWorld
//mRendering->skySetHour (hour); //mRendering->skySetHour (hour);
//mWeatherManager->setHour(static_cast<float>(hour)); mWeatherManager->setHour(static_cast<float>(hour));
if (days>0) if (days>0)
setDay (days + mGlobalVariables["day"].getInteger()); setDay (days + mGlobalVariables["day"].getInteger());
@ -1604,11 +1602,11 @@ namespace MWWorld
void World::update (float duration, bool paused) void World::update (float duration, bool paused)
{ {
/*
if (mGoToJail && !paused) if (mGoToJail && !paused)
goToJail(); goToJail();
updateWeather(duration, paused); updateWeather(duration, paused);
/*
if (!paused) if (!paused)
doPhysics (duration); doPhysics (duration);
@ -1731,17 +1729,17 @@ namespace MWWorld
int World::getCurrentWeather() const int World::getCurrentWeather() const
{ {
return 0;//mWeatherManager->getWeatherID(); return mWeatherManager->getWeatherID();
} }
void World::changeWeather(const std::string& region, const unsigned int id) void World::changeWeather(const std::string& region, const unsigned int id)
{ {
//mWeatherManager->changeWeather(region, id); mWeatherManager->changeWeather(region, id);
} }
void World::modRegion(const std::string &regionid, const std::vector<char> &chances) void World::modRegion(const std::string &regionid, const std::vector<char> &chances)
{ {
//mWeatherManager->modRegion(regionid, chances); mWeatherManager->modRegion(regionid, chances);
} }
Ogre::Vector2 World::getNorthVector (CellStore* cell) Ogre::Vector2 World::getNorthVector (CellStore* cell)
@ -2975,10 +2973,10 @@ namespace MWWorld
if (mPlayer->wasTeleported()) if (mPlayer->wasTeleported())
{ {
mPlayer->setTeleported(false); mPlayer->setTeleported(false);
//mWeatherManager->switchToNextWeather(true); mWeatherManager->switchToNextWeather(true);
} }
//mWeatherManager->update(duration, paused); mWeatherManager->update(duration, paused);
} }
struct AddDetectedReference struct AddDetectedReference

View file

@ -81,7 +81,7 @@ namespace MWWorld
MWWorld::Fallback mFallback; MWWorld::Fallback mFallback;
MWRender::RenderingManager* mRendering; MWRender::RenderingManager* mRendering;
//MWWorld::WeatherManager* mWeatherManager; MWWorld::WeatherManager* mWeatherManager;
MWWorld::Scene *mWorldScene; MWWorld::Scene *mWorldScene;
MWWorld::Player *mPlayer; MWWorld::Player *mPlayer;

View file

@ -39,7 +39,7 @@ add_component_dir (resource
) )
add_component_dir (sceneutil add_component_dir (sceneutil
clone attach lightmanager visitor util clone attach lightmanager visitor util statesetcontroller
) )
add_component_dir (nif add_component_dir (nif

View file

@ -142,4 +142,14 @@ namespace Resource
} }
} }
const VFS::Manager* SceneManager::getVFS() const
{
return mVFS;
}
Resource::TextureManager* SceneManager::getTextureManager()
{
return mTextureManager;
}
} }

View file

@ -55,6 +55,10 @@ namespace Resource
/// in cases where multiple contexts are used over the lifetime of the application. /// in cases where multiple contexts are used over the lifetime of the application.
void releaseGLObjects(osg::State* state); void releaseGLObjects(osg::State* state);
const VFS::Manager* getVFS() const;
Resource::TextureManager* getTextureManager();
private: private:
const VFS::Manager* mVFS; const VFS::Manager* mVFS;
Resource::TextureManager* mTextureManager; Resource::TextureManager* mTextureManager;

View file

@ -0,0 +1,31 @@
#include "statesetcontroller.hpp"
#include <osg/Node>
namespace SceneUtil
{
void StateSetController::operator()(osg::Node* node, osg::NodeVisitor* nv)
{
if (!mStateSets[0])
{
// first time setup
osg::StateSet* src = node->getOrCreateStateSet();
for (int i=0; i<2; ++i) // Using SHALLOW_COPY for StateAttributes, if users want to modify it is their responsibility to set a non-shared one first
// This can be done conveniently in user implementations of the setDefaults() method
{
mStateSets[i] = static_cast<osg::StateSet*>(osg::clone(src, osg::CopyOp::SHALLOW_COPY));
setDefaults(mStateSets[i]);
}
}
// Swap to make the StateSet in [0] writable, [1] is now the StateSet that was queued by the last frame
std::swap(mStateSets[0], mStateSets[1]);
node->setStateSet(mStateSets[0]);
apply(mStateSets[0], nv);
traverse(node, nv);
}
}

View file

@ -0,0 +1,39 @@
#ifndef OPENMW_COMPONENTS_SCENEUTIL_STATESETCONTROLLER_H
#define OPENMW_COMPONENTS_SCENEUTIL_STATESETCONTROLLER_H
#include <osg/NodeCallback>
namespace SceneUtil
{
/// @brief Implements efficient pre-frame updating of StateSets.
/// @par With a naive update there would be race conditions when the OSG draw thread of the last frame
/// queues up a StateSet that we want to modify for the next frame. To solve this we could set the StateSet to
/// DYNAMIC data variance but that would undo all the benefits of the threading model - having the cull and draw
/// traversals run in parallel can yield up to 200% framerates.
/// @par Race conditions are prevented using a "double buffering" scheme - we have two StateSets that take turns,
/// the first StateSet is the one we can write to, the second is the one currently in use by the draw traversal of the last frame.
/// After a frame is completed the places are swapped.
/// @par Must be set as UpdateCallback on a Node.
class StateSetController : public osg::NodeCallback
{
public:
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
protected:
/// Apply state - to override in derived classes
/// @note Due to the double buffering approach you *have* to apply all state
/// even if it has not changed since the last frame.
virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv) = 0;
/// Set default state - optionally override in derived classes
/// @par May be used e.g. to allocate StateAttributes.
virtual void setDefaults(osg::StateSet* stateset) {}
private:
osg::ref_ptr<osg::StateSet> mStateSets[2];
};
}
#endif