Merge branch 'MoonPhaseAndVisibilityFixes' into 'master'
Some checks are pending
Build and test / Ubuntu (push) Waiting to run
Build and test / MacOS (push) Waiting to run
Build and test / Read .env file and expose it as output (push) Waiting to run
Build and test / Windows (2019) (push) Blocked by required conditions
Build and test / Windows (2022) (push) Blocked by required conditions

Match vanilla moon phases and visibility times

Closes #8375

See merge request OpenMW/openmw!4616
This commit is contained in:
Aussiemon 2025-04-27 20:32:38 -06:00
commit 40bb335929
4 changed files with 836 additions and 25 deletions

View file

@ -352,6 +352,30 @@ namespace MWWorld
mWeather = 0;
}
MoonModel::MoonModel(float fadeInStart, float fadeInFinish, float fadeOutStart, float fadeOutFinish,
float axisOffset, float speed, float dailyIncrement, float fadeStartAngle, float fadeEndAngle,
float moonShadowEarlyFadeAngle)
{
mFadeInStart = fadeInStart;
mFadeInFinish = fadeInFinish;
mFadeOutStart = fadeOutStart;
mFadeOutFinish = fadeOutFinish;
mAxisOffset = axisOffset;
mDailyIncrement = dailyIncrement;
mFadeStartAngle = fadeStartAngle;
mFadeEndAngle = fadeEndAngle;
mMoonShadowEarlyFadeAngle = moonShadowEarlyFadeAngle;
// Morrowind appears to have a minimum speed to avoid situations where the moon can't
// complete a full rotation in a single 24-hour period. The reverse-engineered formula is
// 180 degrees (full hemisphere) / 23 hours / 15 degrees (1 hour travel at speed 1.0).
mSpeed = std::max(speed, (180.0f / 23.0f / 15.0f));
// Morrowind appears to reduce mDailyIncrement with modulo 24.0f to avoid situations where
// the moon would increment more than an entire rotation in a single day.
mDailyIncrement = std::fmod(mDailyIncrement, 24.0f);
}
MoonModel::MoonModel(const std::string& name)
: mFadeInStart(Fallback::Map::getFloat("Moons_" + name + "_Fade_In_Start"))
, mFadeInFinish(Fallback::Map::getFloat("Moons_" + name + "_Fade_In_Finish"))
@ -364,14 +388,19 @@ namespace MWWorld
, mFadeEndAngle(Fallback::Map::getFloat("Moons_" + name + "_Fade_End_Angle"))
, mMoonShadowEarlyFadeAngle(Fallback::Map::getFloat("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);
// Morrowind appears to have a minimum speed to avoid situations where the moon can't
// complete a full rotation in a single 24-hour period. The reverse-engineered formula is
// 180 degrees (full hemisphere) / 23 hours / 15 degrees (1 hour travel at speed 1.0).
mSpeed = std::max(mSpeed, (180.0f / 23.0f / 15.0f));
// Morrowind appears to reduce mDailyIncrement with modulo 24.0f to avoid situations where
// the moon would increment more than an entire rotation in a single day.
mDailyIncrement = std::fmod(mDailyIncrement, 24.0f);
}
MWRender::MoonState MoonModel::calculateState(const TimeStamp& gameTime) const
{
float rotationFromHorizon = angle(gameTime);
float rotationFromHorizon = angle(gameTime.getDay(), gameTime.getHour());
MWRender::MoonState state = { rotationFromHorizon,
mAxisOffset, // Reverse engineered from Morrowind's scene graph rotation matrices.
phase(gameTime), shadowBlend(rotationFromHorizon),
@ -380,7 +409,7 @@ namespace MWWorld
return state;
}
inline float MoonModel::angle(const TimeStamp& gameTime) const
inline float MoonModel::angle(int gameDay, 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
@ -390,49 +419,83 @@ namespace MWWorld
// 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(gameTime.getDay());
float moonRiseAngleToday = 0;
float moonRiseHourToday = moonRiseHour(gameDay);
float moonRiseAngleToday = 0.0f;
if (gameTime.getHour() < moonRiseHourToday)
if (gameHour < moonRiseHourToday)
{
float moonRiseHourYesterday = moonRiseHour(gameTime.getDay() - 1);
if (moonRiseHourYesterday < 24)
// Rise hour increases by mDailyIncrement each day, so yesterday's is easy to calculate
float moonRiseHourYesterday = moonRiseHourToday - mDailyIncrement;
if (moonRiseHourYesterday < 24.0f)
{
float moonRiseAngleYesterday = rotation(24 - moonRiseHourYesterday);
if (moonRiseAngleYesterday < 180)
// Morrowind offsets the increment by -1 when the previous day's visible point crosses into the next
// day. The offset lasts from this point until the next 24-day loop starts. To find this point we add
// mDailyIncrement to the previous visible point and check the result.
float moonShadowEarlyFadeAngle1 = mFadeEndAngle - mMoonShadowEarlyFadeAngle;
float timeToVisible = moonShadowEarlyFadeAngle1 / rotation(1.0f);
float cycleOffset = moonRiseHourYesterday + timeToVisible > 24.0f ? mDailyIncrement : 0.0f;
float moonRiseAngleYesterday = rotation(24.0f - (moonRiseHourYesterday + cycleOffset));
if (moonRiseAngleYesterday < 180.0f)
{
// The moon rose but did not set yesterday, so accumulate yesterday's angle with how much we've
// travelled today.
moonRiseAngleToday = rotation(gameTime.getHour()) + moonRiseAngleYesterday;
moonRiseAngleToday = rotation(gameHour) + moonRiseAngleYesterday;
}
}
}
else
{
moonRiseAngleToday = rotation(gameTime.getHour() - moonRiseHourToday);
moonRiseAngleToday = rotation(gameHour - moonRiseHourToday);
}
if (moonRiseAngleToday >= 180)
if (moonRiseAngleToday >= 180.0f)
{
// The moon set today, reset the angle to the horizon.
moonRiseAngleToday = 0;
moonRiseAngleToday = 0.0f;
}
return moonRiseAngleToday;
}
inline float MoonModel::moonRiseHour(unsigned int daysPassed) const
inline float MoonModel::moonPhaseHour(int gameDay) const
{
// Morrowind delays moon phase changes until one of these is true:
// * The moon is invisible at midnight.
// * The moon reached moonShadowEarlyFadeAngle2 one daily increment ago (therefore invisible).
if (!isVisible(gameDay, 0.0f))
return 0.0f;
else
{
// Calculate the angle at which the moon becomes transparent and the starting angle.
float moonShadowEarlyFadeAngle2 = (180.0f - mFadeEndAngle) + mMoonShadowEarlyFadeAngle;
float midnightAngle = angle(gameDay, 0.0f);
// We can assume that moonShadowEarlyFadeAngle2 > midnightAngle, because the opposite
// case would make the moon invisible at midnight, which is checked above.
return ((moonShadowEarlyFadeAngle2 - midnightAngle) / rotation(1.0f)) + std::max(mDailyIncrement, 0.0f);
}
}
inline float MoonModel::moonRiseHour(int gameDay) const
{
if (mDailyIncrement == 0.0f)
return 0.0f;
// 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;
constexpr int startDay = 16;
// This formula finds the number of missed increments necessary to make the rise hour a 24-day loop.
// The offset increases on the first day of the loop and is multiplied by the number of completed loops.
float incrementOffset = (24.0f - std::abs(24.0f / mDailyIncrement)) * std::floor((gameDay + startDay) / 24.0f);
// 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);
return mDailyIncrement + std::fmod((gameDay - 1 + startDay - incrementOffset) * mDailyIncrement, 24.0f);
}
inline float MoonModel::rotation(float hours) const
@ -449,12 +512,18 @@ namespace MWWorld
// phase cycle.
// If the moon didn't rise yet today, use yesterday's moon phase.
if (gameTime.getHour() < moonRiseHour(gameTime.getDay()))
if (gameTime.getHour() < moonPhaseHour(gameTime.getDay()))
return static_cast<MWRender::MoonState::Phase>((gameTime.getDay() / 3) % 8);
else
return static_cast<MWRender::MoonState::Phase>(((gameTime.getDay() + 1) / 3) % 8);
}
inline bool MoonModel::isVisible(int gameDay, float gameHour) const
{
// Moons are "visible" when their alpha value is non-zero.
return hourlyAlpha(gameHour) > 0.f && earlyMoonShadowAlpha(angle(gameDay, gameHour)) > 0.f;
}
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
@ -480,6 +549,10 @@ namespace MWWorld
inline float MoonModel::hourlyAlpha(float gameHour) const
{
// Morrowind culls the moon one minute before mFadeOutFinish
constexpr float oneMinute = 0.0167f;
float adjustedFadeOutFinish = mFadeOutFinish - oneMinute;
// 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.
@ -487,9 +560,9 @@ namespace MWWorld
// 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))
if ((gameHour >= mFadeOutStart) && (gameHour < adjustedFadeOutFinish))
return (adjustedFadeOutFinish - gameHour) / (adjustedFadeOutFinish - mFadeOutStart);
else if ((gameHour >= adjustedFadeOutFinish) && (gameHour < mFadeInStart))
return 0.0f;
else if ((gameHour >= mFadeInStart) && (gameHour < mFadeInFinish))
return (gameHour - mFadeInStart) / (mFadeInFinish - mFadeInStart);

View file

@ -251,6 +251,9 @@ namespace MWWorld
{
public:
MoonModel(const std::string& name);
MoonModel(float fadeInStart, float fadeInFinish, float fadeOutStart, float fadeOutFinish, float axisOffset,
float speed, float dailyIncrement, float fadeStartAngle, float fadeEndAngle,
float moonShadowEarlyFadeAngle);
MWRender::MoonState calculateState(const TimeStamp& gameTime) const;
@ -266,10 +269,12 @@ namespace MWWorld
float mFadeEndAngle;
float mMoonShadowEarlyFadeAngle;
float angle(const TimeStamp& gameTime) const;
float moonRiseHour(unsigned int daysPassed) const;
float angle(int gameDay, float gameHour) const;
float moonPhaseHour(int gameDay) const;
float moonRiseHour(int gameDay) const;
float rotation(float hours) const;
MWRender::MoonState::Phase phase(const TimeStamp& gameTime) const;
bool isVisible(int gameDay, float gameHour) const;
float shadowBlend(float angle) const;
float hourlyAlpha(float gameHour) const;
float earlyMoonShadowAlpha(float angle) const;

View file

@ -10,6 +10,7 @@ file(GLOB UNITTEST_SRC_FILES
mwworld/testduration.cpp
mwworld/testtimestamp.cpp
mwworld/testptr.cpp
mwworld/testweather.cpp
mwdialogue/test_keywordsearch.cpp

View file

@ -0,0 +1,732 @@
#include <gtest/gtest.h>
#include <cmath>
#include "apps/openmw/mwworld/timestamp.hpp"
#include "apps/openmw/mwworld/weather.hpp"
namespace MWWorld
{
namespace
{
// MASSER PHASES
TEST(MWWorldWeatherTest, masserPhasesFullToWaningGibbousAtCorrectTimes)
{
float dailyIncrement = 1.0f;
float speed = 0.5f;
float fadeEndAngle = 40.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 35.0f;
// Days 2 and 26, 11:57
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 2 + 11.0f + 56.0f / 60.0f);
timeStampAfter += (24.0f * 2 + 11.0f + 58.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 26 + 11.0f + 56.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 26 + 11.0f + 58.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(0));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(1));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(0));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(1));
}
TEST(MWWorldWeatherTest, masserPhasesWaningGibbousToThirdQuarterAtCorrectTimes)
{
float dailyIncrement = 1.0f;
float speed = 0.5f;
float fadeEndAngle = 40.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 35.0f;
// Days 5 and 29, 0:00
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 4 + 23.0f + 59.0f / 60.0f);
timeStampAfter += (24.0f * 5 + 0.0f + 1.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 28 + 23.0f + 59.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 29 + 0.0f + 1.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(1));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(2));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(1));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(2));
}
TEST(MWWorldWeatherTest, masserPhasesThirdQuarterToWaningCrescentAtCorrectTimes)
{
float dailyIncrement = 1.0f;
float speed = 0.5f;
float fadeEndAngle = 40.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 35.0f;
// Days 8 and 32, 0:00
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 7 + 23.0f + 59.0f / 60.0f);
timeStampAfter += (24.0f * 8 + 0.0f + 1.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 31 + 23.0f + 59.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 32 + 0.0f + 1.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(2));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(3));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(2));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(3));
}
TEST(MWWorldWeatherTest, masserPhasesWaningCrescentToNewAtCorrectTimes)
{
float dailyIncrement = 1.0f;
float speed = 0.5f;
float fadeEndAngle = 40.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 35.0f;
// Days 11 and 35, 0:00
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 10 + 23.0f + 59.0f / 60.0f);
timeStampAfter += (24.0f * 11 + 0.0f + 1.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 34 + 23.0f + 59.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 35 + 0.0f + 1.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(3));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(4));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(3));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(4));
}
TEST(MWWorldWeatherTest, masserPhasesNewToWaxingCrescentAtCorrectTimes)
{
float dailyIncrement = 1.0f;
float speed = 0.5f;
float fadeEndAngle = 40.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 35.0f;
// Days 14 and 38, 0:00
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 13 + 23.0f + 59.0f / 60.0f);
timeStampAfter += (24.0f * 14 + 0.0f + 1.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 37 + 23.0f + 59.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 38 + 0.0f + 1.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(4));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(5));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(4));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(5));
}
TEST(MWWorldWeatherTest, masserPhasesWaxingCrescentToFirstQuarterAtCorrectTimes)
{
float dailyIncrement = 1.0f;
float speed = 0.5f;
float fadeEndAngle = 40.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 35.0f;
// Days 17 and 41, 2:57
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 17 + 2.0f + 56.0f / 60.0f);
timeStampAfter += (24.0f * 17 + 2.0f + 58.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 41 + 2.0f + 56.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 41 + 2.0f + 58.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(5));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(6));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(5));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(6));
}
TEST(MWWorldWeatherTest, masserPhasesFirstQuarterToWaxingGibbousAtCorrectTimes)
{
float dailyIncrement = 1.0f;
float speed = 0.5f;
float fadeEndAngle = 40.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 35.0f;
// Days 20 and 44, 5:57
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 20 + 5.0f + 56.0f / 60.0f);
timeStampAfter += (24.0f * 20 + 5.0f + 58.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 44 + 5.0f + 56.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 44 + 5.0f + 58.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(6));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(7));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(6));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(7));
}
TEST(MWWorldWeatherTest, masserPhasesWaxingGibbousToFullAtCorrectTimes)
{
float dailyIncrement = 1.0f;
float speed = 0.5f;
float fadeEndAngle = 40.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 35.0f;
// Days 23 and 47, 8:57
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 23 + 8.0f + 56.0f / 60.0f);
timeStampAfter += (24.0f * 23 + 8.0f + 58.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 47 + 8.0f + 56.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 47 + 8.0f + 58.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(7));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(0));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(7));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(0));
}
// SECUNDA PHASES
TEST(MWWorldWeatherTest, secundaPhasesFullToWaningGibbousAtCorrectTimes)
{
float dailyIncrement = 1.2f;
float speed = 0.6f;
float fadeEndAngle = 30.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 50.0f;
// Days 2 and 26, 14:19
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 2 + 14.0f + 18.0f / 60.0f);
timeStampAfter += (24.0f * 2 + 14.0f + 20.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 26 + 14.0f + 18.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 26 + 14.0f + 20.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(0));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(1));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(0));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(1));
}
TEST(MWWorldWeatherTest, secundaPhasesWaningGibbousToThirdQuarterAtCorrectTimes)
{
float dailyIncrement = 1.2f;
float speed = 0.6f;
float fadeEndAngle = 30.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 50.0f;
// Days 5 and 29, 0:00
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 4 + 23.0f + 59.0f / 60.0f);
timeStampAfter += (24.0f * 5 + 0.0f + 1.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 28 + 23.0f + 59.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 29 + 0.0f + 1.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(1));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(2));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(1));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(2));
}
TEST(MWWorldWeatherTest, secundaPhasesThirdQuarterToWaningCrescentAtCorrectTimes)
{
float dailyIncrement = 1.2f;
float speed = 0.6f;
float fadeEndAngle = 30.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 50.0f;
// Days 8 and 32, 0:00
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 7 + 23.0f + 59.0f / 60.0f);
timeStampAfter += (24.0f * 8 + 0.0f + 1.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 31 + 23.0f + 59.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 32 + 0.0f + 1.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(2));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(3));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(2));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(3));
}
TEST(MWWorldWeatherTest, secundaPhasesWaningCrescentToNewAtCorrectTimes)
{
float dailyIncrement = 1.2f;
float speed = 0.6f;
float fadeEndAngle = 30.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 50.0f;
// Days 11 and 35, 0:00
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 10 + 23.0f + 59.0f / 60.0f);
timeStampAfter += (24.0f * 11 + 0.0f + 1.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 34 + 23.0f + 59.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 35 + 0.0f + 1.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(3));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(4));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(3));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(4));
}
TEST(MWWorldWeatherTest, secundaPhasesNewToWaxingCrescentAtCorrectTimes)
{
float dailyIncrement = 1.2f;
float speed = 0.6f;
float fadeEndAngle = 30.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 50.0f;
// Days 14 and 38, 0:00
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 13 + 23.0f + 59.0f / 60.0f);
timeStampAfter += (24.0f * 14 + 0.0f + 1.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 37 + 23.0f + 59.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 38 + 0.0f + 1.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(4));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(5));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(4));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(5));
}
TEST(MWWorldWeatherTest, secundaPhasesWaxingCrescentToFirstQuarterAtCorrectTimes)
{
float dailyIncrement = 1.2f;
float speed = 0.6f;
float fadeEndAngle = 30.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 50.0f;
// Days 17 and 41, 3:31
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 17 + 3.0f + 30.0f / 60.0f);
timeStampAfter += (24.0f * 17 + 3.0f + 32.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 41 + 3.0f + 30.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 41 + 3.0f + 32.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(5));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(6));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(5));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(6));
}
TEST(MWWorldWeatherTest, secundaPhasesFirstQuarterToWaxingGibbousAtCorrectTimes)
{
float dailyIncrement = 1.2f;
float speed = 0.6f;
float fadeEndAngle = 30.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 50.0f;
// Days 20 and 44, 7:07
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 20 + 7.0f + 6.0f / 60.0f);
timeStampAfter += (24.0f * 20 + 7.0f + 8.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 44 + 7.0f + 6.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 44 + 7.0f + 8.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(6));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(7));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(6));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(7));
}
TEST(MWWorldWeatherTest, secundaPhasesWaxingGibbousToFullAtCorrectTimes)
{
float dailyIncrement = 1.2f;
float speed = 0.6f;
float fadeEndAngle = 30.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 50.0f;
// Days 23 and 47, 10:43
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 23 + 10.0f + 42.0f / 60.0f);
timeStampAfter += (24.0f * 23 + 10.0f + 44.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 47 + 10.0f + 42.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 47 + 10.0f + 44.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_EQ(beforeState.mPhase, static_cast<MWRender::MoonState::Phase>(7));
EXPECT_EQ(afterState.mPhase, static_cast<MWRender::MoonState::Phase>(0));
EXPECT_EQ(beforeStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(7));
EXPECT_EQ(afterStatePostLoop.mPhase, static_cast<MWRender::MoonState::Phase>(0));
}
// OFFSETS
TEST(MWWorldWeatherTest, secundaShouldApplyIncrementOffsetAfterFirstLoop)
{
float dailyIncrement = 1.2f;
float speed = 0.6f;
float fadeEndAngle = 30.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 14.0f;
float fadeInFinish = 15.0f;
float fadeOutStart = 7.0f;
float fadeOutFinish = 10.0f;
float axisOffset = 50.0f;
// Days 8 and 32, 3:16
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 8 + 3.0f + 15.0f / 60.0f);
timeStampAfter += (24.0f * 8 + 3.0f + 17.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 32 + 3.0f + 15.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 32 + 3.0f + 17.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_LE(beforeState.mMoonAlpha, 0.0f);
EXPECT_GT(afterState.mMoonAlpha, 0.0f);
EXPECT_LE(beforeStatePostLoop.mMoonAlpha, 0.0f);
EXPECT_GT(afterStatePostLoop.mMoonAlpha, 0.0f);
}
TEST(MWWorldWeatherTest, moonWithLowIncrementShouldApplyIncrementOffsetAfterCycle)
{
float dailyIncrement = 0.9f;
float speed = 0.5f;
float fadeEndAngle = 40.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 0.0f;
float fadeInFinish = 0.0f;
float fadeOutStart = 0.0f;
float fadeOutFinish = 0.0f;
float axisOffset = 35.0f;
// Days 7 and 31, 1:44
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 7 + 1.0f + 43.0f / 60.0f);
timeStampAfter += (24.0f * 7 + 1.0f + 45.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 31 + 1.0f + 43.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 31 + 1.0f + 45.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_LE(beforeState.mMoonAlpha, 0.0f);
EXPECT_GT(afterState.mMoonAlpha, 0.0f);
EXPECT_LE(beforeStatePostLoop.mMoonAlpha, 0.0f);
EXPECT_GT(afterStatePostLoop.mMoonAlpha, 0.0f);
}
TEST(MWWorldWeatherTest, masserShouldApplyIncrementOffsetAfterCycle)
{
float dailyIncrement = 1.0f;
float speed = 0.5f;
float fadeEndAngle = 40.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 0.0f;
float fadeInFinish = 0.0f;
float fadeOutStart = 0.0f;
float fadeOutFinish = 0.0f;
float axisOffset = 35.0f;
// Days 4 and 28, 1:02
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 4 + 1.0f + 1.0f / 60.0f);
timeStampAfter += (24.0f * 4 + 1.0f + 3.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 28 + 1.0f + 1.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 28 + 1.0f + 3.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_LE(beforeState.mMoonAlpha, 0.0f);
EXPECT_GT(afterState.mMoonAlpha, 0.0f);
EXPECT_LE(beforeStatePostLoop.mMoonAlpha, 0.0f);
EXPECT_GT(afterStatePostLoop.mMoonAlpha, 0.0f);
}
TEST(MWWorldWeatherTest, secundaShouldApplyIncrementOffsetAfterCycle)
{
float dailyIncrement = 1.2f;
float speed = 0.6f;
float fadeEndAngle = 30.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 0.0f;
float fadeInFinish = 0.0f;
float fadeOutStart = 0.0f;
float fadeOutFinish = 0.0f;
float axisOffset = 50.0f;
// Days 3 and 27, 2:04
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 3 + 2.0f + 3.0f / 60.0f);
timeStampAfter += (24.0f * 3 + 2.0f + 5.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 27 + 2.0f + 3.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 27 + 2.0f + 5.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_LE(beforeState.mMoonAlpha, 0.0f);
EXPECT_GT(afterState.mMoonAlpha, 0.0f);
EXPECT_LE(beforeStatePostLoop.mMoonAlpha, 0.0f);
EXPECT_GT(afterStatePostLoop.mMoonAlpha, 0.0f);
}
TEST(MWWorldWeatherTest, moonWithIncreasedSpeedShouldApplyIncrementOffsetAfterCycle)
{
float dailyIncrement = 1.2f;
float speed = 1.6f;
float fadeEndAngle = 30.0f;
float fadeStartAngle = 50.0f;
float moonShadowEarlyFadeAngle = 0.5f;
float fadeInStart = 0.0f;
float fadeInFinish = 0.0f;
float fadeOutStart = 0.0f;
float fadeOutFinish = 0.0f;
float axisOffset = 50.0f;
// Days 4 and 28, 1:13
TimeStamp timeStampBefore, timeStampAfter, timeStampBeforePostLoop, timeStampAfterPostLoop;
timeStampBefore += (24.0f * 4 + 1.0f + 12.0f / 60.0f);
timeStampAfter += (24.0f * 4 + 1.0f + 14.0f / 60.0f);
timeStampBeforePostLoop += (24.0f * 28 + 1.0f + 12.0f / 60.0f);
timeStampAfterPostLoop += (24.0f * 28 + 1.0f + 14.0f / 60.0f);
MWWorld::MoonModel moon = MWWorld::MoonModel(fadeInStart, fadeInFinish, fadeOutStart, fadeOutFinish,
axisOffset, speed, dailyIncrement, fadeStartAngle, fadeEndAngle, moonShadowEarlyFadeAngle);
MWRender::MoonState beforeState = moon.calculateState(timeStampBefore);
MWRender::MoonState afterState = moon.calculateState(timeStampAfter);
MWRender::MoonState beforeStatePostLoop = moon.calculateState(timeStampBeforePostLoop);
MWRender::MoonState afterStatePostLoop = moon.calculateState(timeStampAfterPostLoop);
EXPECT_LE(beforeState.mMoonAlpha, 0.0f);
EXPECT_GT(afterState.mMoonAlpha, 0.0f);
EXPECT_LE(beforeStatePostLoop.mMoonAlpha, 0.0f);
EXPECT_GT(afterStatePostLoop.mMoonAlpha, 0.0f);
}
}
}