mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-29 23:26:38 +00:00 
			
		
		
		
	Implement vanilla-style wind speed calculations (bug #4449)
This commit is contained in:
		
							parent
							
								
									822b20ef46
								
							
						
					
					
						commit
						e5564df8cb
					
				
					 5 changed files with 64 additions and 9 deletions
				
			
		|  | @ -27,6 +27,7 @@ | ||||||
|     Bug #4383: Bow model obscures crosshair when arrow is drawn |     Bug #4383: Bow model obscures crosshair when arrow is drawn | ||||||
|     Bug #4384: Resist Normal Weapons only checks ammunition for ranged weapons |     Bug #4384: Resist Normal Weapons only checks ammunition for ranged weapons | ||||||
|     Bug #4411: Reloading a saved game while falling prevents damage in some cases |     Bug #4411: Reloading a saved game while falling prevents damage in some cases | ||||||
|  |     Bug #4449: Value returned by GetWindSpeed is incorrect | ||||||
|     Bug #4540: Rain delay when exiting water |     Bug #4540: Rain delay when exiting water | ||||||
|     Bug #4600: Crash when no sound output is available or --no-sound is used. |     Bug #4600: Crash when no sound output is available or --no-sound is used. | ||||||
|     Bug #4639: Black screen after completing first mages guild mission + training |     Bug #4639: Black screen after completing first mages guild mission + training | ||||||
|  |  | ||||||
|  | @ -1625,7 +1625,8 @@ void SkyManager::updateRainParameters() | ||||||
| { | { | ||||||
|     if (mRainShooter) |     if (mRainShooter) | ||||||
|     { |     { | ||||||
|         float windFactor = mWindSpeed/3.f; |         // Note: an arbitrary value. An original engine seems to use a different approach to rotate raindrops.
 | ||||||
|  |         float windFactor = mWindSpeed/32.f; | ||||||
|         float angle = windFactor * osg::PI/4; |         float angle = windFactor * osg::PI/4; | ||||||
|         mRainShooter->setVelocity(osg::Vec3f(0, mRainSpeed * windFactor, -mRainSpeed)); |         mRainShooter->setVelocity(osg::Vec3f(0, mRainSpeed * windFactor, -mRainSpeed)); | ||||||
|         mRainShooter->setAngle(angle); |         mRainShooter->setAngle(angle); | ||||||
|  |  | ||||||
|  | @ -68,6 +68,8 @@ namespace MWRender | ||||||
|         float mDLFogOffset; |         float mDLFogOffset; | ||||||
| 
 | 
 | ||||||
|         float mWindSpeed; |         float mWindSpeed; | ||||||
|  |         float mCurrentWindSpeed; | ||||||
|  |         float mNextWindSpeed; | ||||||
| 
 | 
 | ||||||
|         float mCloudSpeed; |         float mCloudSpeed; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -538,6 +538,8 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, MWWorld::E | ||||||
|     , mMasser("Masser") |     , mMasser("Masser") | ||||||
|     , mSecunda("Secunda") |     , mSecunda("Secunda") | ||||||
|     , mWindSpeed(0.f) |     , mWindSpeed(0.f) | ||||||
|  |     , mCurrentWindSpeed(0.f) | ||||||
|  |     , mNextWindSpeed(0.f) | ||||||
|     , mIsStorm(false) |     , mIsStorm(false) | ||||||
|     , mPrecipitation(false) |     , mPrecipitation(false) | ||||||
|     , mStormDirection(0,1,0) |     , mStormDirection(0,1,0) | ||||||
|  | @ -663,6 +665,40 @@ void WeatherManager::playerTeleported(const std::string& playerRegion, bool isEx | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | osg::Vec3f WeatherManager::calculateStormDirection() | ||||||
|  | { | ||||||
|  |     osg::Vec3f playerPos (MWMechanics::getPlayer().getRefData().getPosition().asVec3()); | ||||||
|  |     playerPos.z() = 0; | ||||||
|  |     osg::Vec3f redMountainPos (25000, 70000, 0); | ||||||
|  |     osg::Vec3f stormDirection = (playerPos - redMountainPos); | ||||||
|  |     stormDirection.normalize(); | ||||||
|  | 
 | ||||||
|  |     return stormDirection; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | float WeatherManager::calculateWindSpeed(int weatherId, float currentSpeed) | ||||||
|  | { | ||||||
|  |     float targetSpeed = std::min(8.0f * mWeatherSettings[weatherId].mWindSpeed, 70.f); | ||||||
|  |     if (currentSpeed == 0.f) | ||||||
|  |         currentSpeed = targetSpeed; | ||||||
|  | 
 | ||||||
|  |     float multiplier = mWeatherSettings[weatherId].mRainEffect.empty() ? 1.f : 0.5f; | ||||||
|  |     float updatedSpeed = (Misc::Rng::rollClosedProbability() - 0.5f) * multiplier * targetSpeed + currentSpeed; | ||||||
|  | 
 | ||||||
|  |     if (updatedSpeed > 0.5f * targetSpeed && updatedSpeed < 2.f * targetSpeed) | ||||||
|  |     { | ||||||
|  |         currentSpeed = updatedSpeed; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Take in account direction to the Red Mountain, when needed
 | ||||||
|  |     if (weatherId == 6 || weatherId == 7) | ||||||
|  |     { | ||||||
|  |         currentSpeed = (calculateStormDirection() * currentSpeed).length(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return currentSpeed; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void WeatherManager::update(float duration, bool paused, const TimeStamp& time, bool isExterior) | void WeatherManager::update(float duration, bool paused, const TimeStamp& time, bool isExterior) | ||||||
| { | { | ||||||
|     MWWorld::ConstPtr player = MWMechanics::getPlayer(); |     MWWorld::ConstPtr player = MWMechanics::getPlayer(); | ||||||
|  | @ -695,12 +731,21 @@ void WeatherManager::update(float duration, bool paused, const TimeStamp& time, | ||||||
|     { |     { | ||||||
|         mRendering.setSkyEnabled(false); |         mRendering.setSkyEnabled(false); | ||||||
|         stopSounds(); |         stopSounds(); | ||||||
|  |         mWindSpeed = 0.f; | ||||||
|  |         mCurrentWindSpeed = 0.f; | ||||||
|  |         mNextWindSpeed = 0.f; | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     calculateWeatherResult(time.getHour(), duration, paused); |     calculateWeatherResult(time.getHour(), duration, paused); | ||||||
| 
 | 
 | ||||||
|  |     if (!paused) | ||||||
|  |     { | ||||||
|         mWindSpeed = mResult.mWindSpeed; |         mWindSpeed = mResult.mWindSpeed; | ||||||
|  |         mCurrentWindSpeed = mResult.mCurrentWindSpeed; | ||||||
|  |         mNextWindSpeed = mResult.mNextWindSpeed; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     mIsStorm = mResult.mIsStorm; |     mIsStorm = mResult.mIsStorm; | ||||||
| 
 | 
 | ||||||
|     // For some reason Ash Storm is not considered as a precipitation weather in game
 |     // For some reason Ash Storm is not considered as a precipitation weather in game
 | ||||||
|  | @ -709,11 +754,7 @@ void WeatherManager::update(float duration, bool paused, const TimeStamp& time, | ||||||
| 
 | 
 | ||||||
|     if (mIsStorm) |     if (mIsStorm) | ||||||
|     { |     { | ||||||
|         osg::Vec3f playerPos (player.getRefData().getPosition().asVec3()); |         mStormDirection = calculateStormDirection(); | ||||||
|         playerPos.z() = 0; |  | ||||||
|         osg::Vec3f redMountainPos (25000, 70000, 0); |  | ||||||
|         mStormDirection = (playerPos - redMountainPos); |  | ||||||
|         mStormDirection.normalize(); |  | ||||||
|         mRendering.getSkyManager()->setStormDirection(mStormDirection); |         mRendering.getSkyManager()->setStormDirection(mStormDirection); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1096,7 +1137,9 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam | ||||||
| 
 | 
 | ||||||
|     mResult.mCloudTexture = current.mCloudTexture; |     mResult.mCloudTexture = current.mCloudTexture; | ||||||
|     mResult.mCloudBlendFactor = 0; |     mResult.mCloudBlendFactor = 0; | ||||||
|     mResult.mWindSpeed = current.mWindSpeed; |     mResult.mNextWindSpeed = 0; | ||||||
|  |     mResult.mWindSpeed = mResult.mCurrentWindSpeed = calculateWindSpeed(weatherID, mWindSpeed); | ||||||
|  | 
 | ||||||
|     mResult.mCloudSpeed = current.mCloudSpeed; |     mResult.mCloudSpeed = current.mCloudSpeed; | ||||||
|     mResult.mGlareView = current.mGlareView; |     mResult.mGlareView = current.mGlareView; | ||||||
|     mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID; |     mResult.mAmbientLoopSoundID = current.mAmbientLoopSoundID; | ||||||
|  | @ -1180,7 +1223,11 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const | ||||||
|     mResult.mFogDepth = lerp(current.mFogDepth, other.mFogDepth, factor); |     mResult.mFogDepth = lerp(current.mFogDepth, other.mFogDepth, factor); | ||||||
|     mResult.mDLFogFactor = lerp(current.mDLFogFactor, other.mDLFogFactor, factor); |     mResult.mDLFogFactor = lerp(current.mDLFogFactor, other.mDLFogFactor, factor); | ||||||
|     mResult.mDLFogOffset = lerp(current.mDLFogOffset, other.mDLFogOffset, factor); |     mResult.mDLFogOffset = lerp(current.mDLFogOffset, other.mDLFogOffset, factor); | ||||||
|     mResult.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed, factor); | 
 | ||||||
|  |     mResult.mCurrentWindSpeed = calculateWindSpeed(mCurrentWeather, mCurrentWindSpeed); | ||||||
|  |     mResult.mNextWindSpeed = calculateWindSpeed(mNextWeather, mNextWindSpeed); | ||||||
|  | 
 | ||||||
|  |     mResult.mWindSpeed = lerp(mResult.mCurrentWindSpeed, mResult.mNextWindSpeed, factor); | ||||||
|     mResult.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed, factor); |     mResult.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed, factor); | ||||||
|     mResult.mGlareView = lerp(current.mGlareView, other.mGlareView, factor); |     mResult.mGlareView = lerp(current.mGlareView, other.mGlareView, factor); | ||||||
|     mResult.mNightFade = lerp(current.mNightFade, other.mNightFade, factor); |     mResult.mNightFade = lerp(current.mNightFade, other.mNightFade, factor); | ||||||
|  |  | ||||||
|  | @ -325,6 +325,8 @@ namespace MWWorld | ||||||
|         MoonModel mSecunda; |         MoonModel mSecunda; | ||||||
| 
 | 
 | ||||||
|         float mWindSpeed; |         float mWindSpeed; | ||||||
|  |         float mCurrentWindSpeed; | ||||||
|  |         float mNextWindSpeed; | ||||||
|         bool mIsStorm; |         bool mIsStorm; | ||||||
|         bool mPrecipitation; |         bool mPrecipitation; | ||||||
|         osg::Vec3f mStormDirection; |         osg::Vec3f mStormDirection; | ||||||
|  | @ -355,6 +357,7 @@ namespace MWWorld | ||||||
|         bool updateWeatherRegion(const std::string& playerRegion); |         bool updateWeatherRegion(const std::string& playerRegion); | ||||||
|         void updateWeatherTransitions(const float elapsedRealSeconds); |         void updateWeatherTransitions(const float elapsedRealSeconds); | ||||||
|         void forceWeather(const int weatherID); |         void forceWeather(const int weatherID); | ||||||
|  |         osg::Vec3f calculateStormDirection(); | ||||||
| 
 | 
 | ||||||
|         bool inTransition(); |         bool inTransition(); | ||||||
|         void addWeatherTransition(const int weatherID); |         void addWeatherTransition(const int weatherID); | ||||||
|  | @ -362,6 +365,7 @@ namespace MWWorld | ||||||
|         void calculateWeatherResult(const float gameHour, const float elapsedSeconds, const bool isPaused); |         void calculateWeatherResult(const float gameHour, const float elapsedSeconds, const bool isPaused); | ||||||
|         void calculateResult(const int weatherID, const float gameHour); |         void calculateResult(const int weatherID, const float gameHour); | ||||||
|         void calculateTransitionResult(const float factor, const float gameHour); |         void calculateTransitionResult(const float factor, const float gameHour); | ||||||
|  |         float calculateWindSpeed(int weatherId, float currentSpeed); | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue