1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-27 12:35:46 +00:00

Fix several sky rendering bugs, maybe also #639

Added code to hide the moons, sun, and stars for certain weather
effects. Lightly refactored CelestialBody and derived classes. Fixed
moons switching phase at 24:00.
This commit is contained in:
slothlife 2015-08-04 21:07:42 -05:00
parent 06f170a8e1
commit ea2f88a355
4 changed files with 248 additions and 219 deletions

View File

@ -8,7 +8,6 @@
#include <osg/Depth> #include <osg/Depth>
#include <osg/Geometry> #include <osg/Geometry>
#include <osg/Material> #include <osg/Material>
#include <osg/PositionAttitudeTransform>
#include <osg/TexEnvCombine> #include <osg/TexEnvCombine>
#include <osg/TexMat> #include <osg/TexMat>
#include <osg/Version> #include <osg/Version>
@ -322,11 +321,12 @@ private:
int mMeshType; int mMeshType;
}; };
class CelestialBody // A base class for the sun and moons. Must be stored in an osg::ref_ptr due to being
// derived from osg::Referenced.
class CelestialBody : public SceneUtil::StateSetUpdater
{ {
public: public:
CelestialBody(osg::Group* parentNode, Resource::SceneManager* sceneManager, float scaleFactor = 1.f, int numUvSets=1) CelestialBody(osg::Group* parentNode, float scaleFactor = 1.f, int numUvSets=1)
: mSceneManager(sceneManager)
{ {
mGeode = new osg::Geode; mGeode = new osg::Geode;
osg::ref_ptr<osg::Geometry> geom = createTexturedQuad(numUvSets); osg::ref_ptr<osg::Geometry> geom = createTexturedQuad(numUvSets);
@ -336,42 +336,85 @@ public:
mTransform->addChild(mGeode); mTransform->addChild(mGeode);
parentNode->addChild(mTransform); parentNode->addChild(mTransform);
mGeode->addUpdateCallback(this);
} }
void setDirection(const osg::Vec3f& direction) virtual ~CelestialBody()
{ {
osg::Vec3f normalizedDirection = direction / direction.length(); mGeode->removeUpdateCallback(this);
mTransform->setPosition(normalizedDirection*1000.f);
osg::Quat quat;
quat.makeRotate(osg::Vec3f(0,0,1), normalizedDirection);
mTransform->setAttitude(quat);
} }
virtual void adjustTransparency(const float ratio) = 0;
void setVisible(bool visible) void setVisible(bool visible)
{ {
mTransform->setNodeMask(visible ? ~0 : 0); mTransform->setNodeMask(visible ? ~0 : 0);
} }
protected: protected:
static const float mDistance;
osg::ref_ptr<osg::PositionAttitudeTransform> mTransform; osg::ref_ptr<osg::PositionAttitudeTransform> mTransform;
osg::ref_ptr<osg::Geode> mGeode; osg::ref_ptr<osg::Geode> mGeode;
Resource::SceneManager* mSceneManager;
}; };
const float CelestialBody::mDistance = 1000.0f;
class Sun : public CelestialBody class Sun : public CelestialBody
{ {
public: public:
Sun(osg::Group* parentNode, Resource::SceneManager* sceneManager) Sun(osg::Group* parentNode, Resource::TextureManager& textureManager)
: CelestialBody(parentNode, sceneManager, 1.f, 1) : CelestialBody(parentNode, 1.0f, 1)
, mColor(1.0f, 1.0f, 1.0f, 1.0f)
, mDummyTexture(textureManager.getWarningTexture())
{ {
osg::ref_ptr<osg::Texture2D> tex = mSceneManager->getTextureManager()->getTexture2D("textures/tx_sun_05.dds", osg::ref_ptr<osg::Texture2D> tex = textureManager.getTexture2D("textures/tx_sun_05.dds",
osg::Texture::CLAMP, osg::Texture::CLAMP); osg::Texture::CLAMP,
osg::Texture::CLAMP);
mTransform->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON); mTransform->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
mTransform->getOrCreateStateSet()->setAttributeAndModes(createUnlitMaterial(), osg::StateAttribute::ON); mTransform->getOrCreateStateSet()->setAttributeAndModes(createUnlitMaterial(), osg::StateAttribute::ON);
} }
virtual void setDefaults(osg::StateSet* stateset)
{
osg::ref_ptr<osg::TexEnvCombine> texEnv(new osg::TexEnvCombine);
texEnv->setCombine_Alpha(osg::TexEnvCombine::MODULATE);
texEnv->setSource0_Alpha(osg::TexEnvCombine::PREVIOUS);
texEnv->setSource1_Alpha(osg::TexEnvCombine::CONSTANT);
texEnv->setCombine_RGB(osg::TexEnvCombine::REPLACE);
texEnv->setSource0_RGB(osg::TexEnvCombine::PREVIOUS);
texEnv->setConstantColor(osg::Vec4f(1.0f, 1.0f, 1.0f, 1.0f));
stateset->setTextureAttributeAndModes(1, mDummyTexture, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
stateset->setTextureAttributeAndModes(1, texEnv, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
}
virtual void apply(osg::StateSet* stateset, osg::NodeVisitor*)
{
osg::TexEnvCombine* texEnv = static_cast<osg::TexEnvCombine*>(stateset->getTextureAttribute(1, osg::StateAttribute::TEXENV));
texEnv->setConstantColor(mColor);
}
virtual void adjustTransparency(const float ratio)
{
mColor.a() = ratio;
}
void setDirection(const osg::Vec3f& direction)
{
osg::Vec3f normalizedDirection = direction / direction.length();
mTransform->setPosition(normalizedDirection * mDistance);
osg::Quat quat;
quat.makeRotate(osg::Vec3f(0.0f, 0.0f, 1.0f), normalizedDirection);
mTransform->setAttitude(quat);
}
private:
osg::Vec4f mColor;
osg::ref_ptr<osg::Texture2D> mDummyTexture;
}; };
class Moon : public CelestialBody class Moon : public CelestialBody
@ -383,93 +426,19 @@ public:
Type_Secunda Type_Secunda
}; };
Moon(osg::Group* parentNode, Resource::SceneManager* sceneManager, float scaleFactor, Type type) Moon(osg::Group* parentNode, Resource::TextureManager& textureManager, float scaleFactor, Type type)
: CelestialBody(parentNode, sceneManager, scaleFactor, 2) : CelestialBody(parentNode, scaleFactor, 2)
, mTextureManager(textureManager)
, mType(type) , mType(type)
, mPhase(MoonState::Phase_Unspecified) , mPhase(MoonState::Phase_Unspecified)
, mTransparency(1.0f)
, mShadowBlend(1.0f)
, mMoonColor(1.0f, 1.0f, 1.0f, 1.0f)
{ {
mUpdater = new MoonUpdater;
mGeode->addUpdateCallback(mUpdater);
setPhase(MoonState::Phase_Full); setPhase(MoonState::Phase_Full);
setVisible(true); setVisible(true);
} }
void setState(const MoonState& state)
{
float radsX = ((state.mRotationFromHorizon) * M_PI) / 180.0f;
float radsZ = ((state.mRotationFromNorth) * M_PI) / 180.0f;
osg::Quat rotX(radsX, osg::Vec3f(1.0f, 0.0f, 0.0f));
osg::Quat rotZ(radsZ, osg::Vec3f(0.0f, 0.0f, 1.0f));
osg::Vec3f direction = rotX * rotZ * osg::Vec3f(0.0f, 1.0f, 0.0f);
mTransform->setPosition(direction * 1000.0f);
// The moon quad is initially oriented facing down, so we need to offset its X-axis
// rotation to rotate it to face the camera when sitting at the horizon.
osg::Quat attX((-M_PI / 2.0f) + radsX, osg::Vec3f(1,0,0));
mTransform->setAttitude(attX * rotZ);
setPhase(state.mPhase);
setTransparency(state.mMoonAlpha);
setShadowBlend(state.mShadowBlend);
}
void setTextures(const std::string& phaseTex, const std::string& circleTex)
{
osg::ref_ptr<osg::Texture2D> phaseTexPtr = mSceneManager->getTextureManager()->getTexture2D(phaseTex,
osg::Texture::CLAMP, osg::Texture::CLAMP);
osg::ref_ptr<osg::Texture2D> circleTexPtr = mSceneManager->getTextureManager()->getTexture2D(circleTex,
osg::Texture::CLAMP, osg::Texture::CLAMP);
mUpdater->setTextures(phaseTexPtr, circleTexPtr);
}
void setPhase(const MoonState::Phase& phase)
{
if (mPhase == phase)
return;
mPhase = phase;
std::string textureName = "textures/tx_";
if (mType == Moon::Type_Secunda) textureName += "secunda_";
else textureName += "masser_";
if (phase == MoonState::Phase_New) textureName += "new";
else if (phase == MoonState::Phase_WaxingCrescent) textureName += "one_wax";
else if (phase == MoonState::Phase_FirstQuarter) textureName += "half_wax";
else if (phase == MoonState::Phase_WaxingGibbous) textureName += "three_wax";
else if (phase == MoonState::Phase_WaningCrescent) textureName += "one_wan";
else if (phase == MoonState::Phase_ThirdQuarter) textureName += "half_wan";
else if (phase == MoonState::Phase_WaningGibbous) textureName += "three_wan";
else if (phase == MoonState::Phase_Full) textureName += "full";
textureName += ".dds";
if (mType == Moon::Type_Secunda)
setTextures(textureName, "textures/tx_mooncircle_full_s.dds");
else
setTextures(textureName, "textures/tx_mooncircle_full_m.dds");
}
void setType(const Type& type)
{
mType = type;
}
class MoonUpdater : public SceneUtil::StateSetUpdater
{
public:
MoonUpdater()
: mTransparency(1.0f)
, mShadowBlend(1.0f)
, mMoonColor(1,1,1,1)
{
}
virtual void setDefaults(osg::StateSet *stateset) virtual void setDefaults(osg::StateSet *stateset)
{ {
stateset->setTextureAttributeAndModes(0, mPhaseTex, osg::StateAttribute::ON); stateset->setTextureAttributeAndModes(0, mPhaseTex, osg::StateAttribute::ON);
@ -503,14 +472,30 @@ public:
texEnv2->setConstantColor(osg::Vec4f(mAtmosphereColor.x(), mAtmosphereColor.y(), mAtmosphereColor.z(), mTransparency)); texEnv2->setConstantColor(osg::Vec4f(mAtmosphereColor.x(), mAtmosphereColor.y(), mAtmosphereColor.z(), mTransparency));
} }
void setTransparency(const float ratio) virtual void adjustTransparency(const float ratio)
{ {
mTransparency = ratio; mTransparency *= ratio;
} }
void setShadowBlend(const float blendFactor) void setState(const MoonState& state)
{ {
mShadowBlend = blendFactor; float radsX = ((state.mRotationFromHorizon) * M_PI) / 180.0f;
float radsZ = ((state.mRotationFromNorth) * M_PI) / 180.0f;
osg::Quat rotX(radsX, osg::Vec3f(1.0f, 0.0f, 0.0f));
osg::Quat rotZ(radsZ, osg::Vec3f(0.0f, 0.0f, 1.0f));
osg::Vec3f direction = rotX * rotZ * osg::Vec3f(0.0f, 1.0f, 0.0f);
mTransform->setPosition(direction * mDistance);
// The moon quad is initially oriented facing down, so we need to offset its X-axis
// rotation to rotate it to face the camera when sitting at the horizon.
osg::Quat attX((-M_PI / 2.0f) + radsX, osg::Vec3f(1.0f, 0.0f, 0.0f));
mTransform->setAttitude(attX * rotZ);
setPhase(state.mPhase);
mTransparency = state.mMoonAlpha;
mShadowBlend = state.mShadowBlend;
} }
void setAtmosphereColor(const osg::Vec4f& color) void setAtmosphereColor(const osg::Vec4f& color)
@ -518,46 +503,9 @@ public:
mAtmosphereColor = color; mAtmosphereColor = color;
} }
void setMoonColor(const osg::Vec4f& color)
{
mMoonColor = color;
}
void setTextures(osg::ref_ptr<osg::Texture2D> phaseTex, osg::ref_ptr<osg::Texture2D> circleTex)
{
mPhaseTex = phaseTex;
mCircleTex = circleTex;
reset();
}
private:
float mTransparency;
float mShadowBlend;
osg::Vec4f mAtmosphereColor;
osg::Vec4f mMoonColor;
osg::ref_ptr<osg::Texture2D> mPhaseTex;
osg::ref_ptr<osg::Texture2D> mCircleTex;
};
void setAtmosphereColor(const osg::Vec4f& color)
{
mUpdater->setAtmosphereColor(color);
}
void setColor(const osg::Vec4f& color) void setColor(const osg::Vec4f& color)
{ {
mUpdater->setMoonColor(color); mMoonColor = color;
}
void setTransparency(const float ratio)
{
mUpdater->setTransparency(ratio);
}
void setShadowBlend(const float blendFactor)
{
mUpdater->setShadowBlend(blendFactor);
} }
unsigned int getPhaseInt() const unsigned int getPhaseInt() const
@ -574,9 +522,52 @@ public:
} }
private: private:
Resource::TextureManager& mTextureManager;
Type mType; Type mType;
MoonState::Phase mPhase; MoonState::Phase mPhase;
osg::ref_ptr<MoonUpdater> mUpdater; float mTransparency;
float mShadowBlend;
osg::Vec4f mAtmosphereColor;
osg::Vec4f mMoonColor;
osg::ref_ptr<osg::Texture2D> mPhaseTex;
osg::ref_ptr<osg::Texture2D> mCircleTex;
void setTextures(const std::string& phaseTex, const std::string& circleTex)
{
mPhaseTex = mTextureManager.getTexture2D(phaseTex, osg::Texture::CLAMP, osg::Texture::CLAMP);
mCircleTex = mTextureManager.getTexture2D(circleTex, osg::Texture::CLAMP, osg::Texture::CLAMP);
reset();
}
void setPhase(const MoonState::Phase& phase)
{
if (mPhase == phase)
return;
mPhase = phase;
std::string textureName = "textures/tx_";
if (mType == Moon::Type_Secunda) textureName += "secunda_";
else textureName += "masser_";
if (phase == MoonState::Phase_New) textureName += "new";
else if (phase == MoonState::Phase_WaxingCrescent) textureName += "one_wax";
else if (phase == MoonState::Phase_FirstQuarter) textureName += "half_wax";
else if (phase == MoonState::Phase_WaxingGibbous) textureName += "three_wax";
else if (phase == MoonState::Phase_WaningCrescent) textureName += "one_wan";
else if (phase == MoonState::Phase_ThirdQuarter) textureName += "half_wan";
else if (phase == MoonState::Phase_WaningGibbous) textureName += "three_wan";
else if (phase == MoonState::Phase_Full) textureName += "full";
textureName += ".dds";
if (mType == Moon::Type_Secunda)
setTextures(textureName, "textures/tx_mooncircle_full_s.dds");
else
setTextures(textureName, "textures/tx_mooncircle_full_m.dds");
}
}; };
SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager) SkyManager::SkyManager(osg::Group* parentNode, Resource::SceneManager* sceneManager)
@ -641,11 +632,11 @@ void SkyManager::create()
mAtmosphereNightUpdater = new AtmosphereNightUpdater(mSceneManager->getTextureManager()); mAtmosphereNightUpdater = new AtmosphereNightUpdater(mSceneManager->getTextureManager());
atmosphereNight->addUpdateCallback(mAtmosphereNightUpdater); atmosphereNight->addUpdateCallback(mAtmosphereNightUpdater);
mSun.reset(new Sun(mRootNode, mSceneManager)); mSun = new Sun(mRootNode, *mSceneManager->getTextureManager());
const MWWorld::Fallback* fallback=MWBase::Environment::get().getWorld()->getFallback(); const MWWorld::Fallback* fallback=MWBase::Environment::get().getWorld()->getFallback();
mMasser.reset(new Moon(mRootNode, mSceneManager, fallback->getFallbackFloat("Moons_Masser_Size")/125, Moon::Type_Masser)); mMasser = new Moon(mRootNode, *mSceneManager->getTextureManager(), fallback->getFallbackFloat("Moons_Masser_Size")/125, Moon::Type_Masser);
mSecunda.reset(new Moon(mRootNode, mSceneManager, fallback->getFallbackFloat("Moons_Secunda_Size")/125, Moon::Type_Secunda)); mSecunda = new Moon(mRootNode, *mSceneManager->getTextureManager(), fallback->getFallbackFloat("Moons_Secunda_Size")/125, Moon::Type_Secunda);
mCloudNode = new osg::PositionAttitudeTransform; mCloudNode = new osg::PositionAttitudeTransform;
mRootNode->addChild(mCloudNode); mRootNode->addChild(mCloudNode);
@ -970,7 +961,7 @@ void SkyManager::updateRainParameters()
} }
} }
void SkyManager::setWeather(const MWWorld::WeatherResult& weather) void SkyManager::setWeather(const WeatherResult& weather)
{ {
if (!mCreated) return; if (!mCreated) return;
@ -1087,9 +1078,14 @@ void SkyManager::setWeather(const MWWorld::WeatherResult& weather)
mCloudSpeed = weather.mCloudSpeed; mCloudSpeed = weather.mCloudSpeed;
if (weather.mNight && mStarsOpacity != weather.mNightFade) mMasser->adjustTransparency(weather.mCelestialBodyTransparency);
mSecunda->adjustTransparency(weather.mCelestialBodyTransparency);
mSun->adjustTransparency(weather.mCelestialBodyTransparency);
float nextStarsOpacity = weather.mNightFade * weather.mCelestialBodyTransparency;
if(weather.mNight && mStarsOpacity != nextStarsOpacity)
{ {
mStarsOpacity = weather.mNightFade; mStarsOpacity = nextStarsOpacity;
mAtmosphereNightUpdater->setFade(mStarsOpacity); mAtmosphereNightUpdater->setFade(mStarsOpacity);
} }

View File

@ -1,9 +1,11 @@
#ifndef OPENMW_MWRENDER_SKY_H #ifndef OPENMW_MWRENDER_SKY_H
#define OPENMW_MWRENDER_SKY_H #define OPENMW_MWRENDER_SKY_H
#include <osg/ref_ptr> #include <string>
#include "../mwworld/weather.hpp" #include <osg/ref_ptr>
#include <osg/Vec4f>
#include <osg/PositionAttitudeTransform>
namespace osg namespace osg
{ {
@ -33,6 +35,50 @@ namespace MWRender
class RainFader; class RainFader;
class AlphaFader; class AlphaFader;
struct WeatherResult
{
std::string mCloudTexture;
std::string mNextCloudTexture;
float mCloudBlendFactor;
osg::Vec4f mFogColor;
osg::Vec4f mAmbientColor;
osg::Vec4f mSkyColor;
osg::Vec4f mSunColor;
osg::Vec4f mSunDiscColor;
float mFogDepth;
float mWindSpeed;
float mCloudSpeed;
float mCloudOpacity;
float mGlareView;
bool mNight; // use night skybox
float mNightFade; // fading factor for night skybox
bool mIsStorm;
std::string mAmbientLoopSoundID;
float mAmbientSoundVolume;
std::string mParticleEffect;
std::string mRainEffect;
float mEffectFade;
float mRainSpeed;
float mRainFrequency;
float mCelestialBodyTransparency;
};
struct MoonState struct MoonState
{ {
enum Phase enum Phase
@ -82,7 +128,7 @@ namespace MWRender
void setMoonColour (bool red); void setMoonColour (bool red);
///< change Secunda colour to red ///< change Secunda colour to red
void setWeather(const MWWorld::WeatherResult& weather); void setWeather(const WeatherResult& weather);
void sunEnable(); void sunEnable();
@ -133,9 +179,9 @@ namespace MWRender
osg::ref_ptr<AtmosphereUpdater> mAtmosphereUpdater; osg::ref_ptr<AtmosphereUpdater> mAtmosphereUpdater;
std::auto_ptr<Sun> mSun; osg::ref_ptr<Sun> mSun;
std::auto_ptr<Moon> mMasser; osg::ref_ptr<Moon> mMasser;
std::auto_ptr<Moon> mSecunda; osg::ref_ptr<Moon> mSecunda;
osg::ref_ptr<osg::Group> mRainNode; osg::ref_ptr<osg::Group> mRainNode;
osg::ref_ptr<osgParticle::ParticleSystem> mRainParticleSystem; osg::ref_ptr<osgParticle::ParticleSystem> mRainParticleSystem;

View File

@ -61,7 +61,7 @@ MWRender::MoonState MoonModel::calculateState(unsigned int daysPassed, float gam
{ {
rotationFromHorizon, rotationFromHorizon,
mAxisOffset, // Reverse engineered from Morrowind's scene graph rotation matrices. mAxisOffset, // Reverse engineered from Morrowind's scene graph rotation matrices.
static_cast<MWRender::MoonState::Phase>(phase(daysPassed)), static_cast<MWRender::MoonState::Phase>(phase(daysPassed, gameHour)),
shadowBlend(rotationFromHorizon), shadowBlend(rotationFromHorizon),
earlyMoonShadowAlpha(rotationFromHorizon) * hourlyAlpha(gameHour) earlyMoonShadowAlpha(rotationFromHorizon) * hourlyAlpha(gameHour)
}; };
@ -130,11 +130,16 @@ inline float MoonModel::rotation(float hours) const
return 15.0f * mSpeed * hours; return 15.0f * mSpeed * hours;
} }
inline unsigned int MoonModel::phase(unsigned int daysPassed) const inline unsigned int MoonModel::phase(unsigned int daysPassed, float gameHour) const
{ {
// Morrowind starts with a full moon on 16 Last Seed and then begins to wane 17 Last Seed, working on 3 day phase cycle. // Morrowind starts with a full moon on 16 Last Seed and then begins to wane 17 Last Seed, working on 3 day phase cycle.
// Note: this is an internal helper, and as such we don't want to return MWRender::MoonState::Phase since we can't // Note: this is an internal helper, and as such we don't want to return MWRender::MoonState::Phase since we can't
// forward declare it (C++11 strongly typed enums solve this). // forward declare it (C++11 strongly typed enums solve this).
// If the moon didn't rise yet today, use yesterday's moon phase.
if(gameHour < moonRiseHour(daysPassed))
return (daysPassed / 3) % 8;
else
return ((daysPassed + 1) / 3) % 8; return ((daysPassed + 1) / 3) % 8;
} }
@ -289,44 +294,54 @@ WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::F
//Weather //Weather
Weather clear; Weather clear;
clear.mObstructsCelestialBodies = false;
setFallbackWeather(clear,"clear"); setFallbackWeather(clear,"clear");
Weather cloudy; Weather cloudy;
cloudy.mObstructsCelestialBodies = false;
setFallbackWeather(cloudy,"cloudy"); setFallbackWeather(cloudy,"cloudy");
Weather foggy; Weather foggy;
foggy.mObstructsCelestialBodies = false;
setFallbackWeather(foggy,"foggy"); setFallbackWeather(foggy,"foggy");
Weather thunderstorm; Weather thunderstorm;
thunderstorm.mAmbientLoopSoundID = "rain heavy"; thunderstorm.mAmbientLoopSoundID = "rain heavy";
thunderstorm.mRainEffect = "meshes\\raindrop.nif"; thunderstorm.mRainEffect = "meshes\\raindrop.nif";
thunderstorm.mObstructsCelestialBodies = true;
setFallbackWeather(thunderstorm,"thunderstorm"); setFallbackWeather(thunderstorm,"thunderstorm");
Weather rain; Weather rain;
rain.mAmbientLoopSoundID = "rain"; rain.mAmbientLoopSoundID = "rain";
rain.mRainEffect = "meshes\\raindrop.nif"; rain.mRainEffect = "meshes\\raindrop.nif";
rain.mObstructsCelestialBodies = true;
setFallbackWeather(rain,"rain"); setFallbackWeather(rain,"rain");
Weather overcast; Weather overcast;
overcast.mObstructsCelestialBodies = true;
setFallbackWeather(overcast,"overcast"); setFallbackWeather(overcast,"overcast");
Weather ashstorm; Weather ashstorm;
ashstorm.mAmbientLoopSoundID = "ashstorm"; ashstorm.mAmbientLoopSoundID = "ashstorm";
ashstorm.mParticleEffect = "meshes\\ashcloud.nif"; ashstorm.mParticleEffect = "meshes\\ashcloud.nif";
ashstorm.mObstructsCelestialBodies = true;
setFallbackWeather(ashstorm,"ashstorm"); setFallbackWeather(ashstorm,"ashstorm");
Weather blight; Weather blight;
blight.mAmbientLoopSoundID = "blight"; blight.mAmbientLoopSoundID = "blight";
blight.mParticleEffect = "meshes\\blightcloud.nif"; blight.mParticleEffect = "meshes\\blightcloud.nif";
blight.mObstructsCelestialBodies = true;
setFallbackWeather(blight,"blight"); setFallbackWeather(blight,"blight");
Weather snow; Weather snow;
snow.mParticleEffect = "meshes\\snow.nif"; snow.mParticleEffect = "meshes\\snow.nif";
snow.mObstructsCelestialBodies = true;
setFallbackWeather(snow, "snow"); setFallbackWeather(snow, "snow");
Weather blizzard; Weather blizzard;
blizzard.mAmbientLoopSoundID = "BM Blizzard"; blizzard.mAmbientLoopSoundID = "BM Blizzard";
blizzard.mParticleEffect = "meshes\\blizzard.nif"; blizzard.mParticleEffect = "meshes\\blizzard.nif";
blizzard.mObstructsCelestialBodies = true;
setFallbackWeather(blizzard,"blizzard"); setFallbackWeather(blizzard,"blizzard");
} }
@ -460,14 +475,16 @@ void WeatherManager::setResult(const std::string& weatherType)
mResult.mNightFade = factor; mResult.mNightFade = factor;
} }
} }
mResult.mCelestialBodyTransparency = current.mObstructsCelestialBodies ? 0.0f : 1.0f;
} }
void WeatherManager::transition(float factor) void WeatherManager::transition(float factor)
{ {
setResult(mCurrentWeather); setResult(mCurrentWeather);
const WeatherResult current = mResult; const MWRender::WeatherResult current = mResult;
setResult(mNextWeather); setResult(mNextWeather);
const WeatherResult other = mResult; const MWRender::WeatherResult other = mResult;
mResult.mCloudTexture = current.mCloudTexture; mResult.mCloudTexture = current.mCloudTexture;
mResult.mNextCloudTexture = other.mCloudTexture; mResult.mNextCloudTexture = other.mCloudTexture;
@ -513,6 +530,16 @@ void WeatherManager::transition(float factor)
mResult.mEffectFade = mResult.mAmbientSoundVolume; mResult.mEffectFade = mResult.mAmbientSoundVolume;
mResult.mAmbientLoopSoundID = other.mAmbientLoopSoundID; mResult.mAmbientLoopSoundID = other.mAmbientLoopSoundID;
} }
const Weather& currentSettings = mWeatherSettings[mCurrentWeather];
const Weather& nextSettings = mWeatherSettings[mNextWeather];
if(currentSettings.mObstructsCelestialBodies && !nextSettings.mObstructsCelestialBodies)
mResult.mCelestialBodyTransparency = factor;
else if(!currentSettings.mObstructsCelestialBodies && nextSettings.mObstructsCelestialBodies)
mResult.mCelestialBodyTransparency = 1 - factor;
else
mResult.mCelestialBodyTransparency = current.mCelestialBodyTransparency;
} }
void WeatherManager::update(float duration, bool paused) void WeatherManager::update(float duration, bool paused)

View File

@ -9,6 +9,8 @@
#include "../mwbase/soundmanager.hpp" #include "../mwbase/soundmanager.hpp"
#include "../mwrender/sky.hpp"
namespace ESM namespace ESM
{ {
struct Region; struct Region;
@ -19,7 +21,6 @@ namespace ESM
namespace MWRender namespace MWRender
{ {
class RenderingManager; class RenderingManager;
struct MoonState;
} }
namespace Loading namespace Loading
@ -31,50 +32,6 @@ namespace MWWorld
{ {
class Fallback; class Fallback;
/// Defines the actual weather that results from weather setting (see below), time of day and weather transition
struct WeatherResult
{
std::string mCloudTexture;
std::string mNextCloudTexture;
float mCloudBlendFactor;
osg::Vec4f mFogColor;
osg::Vec4f mAmbientColor;
osg::Vec4f mSkyColor;
osg::Vec4f mSunColor;
osg::Vec4f mSunDiscColor;
float mFogDepth;
float mWindSpeed;
float mCloudSpeed;
float mCloudOpacity;
float mGlareView;
bool mNight; // use night skybox
float mNightFade; // fading factor for night skybox
bool mIsStorm;
std::string mAmbientLoopSoundID;
float mAmbientSoundVolume;
std::string mParticleEffect;
std::string mRainEffect;
float mEffectFade;
float mRainSpeed;
float mRainFrequency;
};
/// Defines a single weather setting (according to INI) /// Defines a single weather setting (according to INI)
struct Weather struct Weather
{ {
@ -149,6 +106,9 @@ namespace MWWorld
// Note: For Weather Blight, there is a "Disease Chance" (=0.1) setting. But according to MWSFD this feature // Note: For Weather Blight, there is a "Disease Chance" (=0.1) setting. But according to MWSFD this feature
// is broken in the vanilla game and was disabled. // is broken in the vanilla game and was disabled.
// Some weather patterns will obstruct the moons, sun, and stars.
bool mObstructsCelestialBodies;
}; };
class MoonModel class MoonModel
@ -173,7 +133,7 @@ namespace MWWorld
float angle(unsigned int daysPassed, float gameHour) const; float angle(unsigned int daysPassed, float gameHour) const;
float moonRiseHour(unsigned int daysPassed) const; float moonRiseHour(unsigned int daysPassed) const;
float rotation(float hours) const; float rotation(float hours) const;
unsigned int phase(unsigned int daysPassed) const; unsigned int phase(unsigned int daysPassed, float gameHour) const;
float shadowBlend(float angle) const; float shadowBlend(float angle) const;
float hourlyAlpha(float gameHour) const; float hourlyAlpha(float gameHour) const;
float earlyMoonShadowAlpha(float angle) const; float earlyMoonShadowAlpha(float angle) const;
@ -268,7 +228,7 @@ namespace MWWorld
void setWeather(const std::string& weatherType, bool instant=false); void setWeather(const std::string& weatherType, bool instant=false);
std::string nextWeather(const ESM::Region* region) const; std::string nextWeather(const ESM::Region* region) const;
WeatherResult mResult; MWRender::WeatherResult mResult;
typedef std::map<std::string,std::vector<char> > RegionModMap; typedef std::map<std::string,std::vector<char> > RegionModMap;
RegionModMap mRegionMods; RegionModMap mRegionMods;