mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-19 22:23:51 +00:00
Merge remote-tracking branch 'slothlife/moon-settings'
This commit is contained in:
commit
529041f6f6
4 changed files with 295 additions and 208 deletions
|
@ -1,5 +1,8 @@
|
|||
#include "sky.hpp"
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
|
||||
#include <osg/Transform>
|
||||
#include <osg/Geode>
|
||||
#include <osg/Depth>
|
||||
|
@ -383,26 +386,35 @@ public:
|
|||
Moon(osg::Group* parentNode, Resource::SceneManager* sceneManager, float scaleFactor, Type type)
|
||||
: CelestialBody(parentNode, sceneManager, scaleFactor, 2)
|
||||
, mType(type)
|
||||
, mPhase(Phase_Unspecified)
|
||||
, mPhase(MoonState::Phase_Unspecified)
|
||||
{
|
||||
mUpdater = new MoonUpdater;
|
||||
mGeode->addUpdateCallback(mUpdater);
|
||||
|
||||
setPhase(Phase_WaxingCrescent);
|
||||
setPhase(MoonState::Phase_Full);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
enum Phase
|
||||
void setState(const MoonState& state)
|
||||
{
|
||||
Phase_New = 0,
|
||||
Phase_WaxingCrescent,
|
||||
Phase_WaxingHalf,
|
||||
Phase_WaxingGibbous,
|
||||
Phase_Full,
|
||||
Phase_WaningGibbous,
|
||||
Phase_WaningHalf,
|
||||
Phase_WaningCrescent,
|
||||
Phase_Unspecified
|
||||
};
|
||||
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)
|
||||
{
|
||||
|
@ -415,7 +427,7 @@ public:
|
|||
mUpdater->setTextures(phaseTexPtr, circleTexPtr);
|
||||
}
|
||||
|
||||
void setPhase(const Phase& phase)
|
||||
void setPhase(const MoonState::Phase& phase)
|
||||
{
|
||||
if (mPhase == phase)
|
||||
return;
|
||||
|
@ -426,14 +438,14 @@ public:
|
|||
if (mType == Moon::Type_Secunda) textureName += "secunda_";
|
||||
else textureName += "masser_";
|
||||
|
||||
if (phase == Moon::Phase_New) textureName += "new";
|
||||
else if (phase == Moon::Phase_WaxingCrescent) textureName += "one_wax";
|
||||
else if (phase == Moon::Phase_WaxingHalf) textureName += "half_wax";
|
||||
else if (phase == Moon::Phase_WaxingGibbous) textureName += "three_wax";
|
||||
else if (phase == Moon::Phase_WaningCrescent) textureName += "one_wan";
|
||||
else if (phase == Moon::Phase_WaningHalf) textureName += "half_wan";
|
||||
else if (phase == Moon::Phase_WaningGibbous) textureName += "three_wan";
|
||||
else if (phase == Moon::Phase_Full) textureName += "full";
|
||||
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";
|
||||
|
||||
|
@ -452,7 +464,8 @@ public:
|
|||
{
|
||||
public:
|
||||
MoonUpdater()
|
||||
: mFade(0.f)
|
||||
: mTransparency(1.0f)
|
||||
, mShadowBlend(1.0f)
|
||||
, mMoonColor(1,1,1,1)
|
||||
{
|
||||
}
|
||||
|
@ -464,7 +477,7 @@ public:
|
|||
texEnv->setCombine_RGB(osg::TexEnvCombine::MODULATE);
|
||||
texEnv->setSource0_RGB(osg::TexEnvCombine::CONSTANT);
|
||||
texEnv->setSource1_RGB(osg::TexEnvCombine::TEXTURE);
|
||||
texEnv->setConstantColor(osg::Vec4f(1.f, 0.f, 0.f, 1.f)); // fade * MoonRedColor
|
||||
texEnv->setConstantColor(osg::Vec4f(1.f, 0.f, 0.f, 1.f)); // mShadowBlend * mMoonColor
|
||||
stateset->setTextureAttributeAndModes(0, texEnv, osg::StateAttribute::ON);
|
||||
|
||||
stateset->setTextureAttributeAndModes(1, mCircleTex, osg::StateAttribute::ON);
|
||||
|
@ -475,7 +488,7 @@ public:
|
|||
texEnv2->setSource1_Alpha(osg::TexEnvCombine::CONSTANT);
|
||||
texEnv2->setSource0_RGB(osg::TexEnvCombine::PREVIOUS);
|
||||
texEnv2->setSource1_RGB(osg::TexEnvCombine::CONSTANT);
|
||||
texEnv2->setConstantColor(osg::Vec4f(0.f, 0.f, 0.f, 1.f)); // atmospherecolor
|
||||
texEnv2->setConstantColor(osg::Vec4f(0.f, 0.f, 0.f, 1.f)); // mAtmosphereColor.rgb, mTransparency
|
||||
stateset->setTextureAttributeAndModes(1, texEnv2, osg::StateAttribute::ON);
|
||||
|
||||
stateset->setAttributeAndModes(createUnlitMaterial(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||
|
@ -484,21 +497,20 @@ public:
|
|||
virtual void apply(osg::StateSet *stateset, osg::NodeVisitor*)
|
||||
{
|
||||
osg::TexEnvCombine* texEnv = static_cast<osg::TexEnvCombine*>(stateset->getTextureAttribute(0, osg::StateAttribute::TEXENV));
|
||||
texEnv->setConstantColor(mMoonColor * mFade);
|
||||
texEnv->setConstantColor(mMoonColor * mShadowBlend);
|
||||
|
||||
osg::TexEnvCombine* texEnv2 = static_cast<osg::TexEnvCombine*>(stateset->getTextureAttribute(1, osg::StateAttribute::TEXENV));
|
||||
const float backdropFadeThreshold = 0.03;
|
||||
if (mFade <= backdropFadeThreshold)
|
||||
{
|
||||
texEnv2->setConstantColor(osg::Vec4f(mAtmosphereColor.x(), mAtmosphereColor.y(), mAtmosphereColor.z(), mFade / backdropFadeThreshold));
|
||||
}
|
||||
else
|
||||
texEnv2->setConstantColor(mAtmosphereColor);
|
||||
texEnv2->setConstantColor(osg::Vec4f(mAtmosphereColor.x(), mAtmosphereColor.y(), mAtmosphereColor.z(), mTransparency));
|
||||
}
|
||||
|
||||
void setFade (const float fade)
|
||||
void setTransparency(const float ratio)
|
||||
{
|
||||
mFade = fade;
|
||||
mTransparency = ratio;
|
||||
}
|
||||
|
||||
void setShadowBlend(const float blendFactor)
|
||||
{
|
||||
mShadowBlend = blendFactor;
|
||||
}
|
||||
|
||||
void setAtmosphereColor(const osg::Vec4f& color)
|
||||
|
@ -519,7 +531,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
float mFade;
|
||||
float mTransparency;
|
||||
float mShadowBlend;
|
||||
osg::Vec4f mAtmosphereColor;
|
||||
osg::Vec4f mMoonColor;
|
||||
osg::ref_ptr<osg::Texture2D> mPhaseTex;
|
||||
|
@ -537,27 +550,32 @@ public:
|
|||
mUpdater->setMoonColor(color);
|
||||
}
|
||||
|
||||
void setFade(const float fade)
|
||||
void setTransparency(const float ratio)
|
||||
{
|
||||
mUpdater->setFade(fade);
|
||||
mUpdater->setTransparency(ratio);
|
||||
}
|
||||
|
||||
void setShadowBlend(const float blendFactor)
|
||||
{
|
||||
mUpdater->setShadowBlend(blendFactor);
|
||||
}
|
||||
|
||||
unsigned int getPhaseInt() const
|
||||
{
|
||||
if (mPhase == Moon::Phase_New) return 0;
|
||||
else if (mPhase == Moon::Phase_WaxingCrescent) return 1;
|
||||
else if (mPhase == Moon::Phase_WaningCrescent) return 1;
|
||||
else if (mPhase == Moon::Phase_WaxingHalf) return 2;
|
||||
else if (mPhase == Moon::Phase_WaningHalf) return 2;
|
||||
else if (mPhase == Moon::Phase_WaxingGibbous) return 3;
|
||||
else if (mPhase == Moon::Phase_WaningGibbous) return 3;
|
||||
else if (mPhase == Moon::Phase_Full) return 4;
|
||||
if (mPhase == MoonState::Phase_New) return 0;
|
||||
else if (mPhase == MoonState::Phase_WaxingCrescent) return 1;
|
||||
else if (mPhase == MoonState::Phase_WaningCrescent) return 1;
|
||||
else if (mPhase == MoonState::Phase_FirstQuarter) return 2;
|
||||
else if (mPhase == MoonState::Phase_ThirdQuarter) return 2;
|
||||
else if (mPhase == MoonState::Phase_WaxingGibbous) return 3;
|
||||
else if (mPhase == MoonState::Phase_WaningGibbous) return 3;
|
||||
else if (mPhase == MoonState::Phase_Full) return 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
Type mType;
|
||||
Phase mPhase;
|
||||
MoonState::Phase mPhase;
|
||||
osg::ref_ptr<MoonUpdater> mUpdater;
|
||||
};
|
||||
|
||||
|
@ -886,10 +904,6 @@ void SkyManager::update(float duration)
|
|||
mCloudUpdater->setAnimationTimer(mCloudAnimationTimer);
|
||||
mCloudUpdater2->setAnimationTimer(mCloudAnimationTimer);
|
||||
|
||||
/// \todo improve this
|
||||
mMasser->setPhase( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
||||
mSecunda->setPhase ( static_cast<Moon::Phase>( (int) ((mDay % 32)/4.f)) );
|
||||
|
||||
if (mSunEnabled)
|
||||
{
|
||||
// take 1/10 sec for fading the glare effect from invisible to full
|
||||
|
@ -1128,46 +1142,18 @@ void SkyManager::setSunDirection(const osg::Vec3f& direction)
|
|||
//mSunGlare->setPosition(direction);
|
||||
}
|
||||
|
||||
void SkyManager::setMasserDirection(const osg::Vec3f& direction)
|
||||
void SkyManager::setMasserState(const MoonState& state)
|
||||
{
|
||||
if (!mCreated) return;
|
||||
if(!mCreated) return;
|
||||
|
||||
mMasser->setDirection(direction);
|
||||
mMasser->setState(state);
|
||||
}
|
||||
|
||||
void SkyManager::setSecundaDirection(const osg::Vec3f& direction)
|
||||
void SkyManager::setSecundaState(const MoonState& state)
|
||||
{
|
||||
if (!mCreated) return;
|
||||
if(!mCreated) return;
|
||||
|
||||
mSecunda->setDirection(direction);
|
||||
}
|
||||
|
||||
void SkyManager::masserEnable()
|
||||
{
|
||||
if (!mCreated) return;
|
||||
|
||||
mMasser->setVisible(true);
|
||||
}
|
||||
|
||||
void SkyManager::secundaEnable()
|
||||
{
|
||||
if (!mCreated) return;
|
||||
|
||||
mSecunda->setVisible(true);
|
||||
}
|
||||
|
||||
void SkyManager::masserDisable()
|
||||
{
|
||||
if (!mCreated) return;
|
||||
|
||||
mMasser->setVisible(false);
|
||||
}
|
||||
|
||||
void SkyManager::secundaDisable()
|
||||
{
|
||||
if (!mCreated) return;
|
||||
|
||||
mSecunda->setVisible(false);
|
||||
mSecunda->setState(state);
|
||||
}
|
||||
|
||||
void SkyManager::setLightningStrength(const float factor)
|
||||
|
@ -1184,18 +1170,6 @@ void SkyManager::setLightningStrength(const float factor)
|
|||
*/
|
||||
}
|
||||
|
||||
void SkyManager::setMasserFade(const float fade)
|
||||
{
|
||||
if (!mCreated) return;
|
||||
mMasser->setFade(fade);
|
||||
}
|
||||
|
||||
void SkyManager::setSecundaFade(const float fade)
|
||||
{
|
||||
if (!mCreated) return;
|
||||
mSecunda->setFade(fade);
|
||||
}
|
||||
|
||||
void SkyManager::setDate(int day, int month)
|
||||
{
|
||||
mDay = day;
|
||||
|
|
|
@ -33,6 +33,28 @@ namespace MWRender
|
|||
class RainFader;
|
||||
class AlphaFader;
|
||||
|
||||
struct MoonState
|
||||
{
|
||||
enum Phase
|
||||
{
|
||||
Phase_Full = 0,
|
||||
Phase_WaningGibbous,
|
||||
Phase_ThirdQuarter,
|
||||
Phase_WaningCrescent,
|
||||
Phase_New,
|
||||
Phase_WaxingCrescent,
|
||||
Phase_FirstQuarter,
|
||||
Phase_WaxingGibbous,
|
||||
Phase_Unspecified
|
||||
};
|
||||
|
||||
float mRotationFromHorizon;
|
||||
float mRotationFromNorth;
|
||||
Phase mPhase;
|
||||
float mShadowBlend;
|
||||
float mMoonAlpha;
|
||||
};
|
||||
|
||||
class SkyManager
|
||||
{
|
||||
public:
|
||||
|
@ -72,19 +94,8 @@ namespace MWRender
|
|||
|
||||
void setSunDirection(const osg::Vec3f& direction);
|
||||
|
||||
void setMasserDirection(const osg::Vec3f& direction);
|
||||
|
||||
void setSecundaDirection(const osg::Vec3f& direction);
|
||||
|
||||
void setMasserFade(const float fade);
|
||||
|
||||
void setSecundaFade(const float fade);
|
||||
|
||||
void masserEnable();
|
||||
void masserDisable();
|
||||
|
||||
void secundaEnable();
|
||||
void secundaDisable();
|
||||
void setMasserState(const MoonState& state);
|
||||
void setSecundaState(const MoonState& state);
|
||||
|
||||
void setLightningStrength(const float factor);
|
||||
|
||||
|
|
|
@ -37,6 +37,170 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
MoonModel::MoonModel(const std::string& name, const MWWorld::Fallback& fallback)
|
||||
: mFadeInStart(fallback.getFallbackFloat("Moons_" + name + "_Fade_In_Start"))
|
||||
, mFadeInFinish(fallback.getFallbackFloat("Moons_" + name + "_Fade_In_Finish"))
|
||||
, mFadeOutStart(fallback.getFallbackFloat("Moons_" + name + "_Fade_Out_Start"))
|
||||
, mFadeOutFinish(fallback.getFallbackFloat("Moons_" + name + "_Fade_Out_Finish"))
|
||||
, mAxisOffset(fallback.getFallbackFloat("Moons_" + name + "_Axis_Offset"))
|
||||
, mSpeed(fallback.getFallbackFloat("Moons_" + name + "_Speed"))
|
||||
, mDailyIncrement(fallback.getFallbackFloat("Moons_" + name + "_Daily_Increment"))
|
||||
, mFadeStartAngle(fallback.getFallbackFloat("Moons_" + name + "_Fade_Start_Angle"))
|
||||
, mFadeEndAngle(fallback.getFallbackFloat("Moons_" + name + "_Fade_End_Angle"))
|
||||
, mMoonShadowEarlyFadeAngle(fallback.getFallbackFloat("Moons_" + name + "_Moon_Shadow_Early_Fade_Angle"))
|
||||
{
|
||||
// Morrowind appears to have a minimum speed in order to avoid situations where the moon couldn't conceivably
|
||||
// complete a rotation in a single 24 hour period. The value of 180/23 was deduced from reverse engineering.
|
||||
mSpeed = std::min(mSpeed, 180.0f / 23.0f);
|
||||
}
|
||||
|
||||
MWRender::MoonState MoonModel::calculateState(unsigned int daysPassed, float gameHour) const
|
||||
{
|
||||
float rotationFromHorizon = angle(daysPassed, gameHour);
|
||||
MWRender::MoonState state =
|
||||
{
|
||||
rotationFromHorizon,
|
||||
mAxisOffset, // Reverse engineered from Morrowind's scene graph rotation matrices.
|
||||
static_cast<MWRender::MoonState::Phase>(phase(daysPassed)),
|
||||
shadowBlend(rotationFromHorizon),
|
||||
earlyMoonShadowAlpha(rotationFromHorizon) * hourlyAlpha(gameHour)
|
||||
};
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
inline float MoonModel::angle(unsigned int daysPassed, float gameHour) const
|
||||
{
|
||||
// Morrowind's moons start travel on one side of the horizon (let's call it H-rise) and travel 180 degrees to the
|
||||
// opposite horizon (let's call it H-set). Upon reaching H-set, they reset to H-rise until the next moon rise.
|
||||
|
||||
// When calculating the angle of the moon, several cases have to be taken into account:
|
||||
// 1. Moon rises and then sets in one day.
|
||||
// 2. Moon sets and doesn't rise in one day (occurs when the moon rise hour is >= 24).
|
||||
// 3. Moon sets and then rises in one day.
|
||||
float moonRiseHourToday = moonRiseHour(daysPassed);
|
||||
float moonRiseAngleToday = 0;
|
||||
|
||||
if(gameHour < moonRiseHourToday)
|
||||
{
|
||||
float moonRiseHourYesterday = moonRiseHour(daysPassed - 1);
|
||||
if(moonRiseHourYesterday < 24)
|
||||
{
|
||||
float moonRiseAngleYesterday = rotation(24 - moonRiseHourYesterday);
|
||||
if(moonRiseAngleYesterday < 180)
|
||||
{
|
||||
// The moon rose but did not set yesterday, so accumulate yesterday's angle with how much we've travelled today.
|
||||
moonRiseAngleToday = rotation(gameHour) + moonRiseAngleYesterday;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
moonRiseAngleToday = rotation(gameHour - moonRiseHourToday);
|
||||
}
|
||||
|
||||
if(moonRiseAngleToday >= 180)
|
||||
{
|
||||
// The moon set today, reset the angle to the horizon.
|
||||
moonRiseAngleToday = 0;
|
||||
}
|
||||
|
||||
return moonRiseAngleToday;
|
||||
}
|
||||
|
||||
inline float MoonModel::moonRiseHour(unsigned int daysPassed) const
|
||||
{
|
||||
// This arises from the start date of 16 Last Seed, 427
|
||||
// TODO: Find an alternate formula that doesn't rely on this day being fixed.
|
||||
static const unsigned int startDay = 16;
|
||||
|
||||
// This odd formula arises from the fact that on 16 Last Seed, 17 increments have occurred, meaning
|
||||
// that upon starting a new game, it must only calculate the moon phase as far back as 1 Last Seed.
|
||||
// Note that we don't modulo after adding the latest daily increment because other calculations need to
|
||||
// know if doing so would cause the moon rise to be postponed until the next day (which happens when
|
||||
// the moon rise hour is >= 24 in Morrowind).
|
||||
return mDailyIncrement + std::fmod((daysPassed - 1 + startDay) * mDailyIncrement, 24.0f);
|
||||
}
|
||||
|
||||
inline float MoonModel::rotation(float hours) const
|
||||
{
|
||||
// 15 degrees per hour was reverse engineered from the rotation matrices of the Morrowind scene graph.
|
||||
// Note that this correlates to 360 / 24, which is a full rotation every 24 hours, so speed is a measure
|
||||
// of whole rotations that could be completed in a day.
|
||||
return 15.0f * mSpeed * hours;
|
||||
}
|
||||
|
||||
inline unsigned int MoonModel::phase(unsigned int daysPassed) 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.
|
||||
// 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).
|
||||
return ((daysPassed + 1) / 3) % 8;
|
||||
}
|
||||
|
||||
inline float MoonModel::shadowBlend(float angle) const
|
||||
{
|
||||
// The Fade End Angle and Fade Start Angle describe a region where the moon transitions from a solid disk
|
||||
// that is roughly the color of the sky, to a textured surface.
|
||||
// Depending on the current angle, the following values describe the ratio between the textured moon
|
||||
// and the solid disk:
|
||||
// 1. From Fade End Angle 1 to Fade Start Angle 1 (during moon rise): 0..1
|
||||
// 2. From Fade Start Angle 1 to Fade Start Angle 2 (between moon rise and moon set): 1 (textured)
|
||||
// 3. From Fade Start Angle 2 to Fade End Angle 2 (during moon set): 1..0
|
||||
// 4. From Fade End Angle 2 to Fade End Angle 1 (between moon set and moon rise): 0 (solid disk)
|
||||
float fadeAngle = mFadeStartAngle - mFadeEndAngle;
|
||||
float fadeEndAngle2 = 180.0f - mFadeEndAngle;
|
||||
float fadeStartAngle2 = 180.0f - mFadeStartAngle;
|
||||
if((angle >= mFadeEndAngle) && (angle < mFadeStartAngle))
|
||||
return (angle - mFadeEndAngle) / fadeAngle;
|
||||
else if((angle >= mFadeStartAngle) && (angle < fadeStartAngle2))
|
||||
return 1.0f;
|
||||
else if((angle >= fadeStartAngle2) && (angle < fadeEndAngle2))
|
||||
return (fadeEndAngle2 - angle) / fadeAngle;
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
inline float MoonModel::hourlyAlpha(float gameHour) const
|
||||
{
|
||||
// The Fade Out Start / Finish and Fade In Start / Finish describe the hours at which the moon
|
||||
// appears and disappears.
|
||||
// Depending on the current hour, the following values describe how transparent the moon is.
|
||||
// 1. From Fade Out Start to Fade Out Finish: 1..0
|
||||
// 2. From Fade Out Finish to Fade In Start: 0 (transparent)
|
||||
// 3. From Fade In Start to Fade In Finish: 0..1
|
||||
// 4. From Fade In Finish to Fade Out Start: 1 (solid)
|
||||
if((gameHour >= mFadeOutStart) && (gameHour < mFadeOutFinish))
|
||||
return (mFadeOutFinish - gameHour) / (mFadeOutFinish - mFadeOutStart);
|
||||
else if((gameHour >= mFadeOutFinish) && (gameHour < mFadeInStart))
|
||||
return 0.0f;
|
||||
else if((gameHour >= mFadeInStart) && (gameHour < mFadeInFinish))
|
||||
return (gameHour - mFadeInStart) / (mFadeInFinish - mFadeInStart);
|
||||
else
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
inline float MoonModel::earlyMoonShadowAlpha(float angle) const
|
||||
{
|
||||
// The Moon Shadow Early Fade Angle describes an arc relative to Fade End Angle.
|
||||
// Depending on the current angle, the following values describe how transparent the moon is.
|
||||
// 1. From Moon Shadow Early Fade Angle 1 to Fade End Angle 1 (during moon rise): 0..1
|
||||
// 2. From Fade End Angle 1 to Fade End Angle 2 (between moon rise and moon set): 1 (solid)
|
||||
// 3. From Fade End Angle 2 to Moon Shadow Early Fade Angle 2 (during moon set): 1..0
|
||||
// 4. From Moon Shadow Early Fade Angle 2 to Moon Shadow Early Fade Angle 1: 0 (transparent)
|
||||
float moonShadowEarlyFadeAngle1 = mFadeEndAngle - mMoonShadowEarlyFadeAngle;
|
||||
float fadeEndAngle2 = 180.0f - mFadeEndAngle;
|
||||
float moonShadowEarlyFadeAngle2 = fadeEndAngle2 + mMoonShadowEarlyFadeAngle;
|
||||
if((angle >= moonShadowEarlyFadeAngle1) && (angle < mFadeEndAngle))
|
||||
return (angle - moonShadowEarlyFadeAngle1) / mMoonShadowEarlyFadeAngle;
|
||||
else if((angle >= mFadeEndAngle) && (angle < fadeEndAngle2))
|
||||
return 1.0f;
|
||||
else if((angle >= fadeEndAngle2) && (angle < moonShadowEarlyFadeAngle2))
|
||||
return (moonShadowEarlyFadeAngle2 - angle) / mMoonShadowEarlyFadeAngle;
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void WeatherManager::setFallbackWeather(Weather& weather,const std::string& name)
|
||||
{
|
||||
std::string upper=name;
|
||||
|
@ -88,39 +252,12 @@ Max Raindrops=650 ?
|
|||
mWeatherSettings[name] = weather;
|
||||
}
|
||||
|
||||
|
||||
float WeatherManager::calculateHourFade (const std::string& moonName) const
|
||||
{
|
||||
float fadeOutStart=mFallback->getFallbackFloat("Moons_"+moonName+"_Fade_Out_Start");
|
||||
float fadeOutFinish=mFallback->getFallbackFloat("Moons_"+moonName+"_Fade_Out_Finish");
|
||||
float fadeInStart=mFallback->getFallbackFloat("Moons_"+moonName+"_Fade_In_Start");
|
||||
float fadeInFinish=mFallback->getFallbackFloat("Moons_"+moonName+"_Fade_In_Finish");
|
||||
|
||||
if (mHour >= fadeOutStart && mHour <= fadeOutFinish)
|
||||
return (1 - ((mHour - fadeOutStart) / (fadeOutFinish - fadeOutStart)));
|
||||
if (mHour >= fadeInStart && mHour <= fadeInFinish)
|
||||
return (1 - ((mHour - fadeInStart) / (fadeInFinish - fadeInStart)));
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
float WeatherManager::calculateAngleFade (const std::string& moonName, float angle) const
|
||||
{
|
||||
float endAngle=mFallback->getFallbackFloat("Moons_"+moonName+"_Fade_End_Angle");
|
||||
float startAngle=mFallback->getFallbackFloat("Moons_"+moonName+"_Fade_Start_Angle");
|
||||
if (angle <= startAngle && angle >= endAngle)
|
||||
return (1 - ((angle - endAngle)/(startAngle-endAngle)));
|
||||
else if (angle > startAngle)
|
||||
return 0.f;
|
||||
else
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
WeatherManager::WeatherManager(MWRender::RenderingManager* rendering, MWWorld::Fallback* fallback, MWWorld::ESMStore* store) :
|
||||
mHour(14), mWindSpeed(0.f), mIsStorm(false), mStormDirection(0,1,0), mFallback(fallback), mStore(store),
|
||||
mRendering(rendering), mCurrentWeather("clear"), mNextWeather(""), mFirstUpdate(true),
|
||||
mRemainingTransitionTime(0), mThunderFlash(0), mThunderChance(0), mThunderChanceNeeded(50),
|
||||
mTimePassed(0), mWeatherUpdateTime(0), mThunderSoundDelay(0)
|
||||
mTimePassed(0), mWeatherUpdateTime(0), mThunderSoundDelay(0),
|
||||
mMasser("Masser", *fallback), mSecunda("Secunda", *fallback)
|
||||
{
|
||||
//Globals
|
||||
mThunderSoundID0 = mFallback->getFallbackString("Weather_Thunderstorm_Thunder_Sound_ID_0");
|
||||
|
@ -465,72 +602,9 @@ void WeatherManager::update(float duration, bool paused)
|
|||
mRendering->setSunDirection( final * -1 );
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: import separated fadeInStart/Finish, fadeOutStart/Finish
|
||||
* for masser and secunda
|
||||
*/
|
||||
|
||||
float fadeOutFinish=mFallback->getFallbackFloat("Moons_Masser_Fade_Out_Finish");
|
||||
float fadeInStart=mFallback->getFallbackFloat("Moons_Masser_Fade_In_Start");
|
||||
|
||||
//moon calculations
|
||||
float moonHeight;
|
||||
if (mHour >= fadeInStart)
|
||||
moonHeight = mHour - fadeInStart;
|
||||
else if (mHour <= fadeOutFinish)
|
||||
moonHeight = mHour + fadeOutFinish;
|
||||
else
|
||||
moonHeight = 0;
|
||||
|
||||
moonHeight /= (24.f - (fadeInStart - fadeOutFinish));
|
||||
|
||||
if (moonHeight != 0)
|
||||
{
|
||||
int facing = (moonHeight <= 1) ? 1 : -1;
|
||||
osg::Vec3f masser(
|
||||
(moonHeight - 1) * facing,
|
||||
(1 - moonHeight) * facing,
|
||||
moonHeight);
|
||||
|
||||
osg::Vec3f secunda(
|
||||
(moonHeight - 1) * facing * 1.25f,
|
||||
(1 - moonHeight) * facing * 0.8f,
|
||||
moonHeight);
|
||||
|
||||
mRendering->getSkyManager()->setMasserDirection(masser);
|
||||
mRendering->getSkyManager()->setSecundaDirection(secunda);
|
||||
|
||||
float angle = (1-moonHeight) * 90.f * facing;
|
||||
float masserHourFade = calculateHourFade("Masser");
|
||||
float secundaHourFade = calculateHourFade("Secunda");
|
||||
float masserAngleFade = calculateAngleFade("Masser", angle);
|
||||
float secundaAngleFade = calculateAngleFade("Secunda", angle);
|
||||
|
||||
masserAngleFade *= masserHourFade;
|
||||
secundaAngleFade *= secundaHourFade;
|
||||
|
||||
if (masserAngleFade > 0)
|
||||
{
|
||||
mRendering->getSkyManager()->setMasserFade(masserAngleFade);
|
||||
mRendering->getSkyManager()->masserEnable();
|
||||
}
|
||||
else
|
||||
mRendering->getSkyManager()->masserDisable();
|
||||
|
||||
if (secundaAngleFade > 0)
|
||||
{
|
||||
mRendering->getSkyManager()->setSecundaFade(secundaAngleFade);
|
||||
mRendering->getSkyManager()->secundaEnable();
|
||||
}
|
||||
else
|
||||
mRendering->getSkyManager()->secundaDisable();
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
mRendering->getSkyManager()->masserDisable();
|
||||
mRendering->getSkyManager()->secundaDisable();
|
||||
}
|
||||
TimeStamp time = MWBase::Environment::get().getWorld()->getTimeStamp();
|
||||
mRendering->getSkyManager()->setMasserState(mMasser.calculateState(time.getDay(), time.getHour()));
|
||||
mRendering->getSkyManager()->setSecundaState(mSecunda.calculateState(time.getDay(), time.getHour()));
|
||||
|
||||
if (!paused)
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace ESM
|
|||
namespace MWRender
|
||||
{
|
||||
class RenderingManager;
|
||||
struct MoonState;
|
||||
}
|
||||
|
||||
namespace Loading
|
||||
|
@ -150,6 +151,34 @@ namespace MWWorld
|
|||
// is broken in the vanilla game and was disabled.
|
||||
};
|
||||
|
||||
class MoonModel
|
||||
{
|
||||
public:
|
||||
MoonModel(const std::string& name, const MWWorld::Fallback& fallback);
|
||||
|
||||
MWRender::MoonState calculateState(unsigned int daysPassed, float gameHour) const;
|
||||
|
||||
private:
|
||||
float mFadeInStart;
|
||||
float mFadeInFinish;
|
||||
float mFadeOutStart;
|
||||
float mFadeOutFinish;
|
||||
float mAxisOffset;
|
||||
float mSpeed;
|
||||
float mDailyIncrement;
|
||||
float mFadeStartAngle;
|
||||
float mFadeEndAngle;
|
||||
float mMoonShadowEarlyFadeAngle;
|
||||
|
||||
float angle(unsigned int daysPassed, float gameHour) const;
|
||||
float moonRiseHour(unsigned int daysPassed) const;
|
||||
float rotation(float hours) const;
|
||||
unsigned int phase(unsigned int daysPassed) const;
|
||||
float shadowBlend(float angle) const;
|
||||
float hourlyAlpha(float gameHour) const;
|
||||
float earlyMoonShadowAlpha(float angle) const;
|
||||
};
|
||||
|
||||
///
|
||||
/// Interface for weather settings
|
||||
///
|
||||
|
@ -237,9 +266,6 @@ namespace MWWorld
|
|||
void transition(const float factor);
|
||||
void setResult(const std::string& weatherType);
|
||||
|
||||
float calculateHourFade (const std::string& moonName) const;
|
||||
float calculateAngleFade (const std::string& moonName, float angle) const;
|
||||
|
||||
void setWeather(const std::string& weatherType, bool instant=false);
|
||||
std::string nextWeather(const ESM::Region* region) const;
|
||||
WeatherResult mResult;
|
||||
|
@ -265,6 +291,8 @@ namespace MWWorld
|
|||
std::string mThunderSoundID1;
|
||||
std::string mThunderSoundID2;
|
||||
std::string mThunderSoundID3;
|
||||
MoonModel mMasser;
|
||||
MoonModel mSecunda;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue