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:
parent
06f170a8e1
commit
ea2f88a355
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user