1
0
forked from 0ad/0ad

Recompute water graphics when changing the water level and upon deserialization to fix a graphical (non-simulation) OOS on rejoin.

Differential Revision: https://code.wildfiregames.com/D638
Refs #4596
Contains a fix mentioned by leper.

This was SVN commit r19862.
This commit is contained in:
elexis 2017-07-01 04:15:49 +00:00
parent 36b315ca32
commit c67d79d9f3
4 changed files with 36 additions and 18 deletions

View File

@ -417,12 +417,14 @@ void WaterManager::UnloadWaterTextures()
// Calculate our binary heightmap from the terrain heightmap.
void WaterManager::RecomputeDistanceHeightmap()
{
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
if (!terrain || !terrain->GetHeightMap())
return;
size_t SideSize = m_MapSize*2;
if (m_DistanceHeightmap == NULL)
m_DistanceHeightmap = new float[SideSize*SideSize];
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
// Create a manhattan-distance heightmap.
// This is currently upsampled by a factor of 2 to get more precision
// This could be refined to only be done near the coast itself, but it's probably not necessary.
@ -483,6 +485,8 @@ void WaterManager::CreateWaveMeshes()
{
size_t SideSize = m_MapSize*2;
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
if (!terrain || !terrain->GetHeightMap())
return;
for (WaveObject* const& obj : m_ShoreWaves)
{
@ -944,13 +948,15 @@ void WaterManager::RenderWaves(const CFrustum& frustrum)
// Calculate The blurred normal map to get an idea of where water ought to go.
void WaterManager::RecomputeBlurredNormalMap()
{
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
if (!terrain || !terrain->GetHeightMap())
return;
// used to cache terrain normals since otherwise we'd recalculate them a lot (I'm blurring the "normal" map).
// this might be updated to actually cache in the terrain manager but that's not for now.
if (m_BlurredNormalMap == NULL)
m_BlurredNormalMap = new CVector3D[m_MapSize*m_MapSize];
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
// It's really slow to calculate normals so cache them first.
CVector3D* normals = new CVector3D[m_MapSize*m_MapSize];
@ -997,6 +1003,17 @@ void WaterManager::RecomputeBlurredNormalMap()
delete[] normals;
}
void WaterManager::RecomputeWaterData()
{
if (!m_MapSize)
return;
RecomputeBlurredNormalMap();
RecomputeDistanceHeightmap();
RecomputeWindStrength();
CreateWaveMeshes();
}
///////////////////////////////////////////////////////////////////
// Calculate the strength of the wind at a given point on the map.
// This is too slow and should support limited recomputation.
@ -1006,6 +1023,9 @@ void WaterManager::RecomputeWindStrength()
m_WindStrength = new float[m_MapSize*m_MapSize];
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
if (!terrain || !terrain->GetHeightMap())
return;
float waterLevel = m_WaterHeight;
CVector2D windDir = CVector2D(cos(m_WindAngle),sin(m_WindAngle));

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2012 Wildfire Games.
/* Copyright (C) 2017 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -154,6 +154,11 @@ public:
*/
void UnloadWaterTextures();
/**
* RecomputeWaterData: calculates all derived data from the waterheight
*/
void RecomputeWaterData();
/**
* RecomputeWindStrength: calculates the intensity of waves
*/

View File

@ -146,10 +146,7 @@ public:
if (ReloadWater && CRenderer::IsInitialised())
{
g_Renderer.GetWaterManager()->SetMapSize(vertices);
g_Renderer.GetWaterManager()->RecomputeBlurredNormalMap();
g_Renderer.GetWaterManager()->RecomputeDistanceHeightmap();
g_Renderer.GetWaterManager()->RecomputeWindStrength();
g_Renderer.GetWaterManager()->CreateWaveMeshes();
g_Renderer.GetWaterManager()->RecomputeWaterData();
}
MakeDirty(0, 0, tiles+1, tiles+1);
}

View File

@ -67,6 +67,8 @@ public:
Init(paramNode);
deserialize.NumberFixed_Unbounded("height", m_WaterHeight);
RecomputeWaterData();
}
virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
@ -97,10 +99,8 @@ public:
{
if (CRenderer::IsInitialised())
{
g_Renderer.GetWaterManager()->RecomputeBlurredNormalMap();
g_Renderer.GetWaterManager()->RecomputeDistanceHeightmap();
g_Renderer.GetWaterManager()->RecomputeWindStrength();
g_Renderer.GetWaterManager()->CreateWaveMeshes();
g_Renderer.GetWaterManager()->RecomputeWaterData();
g_Renderer.GetWaterManager()->m_WaterHeight = m_WaterHeight.ToFloat();
}
// Tell the terrain it'll need to recompute its cached render data
@ -114,11 +114,7 @@ public:
m_WaterHeight = h;
// Tell the terrain it'll need to recompute its cached render data
GetSimContext().GetTerrain().MakeDirty(RENDERDATA_UPDATE_VERTICES);
if (CRenderer::IsInitialised())
g_Renderer.GetWaterManager()->m_WaterHeight = h.ToFloat();
RecomputeWaterData();
CMessageWaterChanged msg;
GetSimContext().GetComponentManager().BroadcastMessage(msg);