Index: source/graphics/GameView.cpp =================================================================== --- source/graphics/GameView.cpp +++ source/graphics/GameView.cpp @@ -581,7 +581,9 @@ const CVector3D nearPoint = position + forwards * m->ViewNear; const CVector3D pivotPoint = position + forwards * m->Zoom.GetSmoothedValue(); - const float ground = m->Game->GetWorld()->GetTerrain()->GetExactGroundLevel(nearPoint.X, nearPoint.Z); + const float ground = std::max( + m->Game->GetWorld()->GetTerrain()->GetExactGroundLevel(nearPoint.X, nearPoint.Z), + g_Renderer.GetWaterManager()->m_WaterHeight); // filter ground levels for smooth camera movement const float filtered_near_ground = m->Game->GetWorld()->GetTerrain()->GetFilteredGroundLevel(nearPoint.X, nearPoint.Z, near_radius); Index: source/renderer/WaterManager.h =================================================================== --- source/renderer/WaterManager.h +++ source/renderer/WaterManager.h @@ -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 @@ -155,6 +155,11 @@ void UnloadWaterTextures(); /** + * RecomputeWaterData: calculates all derived data from the waterheight + */ + void RecomputeWaterData(); + + /** * RecomputeWindStrength: calculates the intensity of waves */ void RecomputeWindStrength(); Index: source/renderer/WaterManager.cpp =================================================================== --- source/renderer/WaterManager.cpp +++ source/renderer/WaterManager.cpp @@ -417,12 +417,14 @@ // 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. @@ -944,6 +946,9 @@ // Calculate The blurred normal map to get an idea of where water ought to go. void WaterManager::RecomputeBlurredNormalMap() { + if (!g_Game->GetWorld()->GetTerrain()->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) @@ -997,6 +1002,17 @@ 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 +1022,9 @@ 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)); Index: source/simulation2/components/CCmpTerrain.cpp =================================================================== --- source/simulation2/components/CCmpTerrain.cpp +++ source/simulation2/components/CCmpTerrain.cpp @@ -146,10 +146,7 @@ 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); } Index: source/simulation2/components/CCmpWaterManager.cpp =================================================================== --- source/simulation2/components/CCmpWaterManager.cpp +++ source/simulation2/components/CCmpWaterManager.cpp @@ -67,6 +67,10 @@ Init(paramNode); deserialize.NumberFixed_Unbounded("height", m_WaterHeight); + + // Only update the graphical water height if it differs from the inital setting of the map + if (m_WaterHeight.ToFloat() != g_Renderer.GetWaterManager()->m_WaterHeight) + RecomputeWaterData(); } virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)) @@ -97,10 +101,8 @@ { 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 +116,7 @@ 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);