From 15ec863aec39d7cc06df00dfc8b96eeafe740ab3 Mon Sep 17 00:00:00 2001 From: wraitii Date: Sun, 5 Jan 2014 16:15:20 +0000 Subject: [PATCH] Substantial speed-up of the foam generation code. Remove waves for now as they were unsatisfactory. Removes "shininess" as a water parameter as it was basically useless. Add a button in Atlas to recompute water parameters so you can now see fog in Atlas. Fixes #1743, #1803 (invalid) Refs #1875, #2114, #48. This was SVN commit r14514. --- .../public/maps/random/rmgen/environment.js | 6 - .../mods/public/maps/random/rmgen/mapgen.js | 1 - .../mods/public/shaders/glsl/model_water.fs | 4 +- .../mods/public/shaders/glsl/water_high.fs | 6 +- source/graphics/MapReader.cpp | 7 +- source/graphics/MapWriter.cpp | 1 - source/ps/CStrInternStatic.h | 1 - source/renderer/TerrainRenderer.cpp | 6 +- source/renderer/WaterManager.cpp | 135 +++++++++--------- source/renderer/WaterManager.h | 1 - .../components/CCmpWaterManager.cpp | 19 ++- .../components/ICmpWaterManager.cpp | 1 + .../simulation2/components/ICmpWaterManager.h | 5 + .../Sections/Environment/Environment.cpp | 16 ++- .../Sections/Environment/Environment.h | 3 + .../Handlers/EnvironmentHandlers.cpp | 26 +++- source/tools/atlas/GameInterface/Messages.h | 3 +- 17 files changed, 145 insertions(+), 96 deletions(-) diff --git a/binaries/data/mods/public/maps/random/rmgen/environment.js b/binaries/data/mods/public/maps/random/rmgen/environment.js index a7041b160c..06123f75f0 100644 --- a/binaries/data/mods/public/maps/random/rmgen/environment.js +++ b/binaries/data/mods/public/maps/random/rmgen/environment.js @@ -56,12 +56,6 @@ function setWaterHeight(h) WATER_LEVEL_CHANGED = true; } -// Set water shininess -function setWaterShininess(s) -{ - g_Environment.Water.WaterBody.Shininess = s; -} - // Set water waviness function setWaterWaviness(w) { diff --git a/binaries/data/mods/public/maps/random/rmgen/mapgen.js b/binaries/data/mods/public/maps/random/rmgen/mapgen.js index 0c4b34585f..b022df739f 100644 --- a/binaries/data/mods/public/maps/random/rmgen/mapgen.js +++ b/binaries/data/mods/public/maps/random/rmgen/mapgen.js @@ -15,7 +15,6 @@ var g_Environment = { Type: "default", Colour: {r: 0.3, g: 0.35, b: 0.7, a: 0}, Height: 5, - Shininess: 150, Waviness: 8, Murkiness: 0.45, Tint: {r: 0.28, g: 0.3, b: 0.59, a: 0}, diff --git a/binaries/data/mods/public/shaders/glsl/model_water.fs b/binaries/data/mods/public/shaders/glsl/model_water.fs index 26906e2465..78f04d81c8 100644 --- a/binaries/data/mods/public/shaders/glsl/model_water.fs +++ b/binaries/data/mods/public/shaders/glsl/model_water.fs @@ -34,8 +34,6 @@ uniform vec3 sunColor; uniform vec3 sunDir; uniform vec3 cameraPos; - -uniform float shininess; uniform float specularStrength; uniform float waviness; uniform vec3 waterTint; @@ -124,7 +122,7 @@ void main() refrColor = (0.5 + 0.5*ndotl) * mix(vec3(0.3), sunColor * waterTint, murkiness * clamp(waterDepth / fullDepth, 0.0, 1.0)); // Murkiness and tint at this pixel (tweaked based on lighting and depth) - specular = pow(max(0.0, ndoth), shininess) * sunColor * specularStrength; + specular = pow(max(0.0, ndoth), 150.0f) * sunColor * specularStrength; losMod = texture2D(losTex, v_los).a; diff --git a/binaries/data/mods/public/shaders/glsl/water_high.fs b/binaries/data/mods/public/shaders/glsl/water_high.fs index 07fcdb4192..830f17d998 100644 --- a/binaries/data/mods/public/shaders/glsl/water_high.fs +++ b/binaries/data/mods/public/shaders/glsl/water_high.fs @@ -5,7 +5,6 @@ uniform vec3 sunDir; uniform vec3 sunColor; uniform vec3 cameraPos; uniform sampler2D losMap; -uniform float shininess; // Blinn-Phong specular strength uniform float specularStrength; // Scaling for specular reflection (specular color is (this,this,this)) uniform float waviness; // "Wildness" of the reflections and refractions; choose based on texture uniform vec3 tint; // Tint for refraction (used to simulate particles in water) @@ -102,8 +101,7 @@ void main() vec2 beachOrientation = heightmapval.rg; float distToShore = heightmapval.b; #endif - - + vec3 n, l, h, v; // Normal, light vector, half-vector and view vector (vector to eye) float ndotl, ndoth, ndotv; float fresnel; @@ -185,7 +183,7 @@ void main() // texture is not rotated, moves twice faster in the opposite direction, translated. vec2 foam2RC = gl_TexCoord[0].st*1.8 + vec2(time*-0.019,time*-0.012) - 0.012*n.xz + vec2(0.4,0.2); - vec2 WaveRocking = cos(time*1.2566) * beachOrientation * clamp(1.0 - distToShore,0.1,1.0)/3.0; + vec2 WaveRocking = cos(time*1.2566) * beachOrientation * clamp(1.0 - distToShore*0.8,0.1,1.0)/3.0; vec4 foam1 = texture2D(Foam, foam1RC + vec2(-WaveRocking.t,WaveRocking.s)); vec4 foam2 = foam1.r*texture2D(Foam, foam2RC + WaveRocking); diff --git a/source/graphics/MapReader.cpp b/source/graphics/MapReader.cpp index 9bb4b264f0..8db47f457f 100644 --- a/source/graphics/MapReader.cpp +++ b/source/graphics/MapReader.cpp @@ -583,7 +583,7 @@ void CXMLReader::ReadEnvironment(XMBElement parent) EL(type); EL(colour); EL(height); - EL(shininess); + EL(shininess); // for compatibility EL(waviness); EL(murkiness); EL(tint); @@ -718,6 +718,8 @@ void CXMLReader::ReadEnvironment(XMBElement parent) if (!m_MapReader.pWaterMan) continue; + float this_avoids_a_warning_about_unused_variables = 0; + if (element_name == el_type) { // TODO: implement this, when WaterManager supports it @@ -740,7 +742,7 @@ void CXMLReader::ReadEnvironment(XMBElement parent) } \ READ_COLOUR(el_colour, m_MapReader.pWaterMan->m_WaterColor) - READ_FLOAT(el_shininess, m_MapReader.pWaterMan->m_Shininess) + READ_FLOAT(el_shininess, this_avoids_a_warning_about_unused_variables) READ_FLOAT(el_waviness, m_MapReader.pWaterMan->m_Waviness) READ_FLOAT(el_murkiness, m_MapReader.pWaterMan->m_Murkiness) READ_COLOUR(el_tint, m_MapReader.pWaterMan->m_WaterTint) @@ -1461,7 +1463,6 @@ int CMapReader::ParseEnvironment() // TODO: Water type not implemented GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Colour, pWaterMan->m_WaterColor) - GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Shininess, pWaterMan->m_Shininess) GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Waviness, pWaterMan->m_Waviness) GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Murkiness, pWaterMan->m_Murkiness) GET_ENVIRONMENT_PROPERTY(waterBodyObj.get(), Tint, pWaterMan->m_WaterTint) diff --git a/source/graphics/MapWriter.cpp b/source/graphics/MapWriter.cpp index f1015c1044..c67cbe8bea 100644 --- a/source/graphics/MapWriter.cpp +++ b/source/graphics/MapWriter.cpp @@ -256,7 +256,6 @@ void CMapWriter::WriteXML(const VfsPath& filename, CmpPtr cmpWaterManager(*pSimulation2, SYSTEM_ENTITY); ENSURE(cmpWaterManager); XML_Setting("Height", cmpWaterManager->GetExactWaterLevel(0, 0)); - XML_Setting("Shininess", pWaterMan->m_Shininess); XML_Setting("Waviness", pWaterMan->m_Waviness); XML_Setting("Murkiness", pWaterMan->m_Murkiness); { diff --git a/source/ps/CStrInternStatic.h b/source/ps/CStrInternStatic.h index 0e85771002..6a6d292529 100644 --- a/source/ps/CStrInternStatic.h +++ b/source/ps/CStrInternStatic.h @@ -126,7 +126,6 @@ X(shadingColor) X(shadowScale) X(shadowTex) X(shadowTransform) -X(shininess) X(skinBlendMatrices) X2(skinBlendMatrices_0, "skinBlendMatrices[0]") X(skyCube) diff --git a/source/renderer/TerrainRenderer.cpp b/source/renderer/TerrainRenderer.cpp index 7c956e494a..657915dc3d 100644 --- a/source/renderer/TerrainRenderer.cpp +++ b/source/renderer/TerrainRenderer.cpp @@ -658,7 +658,7 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap* defines.Add(str_USE_NORMALS, str_1); if (WaterMgr->m_WaterRealDepth) defines.Add(str_USE_REAL_DEPTH, str_1); - if (WaterMgr->m_WaterFoam && !g_AtlasGameLoop->running) + if (WaterMgr->m_WaterFoam) defines.Add(str_USE_FOAM, str_1); if (WaterMgr->m_WaterCoastalWaves && !g_AtlasGameLoop->running) defines.Add(str_USE_WAVES, str_1); @@ -747,7 +747,8 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap* GLuint FramebufferName = 0; // rendering waves to a framebuffer - if (WaterMgr->m_WaterCoastalWaves && WaterMgr->m_VBWaves && !g_AtlasGameLoop->running) + // TODO: reactivate this with something that looks good. + if (false && WaterMgr->m_WaterCoastalWaves && WaterMgr->m_VBWaves && !g_AtlasGameLoop->running) { // Save the post-processing framebuffer. GLint fbo; @@ -840,7 +841,6 @@ bool TerrainRenderer::RenderFancyWater(const CShaderDefines& context, ShadowMap* m->fancyWaterShader->Uniform(str_sunDir, lightEnv.GetSunDir()); m->fancyWaterShader->Uniform(str_sunColor, lightEnv.m_SunColor.X); m->fancyWaterShader->Uniform(str_color, WaterMgr->m_WaterColor); - m->fancyWaterShader->Uniform(str_shininess, WaterMgr->m_Shininess); m->fancyWaterShader->Uniform(str_specularStrength, WaterMgr->m_SpecularStrength); m->fancyWaterShader->Uniform(str_waviness, WaterMgr->m_Waviness); m->fancyWaterShader->Uniform(str_murkiness, WaterMgr->m_Murkiness); diff --git a/source/renderer/WaterManager.cpp b/source/renderer/WaterManager.cpp index b9bffc221d..af34911377 100644 --- a/source/renderer/WaterManager.cpp +++ b/source/renderer/WaterManager.cpp @@ -70,7 +70,6 @@ WaterManager::WaterManager() m_ReflectionTextureSize = 0; m_RefractionTextureSize = 0; m_WaterTexTimer = 0.0; - m_Shininess = 150.0f; m_SpecularStrength = 0.6f; m_Waviness = 8.0f; m_ReflectionTint = CColor(0.28f, 0.3f, 0.59f, 1.0f); @@ -268,11 +267,18 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation) m_WaterHeight = cmpWaterManager->GetExactWaterLevel(0,0); // Get the square we want to work on. - i32 Xstart = clamp(m_updatei0, 0, (i32)m_MapSize-1); - i32 Xend = clamp(m_updatei1, 0, (i32)m_MapSize-1); - i32 Zstart = clamp(m_updatej0, 0, (i32)m_MapSize-1); - i32 Zend = clamp(m_updatej1, 0, (i32)m_MapSize-1); + ssize_t Xstart = m_updatei0 < 0 ? 0 : (m_updatei0 >= (ssize_t)m_MapSize ? (ssize_t)m_MapSize-1 : m_updatei0); + ssize_t Xend = m_updatei1 < 0 ? 0 : (m_updatei1 >= (ssize_t)m_MapSize ? (ssize_t)m_MapSize-1 : m_updatei1); + ssize_t Zstart = m_updatej0 < 0 ? 0 : (m_updatej0 >= (ssize_t)m_MapSize ? (ssize_t)m_MapSize-1 : m_updatej0); + ssize_t Zend = m_updatej1 < 0 ? 0 : (m_updatej1 >= (ssize_t)m_MapSize ? (ssize_t)m_MapSize-1 : m_updatej1); + if (!(Xend > Xstart && Zend > Zstart)) + { + // it corrupts every now and then for reasons I don't get. + std::cout << m_updatei0 << " , " << Xstart << std::endl; + std::cout << m_MapSize << "," << (ssize_t)m_MapSize << std::endl; + } + if (m_WaveX == NULL) { m_WaveX = new float[m_MapSize*m_MapSize]; @@ -291,13 +297,13 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation) // this might be updated to actually cache in the terrain manager but that's not for now. CVector3D* normals = new CVector3D[m_MapSize*m_MapSize]; - // taken out of the bottom loop, blurs the normal map // To remove if below is reactivated ssize_t blurZstart = Zstart-4 < 0 ? 0 : Zstart - 4; ssize_t blurZend = Zend+4 >= (ssize_t)m_MapSize ? (ssize_t)m_MapSize-1 : Zend + 4; ssize_t blurXstart = Xstart-4 < 0 ? 0 : Xstart - 4; ssize_t blurXend = Xend+4 >= (ssize_t)m_MapSize ? (ssize_t)m_MapSize-1 : Xend + 4; + for (ssize_t j = blurZstart; j < blurZend; ++j) { for (ssize_t i = blurXstart; i < blurXend; ++i) @@ -339,113 +345,107 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation) { for (ssize_t i = Xstart; i < Xend; ++i) { + ssize_t index = j*m_MapSize + i; if (circular && (i-halfSize)*(i-halfSize)+(j-halfSize)*(j-halfSize) > mSize) { - m_WaveX[j*m_MapSize + i] = 0.0f; - m_WaveZ[j*m_MapSize + i] = 0.0f; - m_DistanceToShore[j*m_MapSize + i] = 100; - m_FoamFactor[j*m_MapSize + i] = 0.0f; + m_WaveX[index] = 0.0f; + m_WaveZ[index] = 0.0f; + m_DistanceToShore[index] = 100; + m_FoamFactor[index] = 0.0f; continue; } - float depth = m_WaterHeight - heightmap[j*m_MapSize + i]*HEIGHT_SCALE; - int distanceToShore = 10000; + float depth = m_WaterHeight - heightmap[index]*HEIGHT_SCALE; + float distanceToShore = 10000; // calculation of the distance to the shore. - // TODO: this is fairly dumb, though it returns a good result - // Could be sped up a fair bit. - if (depth >= 0) + if (i > 0 && i < (ssize_t)m_MapSize-1 && j > 0 && j < (ssize_t)m_MapSize-1) { - // check in the square around. - for (int yy = -5; yy <= 5; ++yy) + // search a 5x5 array with us in the center (do not search me) + // much faster since we spiral search and can just stop once we've found the shore. + // also everything is precomputed and we get exact results instead. + int offset[24] = { -1,1,-m_MapSize,+m_MapSize, -1-m_MapSize,+1-m_MapSize,-1+m_MapSize,1+m_MapSize, + -2,2,-2*m_MapSize,2*m_MapSize,-2-m_MapSize,-2+m_MapSize,2-m_MapSize,2+m_MapSize, + -1-2*m_MapSize,+1-2*m_MapSize,-1+2*m_MapSize,1+2*m_MapSize, + -2-2*m_MapSize,2+2*m_MapSize,-2+2*m_MapSize,2-2*m_MapSize }; + float dist[24] = { 1.0f, 1.0f, 1.0f, 1.0f, 1.414f, 1.414f, 1.414f, 1.414f, + 2.0f, 2.0f, 2.0f, 2.0f, 2.236f, 2.236f, 2.236f, 2.236f, + 2.236f, 2.236f, 2.236f, 2.236f, + 2.828f, 2.828f, 2.828f, 2.828f }; + + int max = 8; + if (i > 1 && i < (ssize_t)m_MapSize-2 && j > 1 && j < (ssize_t)m_MapSize-2) + max = 24; + + for(int lookupI = 0; lookupI < max;++lookupI) { - for (int xx = -5; xx <= 5; ++xx) - { - if (i+xx >= 0 && i + xx < (long)m_MapSize) - if (j + yy >= 0 && j + yy < (long)m_MapSize) - { - float hereDepth = m_WaterHeight - heightmap[(j+yy)*m_MapSize + (i+xx)]*HEIGHT_SCALE; - if (hereDepth < 0 && xx*xx + yy*yy < distanceToShore) - distanceToShore = xx*xx + yy*yy; - } - } + float hereDepth = m_WaterHeight - heightmap[index+offset[lookupI]]*HEIGHT_SCALE; + distanceToShore = hereDepth <= 0 && depth >= 0 ? dist[lookupI] : (depth < 0 ? 1 : distanceToShore); + if (distanceToShore != 10000) + break; } - // refine the calculation if we're close enough - if (distanceToShore < 9) - { - for (float yy = -2.5f; yy <= 2.5f; ++yy) + } else { + // revert to for and if-based because I can't be bothered to special case all that. + for (int xx = -1; xx <= 1;++xx) + for (int yy = -1; yy <= 1;++yy) { - for (float xx = -2.5f; xx <= 2.5f; ++xx) + if (i+xx >= 0 && i+xx < (ssize_t)m_MapSize && j+yy >= 0 && j+yy < (ssize_t)m_MapSize) { - float hereDepth = m_WaterHeight - terrain->GetExactGroundLevel( (i+xx)*4, (j+yy)*4 ); - if (hereDepth < 0 && xx*xx + yy*yy < distanceToShore) - distanceToShore = xx*xx + yy*yy; + float hereDepth = m_WaterHeight - heightmap[index+xx+yy*m_MapSize]*HEIGHT_SCALE; + distanceToShore = (hereDepth < 0 && sqrt((double)xx*xx+yy*yy) < distanceToShore) ? sqrt((double)xx*xx+yy*yy) : distanceToShore; } } - } - } - else - { - for (int yy = -2; yy <= 2; ++yy) - { - for (int xx = -2; xx <= 2; ++xx) - { - float hereDepth = m_WaterHeight - terrain->GetVertexGroundLevel(i+xx, j+yy); - if (hereDepth > 0) - distanceToShore = 0; - } - } - } + // speedup with default values for land squares if (distanceToShore == 10000) { - m_WaveX[j*m_MapSize + i] = 0.0f; - m_WaveZ[j*m_MapSize + i] = 0.0f; - m_DistanceToShore[j*m_MapSize + i] = 100; - m_FoamFactor[j*m_MapSize + i] = 0.0f; + m_WaveX[index] = 0.0f; + m_WaveZ[index] = 0.0f; + m_DistanceToShore[index] = 100.0f; + m_FoamFactor[index] = 0.0f; continue; } + // We'll compute the normals and the "water raise", to know about foam // Normals are a pretty good calculation but it's slow since we normalize so much. CVector3D normal; int waterRaise = 0; - for (int yy = -4; yy <= 4; yy += 2) + for (int yy = -3; yy <= 3; yy += 2) { - for (int xx = -4; xx <= 4; xx += 2) // every 2 tile is good enough. + for (int xx = -3; xx <= 3; xx += 2) // every 2 tile is good enough. { if (j+yy < (long)m_MapSize && i+xx < (long)m_MapSize && i+xx >= 0 && j+yy >= 0) normal += normals[(j+yy)*m_MapSize + (i+xx)]; - if (terrain->GetVertexGroundLevel(i+xx,j+yy) < heightmap[j*m_MapSize + i]*HEIGHT_SCALE) - waterRaise += heightmap[j*m_MapSize + i]*HEIGHT_SCALE - terrain->GetVertexGroundLevel(i+xx,j+yy); + waterRaise += heightmap[index]*HEIGHT_SCALE - terrain->GetVertexGroundLevel(i+xx,j+yy) > 0 ? heightmap[index]*HEIGHT_SCALE - terrain->GetVertexGroundLevel(i+xx,j+yy) : 0.0f; } } // normalizes the terrain info to avoid foam moving at too different speeds. - normal *= 0.012345679f; + normal *= 0.08f; normal[1] = 0.1f; normal = normal.Normalized(); - m_WaveX[j*m_MapSize + i] = normal[0]; - m_WaveZ[j*m_MapSize + i] = normal[2]; + m_WaveX[index] = normal[0]; + m_WaveZ[index] = normal[2]; // distance is /5.0 to be a [0,1] value. - m_DistanceToShore[j*m_MapSize + i] = sqrtf(distanceToShore)/5.0f; // TODO: this can probably be cached as I'm integer here. + m_DistanceToShore[index] = distanceToShore; // computing the amount of foam I want - depth = clamp(depth,0.0f,10.0f); float foamAmount = (waterRaise/255.0f) * (1.0f - depth/10.0f) /** (waveForceHQ[j*m_MapSize+i]/255.0f)*/ * (m_Waviness/8.0f); - foamAmount += clamp(m_Waviness/2.0f - distanceToShore,0.0f,m_Waviness/2.0f)/(m_Waviness/2.0f) * clamp(m_Waviness/9.0f,0.3f,1.0f); - foamAmount = foamAmount > 1.0f ? 1.0f: foamAmount; + foamAmount += clamp(m_Waviness/2.0f,0.0f,m_Waviness/2.0f)/(m_Waviness/2.0f) * clamp(m_Waviness/9.0f,0.3f,1.0f); + foamAmount *= (m_Waviness/4.0f - distanceToShore); + foamAmount = foamAmount > 1.0f ? 1.0f: (foamAmount < 0.0f ? 0.0f : foamAmount); - m_FoamFactor[j*m_MapSize + i] = foamAmount; + m_FoamFactor[index] = foamAmount; } } delete[] normals; //delete[] waveForceHQ; - // TODO: The rest should be cleaned up - + // TODO: reactivate this with something that looks good and is efficient. +/* // okay let's create the waves squares. i'll divide the map in arbitrary squares // For each of these squares, check if waves are needed. // If yes, look for the best positionning (in order to have a nice blending with the shore) @@ -604,6 +604,7 @@ void WaterManager::CreateSuperfancyInfo(CSimulation2* simulation) // Construct indices buffer m_VBWavesIndices = g_VBMan.Allocate(sizeof(GLushort), waves_indices.size(), GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER); m_VBWavesIndices->m_Owner->UpdateChunkVertices(m_VBWavesIndices, &waves_indices[0]); + */ } //////////////////////////////////////////////////////////////////////// diff --git a/source/renderer/WaterManager.h b/source/renderer/WaterManager.h index 048684534f..50e6876a0b 100644 --- a/source/renderer/WaterManager.h +++ b/source/renderer/WaterManager.h @@ -115,7 +115,6 @@ public: // Shader parameters for fancy water CColor m_WaterTint; float m_RepeatPeriod; - float m_Shininess; float m_SpecularStrength; float m_Waviness; float m_Murkiness; diff --git a/source/simulation2/components/CCmpWaterManager.cpp b/source/simulation2/components/CCmpWaterManager.cpp index f92ab6bbce..3a2b34e7a7 100644 --- a/source/simulation2/components/CCmpWaterManager.cpp +++ b/source/simulation2/components/CCmpWaterManager.cpp @@ -26,6 +26,8 @@ #include "renderer/WaterManager.h" #include "simulation2/MessageTypes.h" +#include "tools/atlas/GameInterface/GameLoop.h" + class CCmpWaterManager : public ICmpWaterManager { public: @@ -81,7 +83,9 @@ public: case MT_TerrainChanged: { // Tell the renderer to redraw the map. - if (CRenderer::IsInitialised()) + // TODO: sometimes atlas glitches out. + // I've added a button to recompute on demand but that's not extremely nice. + if (CRenderer::IsInitialised() && !g_AtlasGameLoop->running) { const CMessageTerrainChanged& msgData = static_cast (msg); g_Renderer.GetWaterManager()->m_NeedInfoUpdate = true; @@ -97,6 +101,19 @@ public: } } + virtual void RecomputeWaterData() + { + ssize_t mapSize = GetSimContext().GetTerrain().GetVerticesPerSide(); + g_Renderer.GetWaterManager()->m_NeedInfoUpdate = true; + g_Renderer.GetWaterManager()->m_updatei0 = 0; + g_Renderer.GetWaterManager()->m_updatej0 = 0; + g_Renderer.GetWaterManager()->m_updatei1 = mapSize-1; + g_Renderer.GetWaterManager()->m_updatej1 = mapSize-1; + + // Tell the terrain it'll need to recompute its cached render data + GetSimContext().GetTerrain().MakeDirty(RENDERDATA_UPDATE_VERTICES); + } + virtual void SetWaterLevel(entity_pos_t h) { m_WaterHeight = h; diff --git a/source/simulation2/components/ICmpWaterManager.cpp b/source/simulation2/components/ICmpWaterManager.cpp index a7e64ca45d..487ccb8841 100644 --- a/source/simulation2/components/ICmpWaterManager.cpp +++ b/source/simulation2/components/ICmpWaterManager.cpp @@ -22,6 +22,7 @@ #include "simulation2/system/InterfaceScripted.h" BEGIN_INTERFACE_WRAPPER(WaterManager) +DEFINE_INTERFACE_METHOD_0("RecomputeWaterData", void, ICmpWaterManager, RecomputeWaterData) DEFINE_INTERFACE_METHOD_1("SetWaterLevel", void, ICmpWaterManager, SetWaterLevel, entity_pos_t) DEFINE_INTERFACE_METHOD_2("GetWaterLevel", entity_pos_t, ICmpWaterManager, GetWaterLevel, entity_pos_t, entity_pos_t) END_INTERFACE_WRAPPER(WaterManager) diff --git a/source/simulation2/components/ICmpWaterManager.h b/source/simulation2/components/ICmpWaterManager.h index dc6cdf2b8f..03915fc1af 100644 --- a/source/simulation2/components/ICmpWaterManager.h +++ b/source/simulation2/components/ICmpWaterManager.h @@ -25,6 +25,11 @@ class ICmpWaterManager : public IComponent { public: + /** + * Recompute all the water information (foam…) + */ + virtual void RecomputeWaterData() = 0; + /** * Set the height of the water level, as a constant value across the whole map. */ diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.cpp b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.cpp index 4ca083c69e..380f687b3b 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.cpp +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.cpp @@ -197,6 +197,9 @@ END_EVENT_TABLE() ////////////////////////////////////////////////////////////////////////// +enum { + ID_RecomputeWaterData +}; static void SendToGame(const AtlasMessage::sEnvironmentSettings& settings) { POST_COMMAND(SetEnvironmentSettings, (settings)); @@ -213,9 +216,8 @@ EnvironmentSidebar::EnvironmentSidebar(ScenarioEditor& scenarioEditor, wxWindow* wxSizer* waterSizer = new wxStaticBoxSizer(wxVERTICAL, scrolledWindow, _T("Water settings")); scrollSizer->Add(waterSizer, wxSizerFlags().Expand()); - + waterSizer->Add(new wxButton(this, ID_RecomputeWaterData, _("Reset Water Data")), wxSizerFlags().Expand()); waterSizer->Add(new VariableSliderBox(scrolledWindow, _("Water height"), g_EnvironmentSettings.waterheight, 0.f, 1.2f), wxSizerFlags().Expand()); - waterSizer->Add(new VariableSliderBox(scrolledWindow, _("Water shininess"), g_EnvironmentSettings.watershininess, 0.f, 250.f), wxSizerFlags().Expand()); waterSizer->Add(new VariableSliderBox(scrolledWindow, _("Water waviness"), g_EnvironmentSettings.waterwaviness, 0.f, 10.f), wxSizerFlags().Expand()); waterSizer->Add(new VariableSliderBox(scrolledWindow, _("Water murkiness"), g_EnvironmentSettings.watermurkiness, 0.f, 1.f), wxSizerFlags().Expand()); waterSizer->Add(new VariableColourBox(scrolledWindow, _("Water colour"), g_EnvironmentSettings.watercolour), wxSizerFlags().Expand()); @@ -277,3 +279,13 @@ void EnvironmentSidebar::OnMapReload() g_EnvironmentSettings.NotifyObservers(); } + +void EnvironmentSidebar::RecomputeWaterData(wxCommandEvent& evt) +{ + POST_COMMAND(RecalculateWaterData, (0.0f)); +} + +BEGIN_EVENT_TABLE(EnvironmentSidebar, Sidebar) + EVT_BUTTON(ID_RecomputeWaterData, EnvironmentSidebar::RecomputeWaterData) +END_EVENT_TABLE(); + diff --git a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.h b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.h index b53bd80751..9e16f34e0e 100644 --- a/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.h +++ b/source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Environment/Environment.h @@ -27,6 +27,7 @@ public: EnvironmentSidebar(ScenarioEditor& scenarioEditor, wxWindow* sidebarContainer, wxWindow* bottomBarContainer); virtual void OnMapReload(); + virtual void RecomputeWaterData(wxCommandEvent& evt); protected: virtual void OnFirstDisplay(); @@ -35,4 +36,6 @@ private: VariableListBox* m_PostEffectList; VariableListBox* m_SkyList; ObservableScopedConnection m_Conn; + + DECLARE_EVENT_TABLE(); }; diff --git a/source/tools/atlas/GameInterface/Handlers/EnvironmentHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/EnvironmentHandlers.cpp index 68faa9c317..5a2e9a18f2 100644 --- a/source/tools/atlas/GameInterface/Handlers/EnvironmentHandlers.cpp +++ b/source/tools/atlas/GameInterface/Handlers/EnvironmentHandlers.cpp @@ -44,7 +44,6 @@ sEnvironmentSettings GetSettings() s.waterheight = cmpWaterManager->GetExactWaterLevel(0, 0) / (65536.f * HEIGHT_SCALE); WaterManager* wm = g_Renderer.GetWaterManager(); - s.watershininess = wm->m_Shininess; s.waterwaviness = wm->m_Waviness; s.watermurkiness = wm->m_Murkiness; s.waterreflectiontintstrength = wm->m_ReflectionTintStrength; @@ -100,7 +99,6 @@ void SetSettings(const sEnvironmentSettings& s) cmpWaterManager->SetWaterLevel(entity_pos_t::FromFloat(s.waterheight * (65536.f * HEIGHT_SCALE))); WaterManager* wm = g_Renderer.GetWaterManager(); - wm->m_Shininess = s.watershininess; wm->m_Waviness = s.waterwaviness; wm->m_Murkiness = s.watermurkiness; wm->m_ReflectionTintStrength = s.waterreflectiontintstrength; @@ -169,6 +167,30 @@ BEGIN_COMMAND(SetEnvironmentSettings) }; END_COMMAND(SetEnvironmentSettings) +BEGIN_COMMAND(RecalculateWaterData) +{ + void Do() + { + Redo(); + } + + void Redo() + { + CmpPtr cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); + ENSURE(cmpWaterManager); + + cmpWaterManager->RecomputeWaterData(); + } + + void Undo() + { + Redo(); + } + +}; +END_COMMAND(RecalculateWaterData) + + QUERYHANDLER(GetEnvironmentSettings) { msg->settings = GetSettings(); diff --git a/source/tools/atlas/GameInterface/Messages.h b/source/tools/atlas/GameInterface/Messages.h index 48ce2809ae..ae665ff2c1 100644 --- a/source/tools/atlas/GameInterface/Messages.h +++ b/source/tools/atlas/GameInterface/Messages.h @@ -422,7 +422,6 @@ MESSAGE(SetView, struct sEnvironmentSettings { Shareable waterheight; // range 0..1 corresponds to min..max terrain height; out-of-bounds values allowed - Shareable watershininess; // range ??? Shareable waterwaviness; // range ??? Shareable watermurkiness; // range ??? @@ -471,6 +470,8 @@ COMMAND(SetEnvironmentSettings, MERGE, // merge lots of small changes into one u ((sEnvironmentSettings, settings)) ); +COMMAND(RecalculateWaterData, NOMERGE, ((float,unused))); + QUERY(GetSkySets, // no inputs ,