Index: source/graphics/Camera.cpp =================================================================== --- source/graphics/Camera.cpp +++ source/graphics/Camera.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -21,14 +21,12 @@ #include "graphics/HFTracer.h" #include "graphics/Terrain.h" +#include "graphics/Water.h" #include "maths/MathUtil.h" #include "maths/Vector2D.h" #include "maths/Vector4D.h" #include "ps/Game.h" #include "ps/World.h" -#include "renderer/Renderer.h" -#include "renderer/SceneRenderer.h" -#include "renderer/WaterManager.h" CCamera::CCamera() { @@ -271,7 +269,7 @@ CPlane plane; plane.Set(CVector3D(0.f, 1.f, 0.f), // upwards normal - CVector3D(0.f, g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight, 0.f)); // passes through water plane + CVector3D(0.f, g_Game->GetWorld()->GetWater().GetWaterHeight(), 0.f)); // passes through water plane bool gotWater = plane.FindRayIntersection( origin, dir, &waterPoint ); @@ -349,7 +347,7 @@ CPlane plane; plane.Set(CVector3D(0.f, 1.f, 0.f), // upwards normal - CVector3D(0.f, g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight, 0.f)); // passes through water plane + CVector3D(0.f, g_Game->GetWorld()->GetWater().GetWaterHeight(), 0.f)); // passes through water plane bool gotWater = plane.FindRayIntersection( origin, dir, &waterPoint ); Index: source/graphics/CameraController.cpp =================================================================== --- source/graphics/CameraController.cpp +++ source/graphics/CameraController.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -21,6 +21,7 @@ #include "graphics/HFTracer.h" #include "graphics/Terrain.h" +#include "graphics/Water.h" #include "i18n/L10n.h" #include "lib/input.h" #include "lib/timer.h" @@ -35,9 +36,6 @@ #include "ps/Pyrogenesis.h" #include "ps/TouchInput.h" #include "ps/World.h" -#include "renderer/Renderer.h" -#include "renderer/SceneRenderer.h" -#include "renderer/WaterManager.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpPosition.h" #include "simulation2/components/ICmpRangeManager.h" @@ -581,7 +579,7 @@ const float ground = std::max( g_Game->GetWorld()->GetTerrain()->GetExactGroundLevel(nearPoint.X, nearPoint.Z), - g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight); + g_Game->GetWorld()->GetWater().GetWaterHeight()); // filter ground levels for smooth camera movement const float filtered_near_ground = g_Game->GetWorld()->GetTerrain()->GetFilteredGroundLevel(nearPoint.X, nearPoint.Z, near_radius); @@ -590,7 +588,7 @@ // filtered maximum visible ground level in view const float filtered_ground = std::max( std::max(filtered_near_ground, filtered_pivot_ground), - g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight); + g_Game->GetWorld()->GetWater().GetWaterHeight()); // target camera height above pivot point const float pivot_height = -forwards.Y * (m_Zoom.GetSmoothedValue() - m_ViewNear); Index: source/graphics/GameView.h =================================================================== --- source/graphics/GameView.h +++ source/graphics/GameView.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -29,6 +29,7 @@ class CGame; class CObjectManager; class CVector3D; +class CWorld; struct SViewPort; class CGameViewImpl; @@ -81,6 +82,8 @@ #undef DECLARE_BOOLEAN_SETTING + const CWorld& GetWorld() const override; + CCamera* GetCamera(); CCinemaManager* GetCinema(); CObjectManager& GetObjectManager(); Index: source/graphics/GameView.cpp =================================================================== --- source/graphics/GameView.cpp +++ source/graphics/GameView.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -36,6 +36,7 @@ #include "graphics/TerritoryTexture.h" #include "graphics/Unit.h" #include "graphics/UnitManager.h" +#include "graphics/Water.h" #include "lib/input.h" #include "lib/timer.h" #include "lobby/IXmppClient.h" @@ -192,6 +193,13 @@ return &m->CinemaManager; } +const CWorld& CGameView::GetWorld() const +{ + ENSURE(m->Game); + ENSURE(m->Game->GetWorld()); + return *m->Game->GetWorld(); +} + CLOSTexture& CGameView::GetLOSTexture() { return m->LOSTexture; @@ -219,6 +227,9 @@ RegMemFun(this, &CGameView::Initialize, L"CGameView init", 1); RegMemFun(g_TexMan.GetSingletonPtr(), &CTerrainTextureManager::LoadTerrainTextures, L"LoadTerrainTextures", 60); + + std::wstring ref = m->Game->GetWorld()->GetWater().m_WaterType; + RegMemFun1(&g_Renderer.GetSceneRenderer().GetWaterManager(), &WaterManager::LoadWaterTextures, ref, L"LoadWaterTextures", 80); } void CGameView::BeginFrame() @@ -260,7 +271,7 @@ PROFILE3("submit terrain"); CTerrain* pTerrain = m->Game->GetWorld()->GetTerrain(); - float waterHeight = g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight + 0.001f; + float waterHeight = m->Game->GetWorld()->GetWater().GetWaterHeight() + 0.001f; const ssize_t patchesPerSide = pTerrain->GetPatchesPerSide(); // find out which patches will be drawn Index: source/graphics/MapReader.h =================================================================== --- source/graphics/MapReader.h +++ source/graphics/MapReader.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -27,7 +27,7 @@ #include "simulation2/system/Entity.h" class CTerrain; -class WaterManager; +class CWater; class SkyManager; class CLightEnv; class CCinemaManager; @@ -52,11 +52,11 @@ ~CMapReader(); // LoadMap: try to load the map from given file; reinitialise the scene to new data if successful - void LoadMap(const VfsPath& pathname, const ScriptContext& cx, JS::HandleValue settings, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*, + void LoadMap(const VfsPath& pathname, const ScriptContext& cx, JS::HandleValue settings, CTerrain*, CWater*, SkyManager*, CLightEnv*, CGameView*, CCinemaManager*, CTriggerManager*, CPostprocManager* pPostproc, CSimulation2*, const CSimContext*, int playerID, bool skipEntities); - void LoadRandomMap(const CStrW& scriptFile, const ScriptContext& cx, JS::HandleValue settings, CTerrain*, WaterManager*, SkyManager*, CLightEnv*, CGameView*, CCinemaManager*, CTriggerManager*, CPostprocManager* pPostproc_, CSimulation2*, int playerID); + void LoadRandomMap(const CStrW& scriptFile, const ScriptContext& cx, JS::HandleValue settings, CTerrain*, CWater*, SkyManager*, CLightEnv*, CGameView*, CCinemaManager*, CTriggerManager*, CPostprocManager* pPostproc_, CSimulation2*, int playerID); private: // Load script settings for use by scripts @@ -127,7 +127,7 @@ CFileUnpacker unpacker; CTerrain* pTerrain; - WaterManager* pWaterMan; + CWater* pWater; SkyManager* pSkyMan; CPostprocManager* pPostproc; CLightEnv* pLightEnv; Index: source/graphics/MapReader.cpp =================================================================== --- source/graphics/MapReader.cpp +++ source/graphics/MapReader.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -28,6 +28,7 @@ #include "graphics/Terrain.h" #include "graphics/TerrainTextureEntry.h" #include "graphics/TerrainTextureManager.h" +#include "graphics/Water.h" #include "lib/timer.h" #include "lib/external_libraries/libsdl.h" #include "maths/MathUtil.h" @@ -38,7 +39,6 @@ #include "ps/XML/Xeromyces.h" #include "renderer/PostprocManager.h" #include "renderer/SkyManager.h" -#include "renderer/WaterManager.h" #include "scriptinterface/Object.h" #include "scriptinterface/ScriptContext.h" #include "scriptinterface/ScriptRequest.h" @@ -71,14 +71,14 @@ // LoadMap: try to load the map from given file; reinitialise the scene to new data if successful void CMapReader::LoadMap(const VfsPath& pathname, const ScriptContext& cx, JS::HandleValue settings, CTerrain *pTerrain_, - WaterManager* pWaterMan_, SkyManager* pSkyMan_, + CWater* pWater_, SkyManager* pSkyMan_, CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_, CPostprocManager* pPostproc_, CSimulation2 *pSimulation2_, const CSimContext* pSimContext_, int playerID_, bool skipEntities) { pTerrain = pTerrain_; pLightEnv = pLightEnv_; pGameView = pGameView_; - pWaterMan = pWaterMan_; + pWater = pWater_; pSkyMan = pSkyMan_; pCinema = pCinema_; pTrigMan = pTrigMan_; @@ -153,7 +153,7 @@ // LoadRandomMap: try to load the map data; reinitialise the scene to new data if successful void CMapReader::LoadRandomMap(const CStrW& scriptFile, const ScriptContext& cx, JS::HandleValue settings, CTerrain *pTerrain_, - WaterManager* pWaterMan_, SkyManager* pSkyMan_, + CWater* pWater_, SkyManager* pSkyMan_, CLightEnv *pLightEnv_, CGameView *pGameView_, CCinemaManager* pCinema_, CTriggerManager* pTrigMan_, CPostprocManager* pPostproc_, CSimulation2 *pSimulation2_, int playerID_) { @@ -164,7 +164,7 @@ pTerrain = pTerrain_; pLightEnv = pLightEnv_; pGameView = pGameView_; - pWaterMan = pWaterMan_; + pWater = pWater_; pSkyMan = pSkyMan_; pCinema = pCinema_; pTrigMan = pTrigMan_; @@ -728,15 +728,15 @@ // The rest are purely graphical effects, and should be ignored if // graphics are disabled - if (!m_MapReader.pWaterMan) + if (!m_MapReader.pWater) continue; if (water_element_name == el_type) { if (waterelement.GetText() == "default") - m_MapReader.pWaterMan->m_WaterType = L"ocean"; + m_MapReader.pWater->m_WaterType = L"ocean"; else - m_MapReader.pWaterMan->m_WaterType = waterelement.GetText().FromUTF8(); + m_MapReader.pWater->m_WaterType = waterelement.GetText().FromUTF8(); } #define READ_COLOR(el, out) \ else if (water_element_name == el) \ @@ -755,11 +755,11 @@ out = waterelement.GetText().ToFloat(); \ } \ - READ_COLOR(el_color, m_MapReader.pWaterMan->m_WaterColor) - READ_COLOR(el_tint, m_MapReader.pWaterMan->m_WaterTint) - READ_FLOAT(el_waviness, m_MapReader.pWaterMan->m_Waviness) - READ_FLOAT(el_murkiness, m_MapReader.pWaterMan->m_Murkiness) - READ_FLOAT(el_windangle, m_MapReader.pWaterMan->m_WindAngle) + READ_COLOR(el_color, m_MapReader.pWater->m_WaterColor) + READ_COLOR(el_tint, m_MapReader.pWater->m_WaterTint) + READ_FLOAT(el_waviness, m_MapReader.pWater->m_Waviness) + READ_FLOAT(el_murkiness, m_MapReader.pWater->m_Murkiness) + READ_FLOAT(el_windangle, m_MapReader.pWater->m_WindAngle) #undef READ_FLOAT #undef READ_COLOR @@ -1527,16 +1527,16 @@ cmpWaterManager->SetWaterLevel(entity_pos_t::FromFloat(waterHeight)); // If we have graphics, get rest of settings - if (pWaterMan) + if (pWater) { - GET_ENVIRONMENT_PROPERTY(waterBodyObj, Type, pWaterMan->m_WaterType) - if (pWaterMan->m_WaterType == L"default") - pWaterMan->m_WaterType = L"ocean"; - GET_ENVIRONMENT_PROPERTY(waterBodyObj, Color, pWaterMan->m_WaterColor) - GET_ENVIRONMENT_PROPERTY(waterBodyObj, Tint, pWaterMan->m_WaterTint) - GET_ENVIRONMENT_PROPERTY(waterBodyObj, Waviness, pWaterMan->m_Waviness) - GET_ENVIRONMENT_PROPERTY(waterBodyObj, Murkiness, pWaterMan->m_Murkiness) - GET_ENVIRONMENT_PROPERTY(waterBodyObj, WindAngle, pWaterMan->m_WindAngle) + GET_ENVIRONMENT_PROPERTY(waterBodyObj, Type, pWater->m_WaterType) + if (pWater->m_WaterType == L"default") + pWater->m_WaterType = L"ocean"; + GET_ENVIRONMENT_PROPERTY(waterBodyObj, Color, pWater->m_WaterColor) + GET_ENVIRONMENT_PROPERTY(waterBodyObj, Tint, pWater->m_WaterTint) + GET_ENVIRONMENT_PROPERTY(waterBodyObj, Waviness, pWater->m_Waviness) + GET_ENVIRONMENT_PROPERTY(waterBodyObj, Murkiness, pWater->m_Murkiness) + GET_ENVIRONMENT_PROPERTY(waterBodyObj, WindAngle, pWater->m_WindAngle) } JS::RootedValue fogObject(rq.cx); Index: source/graphics/MapWriter.h =================================================================== --- source/graphics/MapWriter.h +++ source/graphics/MapWriter.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -30,7 +30,7 @@ class CCamera; class CCinemaManager; class CPostprocManager; -class WaterManager; +class CWater; class SkyManager; class CSimulation2; struct MapTrigger; @@ -42,7 +42,7 @@ CMapWriter(); // SaveMap: try to save the current map to the given file void SaveMap(const VfsPath& pathname, CTerrain* pTerr, - WaterManager* pWaterMan, SkyManager* pSkyMan, + CWater* pWater, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* pCinema, CPostprocManager* pPostproc, CSimulation2* pSimulation2); @@ -59,7 +59,7 @@ std::vector& tileIndices); // WriteXML: output some other data (entities, etc) in XML format - void WriteXML(const VfsPath& pathname, WaterManager* pWaterMan, + void WriteXML(const VfsPath& pathname, CWater* pWater, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera, CPostprocManager* pPostproc, CSimulation2* pSimulation2); Index: source/graphics/MapWriter.cpp =================================================================== --- source/graphics/MapWriter.cpp +++ source/graphics/MapWriter.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -27,6 +27,7 @@ #include "Terrain.h" #include "TerrainTextureEntry.h" #include "TerrainTextureManager.h" +#include "Water.h" #include "maths/MathUtil.h" #include "maths/NUSpline.h" @@ -36,7 +37,6 @@ #include "ps/XML/XMLWriter.h" #include "renderer/PostprocManager.h" #include "renderer/SkyManager.h" -#include "renderer/WaterManager.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpCinemaManager.h" #include "simulation2/components/ICmpGarrisonHolder.h" @@ -57,7 +57,7 @@ /////////////////////////////////////////////////////////////////////////////////////////////////// // SaveMap: try to save the current map to the given file void CMapWriter::SaveMap(const VfsPath& pathname, CTerrain* pTerrain, - WaterManager* pWaterMan, SkyManager* pSkyMan, + CWater* pWater, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera, CCinemaManager* UNUSED(pCinema), CPostprocManager* pPostproc, CSimulation2* pSimulation2) @@ -79,7 +79,7 @@ } VfsPath pathnameXML = pathname.ChangeExtension(L".xml"); - WriteXML(pathnameXML, pWaterMan, pSkyMan, pLightEnv, pCamera, pPostproc, pSimulation2); + WriteXML(pathnameXML, pWater, pSkyMan, pLightEnv, pCamera, pPostproc, pSimulation2); } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -186,7 +186,7 @@ } void CMapWriter::WriteXML(const VfsPath& filename, - WaterManager* pWaterMan, SkyManager* pSkyMan, + CWater* pWater, SkyManager* pSkyMan, CLightEnv* pLightEnv, CCamera* pCamera, CPostprocManager* pPostproc, CSimulation2* pSimulation2) @@ -244,25 +244,23 @@ XMLWriter_Element waterTag(xmlMapFile, "Water"); { XMLWriter_Element waterBodyTag(xmlMapFile, "WaterBody"); - CmpPtr cmpWaterManager(sim, SYSTEM_ENTITY); - ENSURE(cmpWaterManager); - waterBodyTag.Setting("Type", pWaterMan->m_WaterType); + waterBodyTag.Setting("Type", pWater->m_WaterType); { XMLWriter_Element colorTag(xmlMapFile, "Color"); - colorTag.Attribute("r", pWaterMan->m_WaterColor.r); - colorTag.Attribute("g", pWaterMan->m_WaterColor.g); - colorTag.Attribute("b", pWaterMan->m_WaterColor.b); + colorTag.Attribute("r", pWater->m_WaterColor.r); + colorTag.Attribute("g", pWater->m_WaterColor.g); + colorTag.Attribute("b", pWater->m_WaterColor.b); } { XMLWriter_Element tintTag(xmlMapFile, "Tint"); - tintTag.Attribute("r", pWaterMan->m_WaterTint.r); - tintTag.Attribute("g", pWaterMan->m_WaterTint.g); - tintTag.Attribute("b", pWaterMan->m_WaterTint.b); + tintTag.Attribute("r", pWater->m_WaterTint.r); + tintTag.Attribute("g", pWater->m_WaterTint.g); + tintTag.Attribute("b", pWater->m_WaterTint.b); } - waterBodyTag.Setting("Height", cmpWaterManager->GetExactWaterLevel(0, 0)); - waterBodyTag.Setting("Waviness", pWaterMan->m_Waviness); - waterBodyTag.Setting("Murkiness", pWaterMan->m_Murkiness); - waterBodyTag.Setting("WindAngle", pWaterMan->m_WindAngle); + waterBodyTag.Setting("Height", pWater->GetWaterHeight()); + waterBodyTag.Setting("Waviness", pWater->m_Waviness); + waterBodyTag.Setting("Murkiness", pWater->m_Murkiness); + waterBodyTag.Setting("WindAngle", pWater->m_WindAngle); } } Index: source/graphics/MiniMapTexture.cpp =================================================================== --- source/graphics/MiniMapTexture.cpp +++ source/graphics/MiniMapTexture.cpp @@ -29,6 +29,7 @@ #include "graphics/TerrainTextureManager.h" #include "graphics/TerritoryTexture.h" #include "graphics/TextureManager.h" +#include "graphics/Water.h" #include "lib/bits.h" #include "lib/code_generation.h" #include "lib/hash.h" @@ -47,7 +48,6 @@ #include "renderer/Renderer.h" #include "renderer/RenderingOptions.h" #include "renderer/SceneRenderer.h" -#include "renderer/WaterManager.h" #include "scriptinterface/Object.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpMinimap.h" @@ -346,7 +346,7 @@ void CMiniMapTexture::Update(const float UNUSED(deltaRealTime)) { - if (m_WaterHeight != g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight) + if (m_WaterHeight != g_Game->GetWorld()->GetWater().GetWaterHeight()) { m_TerrainTextureDirty = true; m_FinalTextureDirty = true; @@ -436,7 +436,7 @@ const u32 width = m_MapSize - 1; const u32 height = m_MapSize - 1; - m_WaterHeight = g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight; + m_WaterHeight = g_Game->GetWorld()->GetWater().GetWaterHeight(); m_TerrainTextureDirty = false; for (u32 j = 0; j < height; ++j) Index: source/graphics/Water.h =================================================================== --- /dev/null +++ source/graphics/Water.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2023 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_WATER +#define INCLUDED_WATER + +#include "graphics/Color.h" + + +/** + * Holds information about the graphics for water. + */ +class CWater +{ +public: + void SetMapSize(size_t size) { + m_MapSize = size; + ++m_Version; + } + + size_t GetMapSize() const { + return m_MapSize; + } + + void SetWaterHeight(float h) { + m_WaterHeight = h; + ++m_Version; + } + + float GetWaterHeight() const { return m_WaterHeight; } + + u8 GetVersion() const { return m_Version; } +protected: + size_t m_MapSize; + + float m_WaterHeight = 5.0f; + + u8 m_Version = 0; +public: + // Water parameters + std::wstring m_WaterType = L"ocean"; // Which texture to use. + CColor m_WaterColor = CColor(0.3f, 0.35f, 0.7f, 1.0f); // Color of the water without refractions. This is what you're seeing when the water's deep or murkiness high. + CColor m_WaterTint = CColor(0.28f, 0.3f, 0.59f, 1.0f); // Tint of refraction in the water. + float m_Waviness = 8.f; // How big the waves are. + float m_Murkiness = 0.45f;; // How murky the water is. + float m_WindAngle = 0.f; // In which direction the water waves go. +}; + +#endif // INCLUDED_WATER Index: source/gui/ObjectTypes/CMiniMap.cpp =================================================================== --- source/gui/ObjectTypes/CMiniMap.cpp +++ source/gui/ObjectTypes/CMiniMap.cpp @@ -27,6 +27,7 @@ #include "graphics/TerrainTextureEntry.h" #include "graphics/TerrainTextureManager.h" #include "graphics/TextureManager.h" +#include "graphics/Water.h" #include "gui/CGUI.h" #include "gui/GUIManager.h" #include "lib/bits.h" @@ -42,7 +43,6 @@ #include "ps/World.h" #include "renderer/Renderer.h" #include "renderer/SceneRenderer.h" -#include "renderer/WaterManager.h" #include "scriptinterface/Object.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpMinimap.h" @@ -269,7 +269,7 @@ { // Compute the camera frustum intersected with a fixed-height plane. // Use the water height as a fixed base height, which should be the lowest we can go - const float sampleHeight = g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight; + const float sampleHeight = g_Game->GetWorld()->GetWater().GetWaterHeight(); const CCamera* camera = g_Game->GetView()->GetCamera(); const std::array hitPoints = { Index: source/ps/Game.cpp =================================================================== --- source/ps/Game.cpp +++ source/ps/Game.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -41,7 +41,6 @@ #include "renderer/Renderer.h" #include "renderer/SceneRenderer.h" #include "renderer/TimeManager.h" -#include "renderer/WaterManager.h" #include "scriptinterface/FunctionWrapper.h" #include "scriptinterface/ScriptInterface.h" #include "scriptinterface/JSON.h" @@ -69,7 +68,7 @@ **/ CGame::CGame(bool replayLog): m_World(new CWorld(this)), - m_Simulation2(new CSimulation2(&m_World->GetUnitManager(), g_ScriptContext, m_World->GetTerrain())), + m_Simulation2(new CSimulation2(&m_World->GetUnitManager(), g_ScriptContext, m_World->GetTerrain(), &m_World->GetWater())), m_GameView(CRenderer::IsInitialised() ? new CGameView(this) : nullptr), m_GameStarted(false), m_Paused(false), @@ -261,8 +260,6 @@ m_World->RegisterInit(mapFile, *scriptInterface.GetContext(), settings, m_PlayerID); } - if (m_GameView) - RegMemFun(&g_Renderer.GetSceneRenderer().GetWaterManager(), &WaterManager::LoadWaterTextures, L"LoadWaterTextures", 80); if (m_IsSavedGame) RegMemFun(this, &CGame::LoadInitialState, L"Loading game", 1000); Index: source/ps/GameSetup/GameSetup.cpp =================================================================== --- source/ps/GameSetup/GameSetup.cpp +++ source/ps/GameSetup/GameSetup.cpp @@ -592,7 +592,7 @@ // on anything else.) if (args.Has("dumpSchema")) { - CSimulation2 sim(NULL, g_ScriptContext, NULL); + CSimulation2 sim(nullptr, g_ScriptContext, nullptr, nullptr); sim.LoadDefaultScripts(); std::ofstream f("entity.rng", std::ios_base::out | std::ios_base::trunc); f << sim.GenerateSchema(); Index: source/ps/World.h =================================================================== --- source/ps/World.h +++ source/ps/World.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -35,9 +35,10 @@ ERROR_TYPE(Game_World, MapLoadFailed); class CGame; +class CMapReader; class CUnitManager; class CTerrain; -class CMapReader; +class CWater; class ScriptContext; /** @@ -57,6 +58,8 @@ **/ CTerrain *m_Terrain; + std::unique_ptr m_Water; + /** * pointer to the CUnitManager that holds all the units in the world. **/ @@ -91,6 +94,8 @@ inline CTerrain *GetTerrain() { return m_Terrain; } + CWater& GetWater() const { return *m_Water; } + /** * Get a reference to the unit manager object. * Index: source/ps/World.cpp =================================================================== --- source/ps/World.cpp +++ source/ps/World.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -22,8 +22,8 @@ #include "graphics/MapReader.h" #include "graphics/MapWriter.h" #include "graphics/Terrain.h" -#include "graphics/Terrain.h" #include "graphics/UnitManager.h" +#include "graphics/Water.h" #include "lib/timer.h" #include "ps/CLogger.h" #include "ps/CStr.h" @@ -53,6 +53,7 @@ m_pGame(pGame), m_Terrain(new CTerrain()), m_UnitManager(new CUnitManager()), + m_Water(new CWater()), m_MapReader(new CMapReader) { } @@ -71,7 +72,7 @@ { CTriggerManager* pTriggerManager = NULL; m_MapReader->LoadMap(mapfilename, cx, settings, m_Terrain, - CRenderer::IsInitialised() ? &g_Renderer.GetSceneRenderer().GetWaterManager() : NULL, + m_Water.get(), CRenderer::IsInitialised() ? &g_Renderer.GetSceneRenderer().GetSkyManager() : NULL, &g_LightEnv, m_pGame->GetView(), m_pGame->GetView() ? m_pGame->GetView()->GetCinema() : NULL, @@ -94,7 +95,7 @@ // If scriptFile is empty, a blank map will be generated using settings (no RMS run) CTriggerManager* pTriggerManager = NULL; m_MapReader->LoadRandomMap(scriptFile, cx, settings, m_Terrain, - CRenderer::IsInitialised() ? &g_Renderer.GetSceneRenderer().GetWaterManager() : NULL, + m_Water.get(), CRenderer::IsInitialised() ? &g_Renderer.GetSceneRenderer().GetSkyManager() : NULL, &g_LightEnv, m_pGame->GetView(), m_pGame->GetView() ? m_pGame->GetView()->GetCinema() : NULL, Index: source/renderer/PatchRData.cpp =================================================================== --- source/renderer/PatchRData.cpp +++ source/renderer/PatchRData.cpp @@ -1474,7 +1474,7 @@ m_WaterBounds += vertex.m_Position; - vertex.m_WaterData = CVector2D(waterManager.m_WindStrength[xx + zz*mapSize], depth); + vertex.m_WaterData = CVector2D(waterManager.GetWindStrength(xx, zz), depth); water_index_map[z+moves[i][1]][x+moves[i][0]] = static_cast(water_vertex_data.size()); water_vertex_data.push_back(vertex); Index: source/renderer/Scene.h =================================================================== --- source/renderer/Scene.h +++ source/renderer/Scene.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -37,6 +37,7 @@ class CLOSTexture; class CMiniMapTexture; class CTerritoryTexture; +class CWorld; struct SOverlayLine; struct SOverlayTexturedLine; struct SOverlaySprite; @@ -64,6 +65,11 @@ */ virtual void EnumerateObjects(const CFrustum& frustum, SceneCollector* c) = 0; + /** + * Return the world that this Scene is a part of. + */ + virtual const CWorld& GetWorld() const = 0; + /** * Return the LOS texture to be used for rendering this scene. */ Index: source/renderer/SceneRenderer.h =================================================================== --- source/renderer/SceneRenderer.h +++ source/renderer/SceneRenderer.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -118,7 +118,7 @@ * Return the scene that is currently being rendered. * Only valid when the renderer is in a RenderScene call. */ - Scene& GetScene(); + Scene& GetScene() const; /** * Render text overlays on top of the scene. Index: source/renderer/SceneRenderer.cpp =================================================================== --- source/renderer/SceneRenderer.cpp +++ source/renderer/SceneRenderer.cpp @@ -35,6 +35,7 @@ #include "graphics/Terrain.h" #include "graphics/Texture.h" #include "graphics/TextureManager.h" +#include "graphics/Water.h" #include "maths/Matrix3D.h" #include "maths/MathUtil.h" #include "ps/CLogger.h" @@ -485,11 +486,11 @@ // the whole screen despite being rendered into a square, and cover slightly more // of the view so we can see wavy reflections of slightly off-screen objects. camera.m_Orientation.Scale(1, -1, 1); - camera.m_Orientation.Translate(0, 2 * wm.m_WaterHeight, 0); + camera.m_Orientation.Translate(0, 2 * GetScene().GetWorld().GetWater().GetWaterHeight(), 0); camera.UpdateFrustum(scissor); // Clip slightly above the water to improve reflections of objects on the water // when the reflections are distorted. - camera.ClipFrustum(CVector4D(0, 1, 0, -wm.m_WaterHeight + 2.0f)); + camera.ClipFrustum(CVector4D(0, 1, 0, -GetScene().GetWorld().GetWater().GetWaterHeight() + 2.0f)); SViewPort vp; vp.m_Height = wm.m_RefTextureSize; @@ -502,7 +503,7 @@ scaleMat.SetScaling(g_Renderer.GetHeight() / static_cast(std::max(1, g_Renderer.GetWidth())), 1.0f, 1.0f); camera.SetProjection(scaleMat * camera.GetProjection()); - CVector4D camPlane(0, 1, 0, -wm.m_WaterHeight + 0.5f); + CVector4D camPlane(0, 1, 0, -GetScene().GetWorld().GetWater().GetWaterHeight() + 0.5f); SetObliqueFrustumClipping(camera, camPlane); } @@ -529,7 +530,7 @@ // the whole screen despite being rendered into a square, and cover slightly more // of the view so we can see wavy refractions of slightly off-screen objects. camera.UpdateFrustum(scissor); - camera.ClipFrustum(CVector4D(0, -1, 0, wm.m_WaterHeight + 0.5f)); // add some to avoid artifacts near steep shores. + camera.ClipFrustum(CVector4D(0, -1, 0, GetScene().GetWorld().GetWater().GetWaterHeight() + 0.5f)); // add some to avoid artifacts near steep shores. SViewPort vp; vp.m_Height = wm.m_RefTextureSize; @@ -642,7 +643,7 @@ return; } - CVector4D camPlane(0, -1, 0, wm.m_WaterHeight + 2.0f); + CVector4D camPlane(0, -1, 0, GetScene().GetWorld().GetWater().GetWaterHeight() + 2.0f); SetObliqueFrustumClipping(m_ViewCamera, camPlane); // Save the model-view-projection matrix so the shaders can use it for projective texturing @@ -1065,6 +1066,8 @@ { m_CurrentScene = &scene; + m->waterManager.RecomputeWaterDataIfNeeded(scene.GetWorld().GetWater()); + CFrustum frustum = m_CullCamera.GetFrustum(); m_CurrentCullGroup = CULL_DEFAULT; @@ -1158,7 +1161,7 @@ m_CurrentScene = nullptr; } -Scene& CSceneRenderer::GetScene() +Scene& CSceneRenderer::GetScene() const { ENSURE(m_CurrentScene); return *m_CurrentScene; Index: source/renderer/TerrainRenderer.cpp =================================================================== --- source/renderer/TerrainRenderer.cpp +++ source/renderer/TerrainRenderer.cpp @@ -31,6 +31,7 @@ #include "graphics/TerritoryTexture.h" #include "graphics/TextRenderer.h" #include "graphics/TextureManager.h" +#include "graphics/Water.h" #include "maths/MathUtil.h" #include "maths/Vector2D.h" #include "ps/CLogger.h" @@ -48,6 +49,7 @@ #include "renderer/SceneRenderer.h" #include "renderer/ShadowMap.h" #include "renderer/SkyManager.h" +#include "renderer/TimeManager.h" #include "renderer/VertexArray.h" #include "renderer/WaterManager.h" @@ -240,7 +242,7 @@ if (!waterBounds.IsEmpty()) { // Add a delta to avoid z-fighting. - const float height = g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight + 0.05f; + const float height = g_Renderer.GetSceneRenderer().GetScene().GetWorld().GetWater().GetWaterHeight() + 0.05f; const float waterPos[] = { waterBounds[0].X, height, waterBounds[0].Z, @@ -447,6 +449,7 @@ CSceneRenderer& sceneRenderer = g_Renderer.GetSceneRenderer(); + CWater& water = sceneRenderer.GetScene().GetWorld().GetWater(); WaterManager& waterManager = sceneRenderer.GetWaterManager(); CShaderDefines defines = context; @@ -482,7 +485,7 @@ WaterMgr->CreateSuperfancyInfo(); }*/ - const double time = waterManager.m_WaterTexTimer; + const double time = g_Renderer.GetTimeManager().GetGlobalTime(); const float repeatPeriod = waterManager.m_RepeatPeriod; deviceCommandContext->SetGraphicsPipelineState( @@ -579,15 +582,15 @@ deviceCommandContext->SetUniform( fancyWaterShader->GetBindingSlot(str_sunColor), lightEnv.m_SunColor.AsFloatArray()); deviceCommandContext->SetUniform( - fancyWaterShader->GetBindingSlot(str_color), waterManager.m_WaterColor.AsFloatArray()); + fancyWaterShader->GetBindingSlot(str_color), water.m_WaterColor.AsFloatArray()); deviceCommandContext->SetUniform( - fancyWaterShader->GetBindingSlot(str_tint), waterManager.m_WaterTint.AsFloatArray()); + fancyWaterShader->GetBindingSlot(str_tint), water.m_WaterTint.AsFloatArray()); deviceCommandContext->SetUniform( - fancyWaterShader->GetBindingSlot(str_waviness), waterManager.m_Waviness); + fancyWaterShader->GetBindingSlot(str_waviness), water.m_Waviness); deviceCommandContext->SetUniform( - fancyWaterShader->GetBindingSlot(str_murkiness), waterManager.m_Murkiness); + fancyWaterShader->GetBindingSlot(str_murkiness), water.m_Murkiness); deviceCommandContext->SetUniform( - fancyWaterShader->GetBindingSlot(str_windAngle), waterManager.m_WindAngle); + fancyWaterShader->GetBindingSlot(str_windAngle), water.m_WindAngle); deviceCommandContext->SetUniform( fancyWaterShader->GetBindingSlot(str_repeatScale), 1.0f / repeatPeriod); @@ -611,7 +614,7 @@ static_cast(g_Renderer.GetWidth()), static_cast(g_Renderer.GetHeight())); - if (waterManager.m_WaterType == L"clap") + if (water.m_WaterType == L"clap") { deviceCommandContext->SetUniform( fancyWaterShader->GetBindingSlot(str_waveParams1), @@ -620,7 +623,7 @@ fancyWaterShader->GetBindingSlot(str_waveParams2), 0.5f, 0.0f, 0.0f, 0.0f); } - else if (waterManager.m_WaterType == L"lake") + else if (water.m_WaterType == L"lake") { deviceCommandContext->SetUniform( fancyWaterShader->GetBindingSlot(str_waveParams1), @@ -661,10 +664,11 @@ PROFILE3_GPU("simple water"); GPU_SCOPED_LABEL(deviceCommandContext, "Render Simple Water"); + const CWater& water = g_Renderer.GetSceneRenderer().GetScene().GetWorld().GetWater(); const WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager(); CLOSTexture& losTexture = g_Renderer.GetSceneRenderer().GetScene().GetLOSTexture(); - const double time = waterManager.m_WaterTexTimer; + const double time = g_Renderer.GetTimeManager().GetGlobalTime(); CShaderDefines context; if (g_Renderer.GetSceneRenderer().GetWaterRenderMode() == WIREFRAME) @@ -696,7 +700,7 @@ deviceCommandContext->SetUniform( waterSimpleShader->GetBindingSlot(str_time), static_cast(time)); deviceCommandContext->SetUniform( - waterSimpleShader->GetBindingSlot(str_color), waterManager.m_WaterColor.AsFloatArray()); + waterSimpleShader->GetBindingSlot(str_color), water.m_WaterColor.AsFloatArray()); for (CPatchRData* data : m->visiblePatches[cullGroup]) { Index: source/renderer/WaterManager.h =================================================================== --- source/renderer/WaterManager.h +++ source/renderer/WaterManager.h @@ -22,7 +22,6 @@ #ifndef INCLUDED_WATERMANAGER #define INCLUDED_WATERMANAGER -#include "graphics/Color.h" #include "graphics/Texture.h" #include "maths/Matrix3D.h" #include "maths/Vector2D.h" @@ -36,6 +35,7 @@ #include class CFrustum; +class CWater; struct WaveObject; @@ -63,7 +63,6 @@ Renderer::Backend::IVertexInputLayout* m_ShoreVertexInputLayout = nullptr; - size_t m_MapSize; ssize_t m_TexSize; CTexturePtr m_WaveTex; @@ -98,8 +97,6 @@ // requires also recreating the super fancy information. bool m_NeedInfoUpdate; - float m_WaterHeight; - double m_WaterTexTimer; float m_RepeatPeriod; @@ -120,15 +117,6 @@ CMatrix3D m_RefractionMatrix; CMatrix3D m_RefractionProjInvMatrix; CMatrix3D m_RefractionViewInvMatrix; - - // Water parameters - std::wstring m_WaterType; // Which texture to use. - CColor m_WaterColor; // Color of the water without refractions. This is what you're seeing when the water's deep or murkiness high. - CColor m_WaterTint; // Tint of refraction in the water. - float m_Waviness; // How big the waves are. - float m_Murkiness; // How murky the water is. - float m_WindAngle; // In which direction the water waves go. - public: WaterManager(); ~WaterManager(); @@ -138,11 +126,12 @@ /** * LoadWaterTextures: Load water textures from within the * progressive load framework. + * Takes a std::wstring by value for RegMemFun1 compatibility. * * @return 0 if loading has completed, a value from 1 to 100 (in percent of completion) * if more textures need to be loaded and a negative error value on failure. */ - int LoadWaterTextures(); + int LoadWaterTextures(std::wstring waterType); /** * Recreates/loads needed water textures. @@ -153,7 +142,7 @@ * ReloadWaterNormalTextures: Reload the normal textures so that changing * water type in Atlas will actually do the right thing. */ - void ReloadWaterNormalTextures(); + void ReloadWaterNormalTextures(const std::wstring& waterType); /** * UnloadWaterTextures: Free any loaded water textures and reset the internal state @@ -161,36 +150,21 @@ */ void UnloadWaterTextures(); - /** - * RecomputeWaterData: calculates all derived data from the waterheight - */ - void RecomputeWaterData(); - - /** - * RecomputeWindStrength: calculates the intensity of waves - */ - void RecomputeWindStrength(); - - /** - * RecomputeDistanceHeightmap: recalculates (or calculates) the distance heightmap. - */ - void RecomputeDistanceHeightmap(); - - /** - * CreateWaveMeshes: Creates the waves objects (and meshes). - */ - void CreateWaveMeshes(); - - /** - * Updates the map size. Will trigger a complete recalculation of fancy water information the next turn. - */ - void SetMapSize(size_t size); - /** * Updates the settings to the one from the renderer, and sets m_NeedsReloading. */ void UpdateQuality(); + /** + * RecomputeWaterData: calculates all derived data from the waterheight + */ + void RecomputeWaterDataIfNeeded(const CWater& water); + + /** + * Return the wind strength at these coordinates. + */ + float GetWindStrength(ssize_t x, ssize_t z) const; + /** * Returns true if fancy water shaders will be used (i.e. the hardware is capable * and it hasn't been configured off) @@ -207,6 +181,27 @@ */ size_t GetCurrentTextureIndex(const double& period) const; size_t GetNextTextureIndex(const double& period) const; + +private: + + /** + * RecomputeWindStrength: calculates the intensity of waves + */ + void RecomputeWindStrength(const CWater& water); + + /** + * RecomputeDistanceHeightmap: recalculates (or calculates) the distance heightmap. + */ + void RecomputeDistanceHeightmap(const CWater& water); + + /** + * CreateWaveMeshes: Creates the waves objects (and meshes). + */ + void CreateWaveMeshes(const CWater& water); + +private: + size_t m_MapSize = 0; + u8 m_LastWaterVersion = -1; }; Index: source/renderer/WaterManager.cpp =================================================================== --- source/renderer/WaterManager.cpp +++ source/renderer/WaterManager.cpp @@ -21,6 +21,7 @@ #include "graphics/TextureManager.h" #include "graphics/ShaderManager.h" #include "graphics/ShaderProgram.h" +#include "graphics/Water.h" #include "lib/bits.h" #include "lib/timer.h" #include "maths/MathUtil.h" @@ -34,6 +35,7 @@ #include "renderer/Renderer.h" #include "renderer/RenderingOptions.h" #include "renderer/SceneRenderer.h" +#include "renderer/TimeManager.h" #include "renderer/WaterManager.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpWaterManager.h" @@ -73,17 +75,9 @@ { // water m_RenderWater = false; // disabled until textures are successfully loaded - m_WaterHeight = 5.0f; m_RefTextureSize = 0; - m_WaterTexTimer = 0.0; - - m_WindAngle = 0.0f; - m_Waviness = 8.0f; - m_WaterColor = CColor(0.3f, 0.35f, 0.7f, 1.0f); - m_WaterTint = CColor(0.28f, 0.3f, 0.59f, 1.0f); - m_Murkiness = 0.45f; m_RepeatPeriod = 16.0f; m_WaterEffects = true; @@ -91,13 +85,10 @@ m_WaterRealDepth = false; m_WaterRefraction = false; m_WaterReflection = false; - m_WaterType = L"ocean"; m_NeedsReloading = false; m_NeedInfoUpdate = true; - m_MapSize = 0; - m_updatei0 = 0; m_updatej0 = 0; m_updatei1 = 0; @@ -112,9 +103,6 @@ m_ShoreWaves.clear(); m_ShoreWavesVBIndices.Reset(); - m_DistanceHeightmap.reset(); - m_WindStrength.reset(); - m_FancyEffectsFramebuffer.reset(); m_FancyEffectsOccludersFramebuffer.reset(); m_RefractionFramebuffer.reset(); @@ -160,9 +148,7 @@ m_ShoreVertexInputLayout = g_Renderer.GetVertexInputLayout(attributes); } -/////////////////////////////////////////////////////////////////// -// Progressive load of water textures -int WaterManager::LoadWaterTextures() +int WaterManager::LoadWaterTextures(std::wstring waterType) { // TODO: this doesn't need to be progressive-loading any more // (since texture loading is async now) @@ -185,7 +171,7 @@ m_RenderWater = true; // Load normalmaps (for fancy water) - ReloadWaterNormalTextures(); + ReloadWaterNormalTextures(waterType); // Load CoastalWaves { @@ -389,12 +375,12 @@ } } -void WaterManager::ReloadWaterNormalTextures() +void WaterManager::ReloadWaterNormalTextures(const std::wstring& waterType) { wchar_t pathname[PATH_MAX]; for (size_t i = 0; i < ARRAY_SIZE(m_NormalMap); ++i) { - swprintf_s(pathname, ARRAY_SIZE(pathname), L"art/textures/animated/water/%ls/normal00%02d.png", m_WaterType.c_str(), static_cast(i) + 1); + swprintf_s(pathname, ARRAY_SIZE(pathname), L"art/textures/animated/water/%ls/normal00%02d.png", waterType.c_str(), static_cast(i) + 1); CTextureProperties textureProps(pathname); textureProps.SetAddressMode( Renderer::Backend::Sampler::AddressMode::REPEAT); @@ -469,36 +455,38 @@ /////////////////////////////////////////////////////////////////// // Calculate our binary heightmap from the terrain heightmap. -void WaterManager::RecomputeDistanceHeightmap() +void WaterManager::RecomputeDistanceHeightmap(const CWater& water) { + m_DistanceHeightmap.reset(); + CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); if (!terrain || !terrain->GetHeightMap()) return; - size_t SideSize = m_MapSize; + size_t SideSize = water.GetMapSize(); + + if (SideSize <= 0) + return; // we want to look ahead some distance, but not too much (less efficient and not interesting). This is our lookahead. const size_t maxLevel = 5; - if (!m_DistanceHeightmap) - { - m_DistanceHeightmap = std::make_unique(SideSize * SideSize); - std::fill(m_DistanceHeightmap.get(), m_DistanceHeightmap.get() + SideSize * SideSize, static_cast(maxLevel)); - } + m_DistanceHeightmap = std::make_unique(SideSize * SideSize); + std::fill(m_DistanceHeightmap.get(), m_DistanceHeightmap.get() + SideSize * SideSize, static_cast(maxLevel)); // Create a manhattan-distance heightmap. // This could be refined to only be done near the coast itself, but it's probably not necessary. u16* heightmap = terrain->GetHeightMap(); - ComputeDirection(m_DistanceHeightmap.get(), heightmap, m_WaterHeight, SideSize, maxLevel); - ComputeDirection(m_DistanceHeightmap.get(), heightmap, m_WaterHeight, SideSize, maxLevel); + ComputeDirection(m_DistanceHeightmap.get(), heightmap, water.GetWaterHeight(), SideSize, maxLevel); + ComputeDirection(m_DistanceHeightmap.get(), heightmap, water.GetWaterHeight(), SideSize, maxLevel); } // This requires m_DistanceHeightmap to be defined properly. -void WaterManager::CreateWaveMeshes() +void WaterManager::CreateWaveMeshes(const CWater& water) { - if (m_MapSize == 0) + if (water.GetMapSize() == 0 || !m_DistanceHeightmap) return; CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); @@ -508,17 +496,19 @@ m_ShoreWaves.clear(); m_ShoreWavesVBIndices.Reset(); - if (m_Waviness < 5.0f && m_WaterType != L"ocean") + if (water.m_Waviness < 5.0f && water.m_WaterType != L"ocean") return; - size_t SideSize = m_MapSize; + float waterHeight = water.GetWaterHeight(); + + size_t SideSize = water.GetMapSize(); // First step: get the points near the coast. std::set CoastalPointsSet; for (size_t z = 1; z < SideSize-1; ++z) for (size_t x = 1; x < SideSize-1; ++x) // get the points not on the shore but near it, ocean-side - if (m_DistanceHeightmap[z*m_MapSize + x] > 0.5f && m_DistanceHeightmap[z*m_MapSize + x] < 1.5f) + if (m_DistanceHeightmap[z*SideSize + x] > 0.5f && m_DistanceHeightmap[z*SideSize + x] < 1.5f) CoastalPointsSet.insert((z)*SideSize + x); // Second step: create chains out of those coastal points. @@ -704,15 +694,15 @@ break; } - if (terrain->GetExactGroundLevel(pos.X+perp.X*1.5f, pos.Y+perp.Y*1.5f) > m_WaterHeight) + if (terrain->GetExactGroundLevel(pos.X+perp.X*1.5f, pos.Y+perp.Y*1.5f) > waterHeight) sign = -1; - avgDepth += terrain->GetExactGroundLevel(pos.X+sign*perp.X*20.0f, pos.Y+sign*perp.Y*20.0f) - m_WaterHeight; + avgDepth += terrain->GetExactGroundLevel(pos.X+sign*perp.X*20.0f, pos.Y+sign*perp.Y*20.0f) - waterHeight; float localOutmost = -2.0f; while (localOutmost < 0.0f) { - float depth = terrain->GetExactGroundLevel(pos.X+sign*perp.X*localOutmost, pos.Y+sign*perp.Y*localOutmost) - m_WaterHeight; + float depth = terrain->GetExactGroundLevel(pos.X+sign*perp.X*localOutmost, pos.Y+sign*perp.Y*localOutmost) - waterHeight; if (depth < 0.0f || depth > 0.6f) localOutmost += 0.2f; else @@ -734,7 +724,7 @@ j += 3; continue; } - outmost = -2.5f + outmost * m_Waviness/10.0f; + outmost = -2.5f + outmost * water.m_Waviness/10.0f; avgDepth /= width; @@ -815,27 +805,27 @@ { float terrHeight = 0.05f + terrain->GetExactGroundLevel(pos.X+sign*perp.X*(perpT1[t]+outmost), pos.Y+sign*perp.Y*(perpT1[t]+outmost)); - point[t].m_BasePosition = CVector3D(pos.X+sign*perp.X*(perpT1[t]+outmost), baseHeight + heightT1[t]*sideNess + std::max(m_WaterHeight,terrHeight), + point[t].m_BasePosition = CVector3D(pos.X+sign*perp.X*(perpT1[t]+outmost), baseHeight + heightT1[t]*sideNess + std::max(waterHeight,terrHeight), pos.Y+sign*perp.Y*(perpT1[t]+outmost)); } for (size_t t = 0; t < 9; ++t) { float terrHeight = 0.05f + terrain->GetExactGroundLevel(pos.X+sign*perp.X*(perpT2[t]+outmost), pos.Y+sign*perp.Y*(perpT2[t]+outmost)); - point[t].m_ApexPosition = CVector3D(pos.X+sign*perp.X*(perpT2[t]+outmost), baseHeight + heightT1[t]*sideNess + std::max(m_WaterHeight,terrHeight), + point[t].m_ApexPosition = CVector3D(pos.X+sign*perp.X*(perpT2[t]+outmost), baseHeight + heightT1[t]*sideNess + std::max(waterHeight,terrHeight), pos.Y+sign*perp.Y*(perpT2[t]+outmost)); } for (size_t t = 0; t < 9; ++t) { float terrHeight = 0.05f + terrain->GetExactGroundLevel(pos.X+sign*perp.X*(perpT3[t]+outmost*sideNess), pos.Y+sign*perp.Y*(perpT3[t]+outmost*sideNess)); - point[t].m_SplashPosition = CVector3D(pos.X+sign*perp.X*(perpT3[t]+outmost*sideNess), baseHeight + heightT2[t]*sideNess + std::max(m_WaterHeight,terrHeight), pos.Y+sign*perp.Y*(perpT3[t]+outmost*sideNess)); + point[t].m_SplashPosition = CVector3D(pos.X+sign*perp.X*(perpT3[t]+outmost*sideNess), baseHeight + heightT2[t]*sideNess + std::max(waterHeight,terrHeight), pos.Y+sign*perp.Y*(perpT3[t]+outmost*sideNess)); } for (size_t t = 0; t < 9; ++t) { float terrHeight = 0.05f + terrain->GetExactGroundLevel(pos.X+sign*perp.X*(perpT4[t]+outmost), pos.Y+sign*perp.Y*(perpT4[t]+outmost)); - point[t].m_RetreatPosition = CVector3D(pos.X+sign*perp.X*(perpT4[t]+outmost), baseHeight + heightT3[t]*sideNess + std::max(m_WaterHeight,terrHeight), + point[t].m_RetreatPosition = CVector3D(pos.X+sign*perp.X*(perpT4[t]+outmost), baseHeight + heightT3[t]*sideNess + std::max(waterHeight,terrHeight), pos.Y+sign*perp.Y*(perpT4[t]+outmost)); } @@ -913,7 +903,7 @@ shader->GetBindingSlot(str_foamTex), m_FoamTex->GetBackendTexture()); deviceCommandContext->SetUniform( - shader->GetBindingSlot(str_time), static_cast(m_WaterTexTimer)); + shader->GetBindingSlot(str_time), static_cast(g_Renderer.GetTimeManager().GetGlobalTime())); const CMatrix3D transform = g_Renderer.GetSceneRenderer().GetViewCamera().GetViewProjection(); deviceCommandContext->SetUniform( @@ -952,31 +942,25 @@ deviceCommandContext->EndFramebufferPass(); } -void WaterManager::RecomputeWaterData() -{ - if (!m_MapSize) - return; - - RecomputeDistanceHeightmap(); - RecomputeWindStrength(); - CreateWaveMeshes(); -} /////////////////////////////////////////////////////////////////// // Calculate the strength of the wind at a given point on the map. -void WaterManager::RecomputeWindStrength() +void WaterManager::RecomputeWindStrength(const CWater& water) { - if (m_MapSize <= 0) + size_t newMapSize = water.GetMapSize(); + + m_WindStrength.reset(); + + if (newMapSize <= 0) return; - if (!m_WindStrength) - m_WindStrength = std::make_unique(m_MapSize * m_MapSize); + m_WindStrength = std::make_unique(newMapSize * newMapSize); CTerrain* terrain = g_Game->GetWorld()->GetTerrain(); if (!terrain || !terrain->GetHeightMap()) return; - CVector2D windDir = CVector2D(cos(m_WindAngle), sin(m_WindAngle)); + CVector2D windDir = CVector2D(cos(water.m_WindAngle), sin(water.m_WindAngle)); int stepSize = 10; ssize_t windX = -round(stepSize * windDir.X); @@ -996,33 +980,33 @@ if (fabs(windDir.X) < 0.01f) { movement.emplace_back(0, windY > 0.f ? 1 : -1); - startingPoints.reserve(m_MapSize); - size_t start = windY > 0 ? 0 : m_MapSize - 1; - for (size_t x = 0; x < m_MapSize; ++x) + startingPoints.reserve(newMapSize); + size_t start = windY > 0 ? 0 : newMapSize - 1; + for (size_t x = 0; x < newMapSize; ++x) startingPoints.emplace_back(x, start, 0.f); } else if (fabs(windDir.Y) < 0.01f) { movement.emplace_back(windX > 0.f ? 1 : - 1, 0); - startingPoints.reserve(m_MapSize); - size_t start = windX > 0 ? 0 : m_MapSize - 1; - for (size_t z = 0; z < m_MapSize; ++z) + startingPoints.reserve(newMapSize); + size_t start = windX > 0 ? 0 : newMapSize - 1; + for (size_t z = 0; z < newMapSize; ++z) startingPoints.emplace_back(start, z, 0.f); } else { - startingPoints.reserve(m_MapSize * 2); + startingPoints.reserve(newMapSize * 2); // Points along X. - size_t start = windY > 0 ? 0 : m_MapSize - 1; - for (size_t x = 0; x < m_MapSize; ++x) + size_t start = windY > 0 ? 0 : newMapSize - 1; + for (size_t x = 0; x < newMapSize; ++x) startingPoints.emplace_back(x, start, 0.f); // Points along Z, avoid repeating the corner point. - start = windX > 0 ? 0 : m_MapSize - 1; + start = windX > 0 ? 0 : newMapSize - 1; if (windY > 0) - for (size_t z = 1; z < m_MapSize; ++z) + for (size_t z = 1; z < newMapSize; ++z) startingPoints.emplace_back(start, z, 0.f); else - for (size_t z = 0; z < m_MapSize-1; ++z) + for (size_t z = 0; z < newMapSize-1; ++z) startingPoints.emplace_back(start, z, 0.f); // Compute movement array. @@ -1039,15 +1023,17 @@ } } + float waterHeight = water.GetWaterHeight(); + // We have all starting points ready, move them all until the map is covered. for (SWindPoint& point : startingPoints) { // Starting velocity is 1.0 unless in shallow water. - m_WindStrength[point.Y * m_MapSize + point.X] = 1.f; - float depth = m_WaterHeight - terrain->GetVertexGroundLevel(point.X, point.Y); + m_WindStrength[point.Y * newMapSize + point.X] = 1.f; + float depth = waterHeight - terrain->GetVertexGroundLevel(point.X, point.Y); if (depth > 0.f && depth < 2.f) - m_WindStrength[point.Y * m_MapSize + point.X] = depth / 2.f; - point.windStrength = m_WindStrength[point.Y * m_MapSize + point.X]; + m_WindStrength[point.Y * newMapSize + point.X] = depth / 2.f; + point.windStrength = m_WindStrength[point.Y * newMapSize + point.X]; bool onMap = true; while (onMap) @@ -1058,8 +1044,8 @@ // Adjust speed based on height difference, a positive height difference slowly increases speed (simulate venturi effect) // and a lower height reduces speed (wind protection from hills/...) - float heightDiff = std::max(m_WaterHeight, terrain->GetVertexGroundLevel(point.X + movement[step].first, point.Y + movement[step].second)) - - std::max(m_WaterHeight, terrain->GetVertexGroundLevel(point.X, point.Y)); + float heightDiff = std::max(waterHeight, terrain->GetVertexGroundLevel(point.X + movement[step].first, point.Y + movement[step].second)) - + std::max(waterHeight, terrain->GetVertexGroundLevel(point.X, point.Y)); if (heightDiff > 0.f) point.windStrength = std::min(2.f, point.windStrength + std::min(4.f, heightDiff) / 40.f); else @@ -1068,31 +1054,38 @@ point.X += movement[step].first; point.Y += movement[step].second; - if (point.X < 0 || point.X >= static_cast(m_MapSize) || point.Y < 0 || point.Y >= static_cast(m_MapSize)) + if (point.X < 0 || point.X >= static_cast(newMapSize) || point.Y < 0 || point.Y >= static_cast(newMapSize)) { onMap = false; break; } - m_WindStrength[point.Y * m_MapSize + point.X] = point.windStrength; + m_WindStrength[point.Y * newMapSize + point.X] = point.windStrength; } } // TODO: should perhaps blur a little, or change the above code to incorporate neighboring tiles a bit. } -//////////////////////////////////////////////////////////////////////// -// TODO: This will always recalculate for now -void WaterManager::SetMapSize(size_t size) +void WaterManager::RecomputeWaterDataIfNeeded(const CWater& water) { - // TODO: Im' blindly trusting the user here. - m_MapSize = size; - m_NeedInfoUpdate = true; - m_updatei0 = 0; - m_updatei1 = size; - m_updatej0 = 0; - m_updatej1 = size; + if (water.GetVersion() == m_LastWaterVersion + && water.GetMapSize() == m_MapSize) + return; + RecomputeDistanceHeightmap(water); + RecomputeWindStrength(water); + CreateWaveMeshes(water); + m_MapSize = water.GetMapSize(); + m_LastWaterVersion = water.GetVersion(); +} - m_DistanceHeightmap.reset(); - m_WindStrength.reset(); +float WaterManager::GetWindStrength(ssize_t x, ssize_t z) const +{ + if (!m_WindStrength) + return 0.f; + + if (x < 0 || z < 0 || (size_t)x >= m_MapSize || (size_t)z >= m_MapSize) + return 0.f; + + return m_WindStrength[x + z * m_MapSize]; } //////////////////////////////////////////////////////////////////////// @@ -1136,7 +1129,7 @@ size_t WaterManager::GetCurrentTextureIndex(const double& period) const { ENSURE(period > 0.0); - return static_cast(m_WaterTexTimer * ARRAY_SIZE(m_WaterTexture) / period) % ARRAY_SIZE(m_WaterTexture); + return static_cast(g_Renderer.GetTimeManager().GetGlobalTime() * ARRAY_SIZE(m_WaterTexture) / period) % ARRAY_SIZE(m_WaterTexture); } size_t WaterManager::GetNextTextureIndex(const double& period) const Index: source/simulation2/Simulation2.h =================================================================== --- source/simulation2/Simulation2.h +++ source/simulation2/Simulation2.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -34,6 +34,7 @@ class CSimulation2Impl; class CTerrain; class CUnitManager; +class CWater; class IComponent; class SceneCollector; class ScriptInterface; @@ -50,7 +51,7 @@ public: // TODO: CUnitManager should probably be handled automatically by this // module, but for now we'll have it passed in externally instead - CSimulation2(CUnitManager* unitManager, std::shared_ptr cx, CTerrain* terrain); + CSimulation2(CUnitManager* unitManager, std::shared_ptr cx, CTerrain* terrain, CWater* water); ~CSimulation2(); void EnableSerializationTest(); Index: source/simulation2/Simulation2.cpp =================================================================== --- source/simulation2/Simulation2.cpp +++ source/simulation2/Simulation2.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -54,13 +54,14 @@ class CSimulation2Impl { public: - CSimulation2Impl(CUnitManager* unitManager, std::shared_ptr cx, CTerrain* terrain) : + CSimulation2Impl(CUnitManager* unitManager, std::shared_ptr cx, CTerrain* terrain, CWater* water) : m_SimContext(), m_ComponentManager(m_SimContext, cx), m_EnableOOSLog(false), m_EnableSerializationTest(false), m_RejoinTestTurn(-1), m_TestingRejoin(false), m_MapSettings(cx->GetGeneralJSContext()), m_InitAttributes(cx->GetGeneralJSContext()) { m_SimContext.m_UnitManager = unitManager; m_SimContext.m_Terrain = terrain; + m_SimContext.m_Water = water; m_ComponentManager.LoadComponentTypes(); RegisterFileReloadFunc(ReloadChangedFileCB, this); @@ -635,8 +636,8 @@ //////////////////////////////////////////////////////////////// -CSimulation2::CSimulation2(CUnitManager* unitManager, std::shared_ptr cx, CTerrain* terrain) : - m(new CSimulation2Impl(unitManager, cx, terrain)) +CSimulation2::CSimulation2(CUnitManager* unitManager, std::shared_ptr cx, CTerrain* terrain, CWater* water) : + m(new CSimulation2Impl(unitManager, cx, terrain, water)) { } Index: source/simulation2/components/CCmpTerrain.cpp =================================================================== --- source/simulation2/components/CCmpTerrain.cpp +++ source/simulation2/components/CCmpTerrain.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -21,9 +21,8 @@ #include "ICmpTerrain.h" #include "graphics/Terrain.h" -#include "renderer/Renderer.h" -#include "renderer/SceneRenderer.h" -#include "renderer/WaterManager.h" +#include "graphics/Water.h" +#include "graphics/RenderableObject.h" #include "maths/Vector3D.h" #include "simulation2/components/ICmpObstructionManager.h" #include "simulation2/components/ICmpRangeManager.h" @@ -142,16 +141,17 @@ entity_pos_t::FromInt(tiles*(int)TERRAIN_TILE_SIZE)); } - if (ReloadWater && CRenderer::IsInitialised()) + if (ReloadWater) { - g_Renderer.GetSceneRenderer().GetWaterManager().SetMapSize(vertices); - g_Renderer.GetSceneRenderer().GetWaterManager().RecomputeWaterData(); + GetSimContext().GetWater().SetMapSize(vertices); } MakeDirty(0, 0, tiles+1, tiles+1); } void MakeDirty(i32 i0, i32 j0, i32 i1, i32 j1) override { + GetSimContext().GetTerrain().MakeDirty(i0, j0, i1, j1, RENDERDATA_UPDATE_VERTICES); + CMessageTerrainChanged msg(i0, j0, i1, j1); GetSimContext().GetComponentManager().BroadcastMessage(msg); } Index: source/simulation2/components/CCmpWaterManager.cpp =================================================================== --- source/simulation2/components/CCmpWaterManager.cpp +++ source/simulation2/components/CCmpWaterManager.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -22,9 +22,7 @@ #include "graphics/RenderableObject.h" #include "graphics/Terrain.h" -#include "renderer/Renderer.h" -#include "renderer/SceneRenderer.h" -#include "renderer/WaterManager.h" +#include "graphics/Water.h" #include "simulation2/MessageTypes.h" #include "tools/atlas/GameInterface/GameLoop.h" @@ -33,9 +31,6 @@ public: static void ClassInit(CComponentManager& componentManager) { - // No need to subscribe to WaterChanged since we're actually the one sending those. - componentManager.SubscribeToMessageType(MT_Interpolate); - componentManager.SubscribeToMessageType(MT_TerrainChanged); } DEFAULT_COMPONENT_ALLOCATOR(WaterManager) @@ -55,9 +50,6 @@ void Deinit() override { - // Clear the map size & data. - if (CRenderer::IsInitialised()) - g_Renderer.GetSceneRenderer().GetWaterManager().SetMapSize(0); } void Serialize(ISerializer& serialize) override @@ -71,43 +63,12 @@ deserialize.NumberFixed_Unbounded("height", m_WaterHeight); - if (CRenderer::IsInitialised()) - g_Renderer.GetSceneRenderer().GetWaterManager().SetMapSize(GetSimContext().GetTerrain().GetVerticesPerSide()); - RecomputeWaterData(); } - void HandleMessage(const CMessage& msg, bool UNUSED(global)) override - { - switch (msg.GetType()) - { - case MT_Interpolate: - { - const CMessageInterpolate& msgData = static_cast (msg); - if (CRenderer::IsInitialised()) - g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterTexTimer += msgData.deltaSimTime; - break; - } - case MT_TerrainChanged: - { - // Tell the renderer to redraw part of the map. - if (CRenderer::IsInitialised()) - { - const CMessageTerrainChanged& msgData = static_cast (msg); - GetSimContext().GetTerrain().MakeDirty(msgData.i0,msgData.j0,msgData.i1,msgData.j1,RENDERDATA_UPDATE_VERTICES); - } - break; - } - } - } - void RecomputeWaterData() override { - if (CRenderer::IsInitialised()) - { - g_Renderer.GetSceneRenderer().GetWaterManager().RecomputeWaterData(); - g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight = m_WaterHeight.ToFloat(); - } + GetSimContext().GetWater().SetWaterHeight(m_WaterHeight.ToFloat()); // Tell the terrain it'll need to recompute its cached render data GetSimContext().GetTerrain().MakeDirty(RENDERDATA_UPDATE_VERTICES); Index: source/simulation2/system/SimContext.h =================================================================== --- source/simulation2/system/SimContext.h +++ source/simulation2/system/SimContext.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -23,6 +23,7 @@ class CComponentManager; class CUnitManager; class CTerrain; +class CWater; class ScriptInterface; /** @@ -32,9 +33,6 @@ class CSimContext { public: - CSimContext(); - ~CSimContext(); - CComponentManager& GetComponentManager() const; void SetComponentManager(CComponentManager* man); @@ -43,6 +41,8 @@ CTerrain& GetTerrain() const; + CWater& GetWater() const; + ScriptInterface& GetScriptInterface() const; void SetSystemEntity(CEntityHandle ent) { m_SystemEntity = ent; } @@ -55,9 +55,10 @@ int GetCurrentDisplayedPlayer() const; private: - CComponentManager* m_ComponentManager; - CUnitManager* m_UnitManager; - CTerrain* m_Terrain; + CComponentManager* m_ComponentManager = nullptr; + CUnitManager* m_UnitManager = nullptr; + CTerrain* m_Terrain = nullptr; + CWater* m_Water = nullptr; CEntityHandle m_SystemEntity; Index: source/simulation2/system/SimContext.cpp =================================================================== --- source/simulation2/system/SimContext.cpp +++ source/simulation2/system/SimContext.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -23,15 +23,6 @@ #include "ps/Game.h" -CSimContext::CSimContext() : - m_ComponentManager(NULL), m_UnitManager(NULL), m_Terrain(NULL) -{ -} - -CSimContext::~CSimContext() -{ -} - CComponentManager& CSimContext::GetComponentManager() const { return *m_ComponentManager; @@ -54,6 +45,12 @@ return *m_Terrain; } +CWater& CSimContext::GetWater() const +{ + ENSURE(m_Water); + return *m_Water; +} + void CSimContext::SetComponentManager(CComponentManager* man) { ENSURE(!m_ComponentManager); Index: source/tools/atlas/GameInterface/ActorViewer.cpp =================================================================== --- source/tools/atlas/GameInterface/ActorViewer.cpp +++ source/tools/atlas/GameInterface/ActorViewer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -44,6 +44,7 @@ #include "ps/GameSetup/Config.h" #include "ps/ProfileViewer.h" #include "ps/VideoMode.h" +#include "ps/World.h" #include "renderer/backend/IDevice.h" #include "renderer/backend/IDeviceCommandContext.h" #include "renderer/Renderer.h" @@ -77,7 +78,8 @@ MeshManager(ColladaManager), SkeletonAnimManager(ColladaManager), UnitManager(), - Simulation2(&UnitManager, g_ScriptContext, &Terrain), + World(nullptr), + Simulation2(&UnitManager, g_ScriptContext, &Terrain, &World.GetWater()), ObjectManager(MeshManager, SkeletonAnimManager, Simulation2), LOSTexture(Simulation2), TerritoryTexture(Simulation2), @@ -110,6 +112,7 @@ CMeshManager MeshManager; CSkeletonAnimManager SkeletonAnimManager; CUnitManager UnitManager; + CWorld World; // Keep before Simulation2 - needed for CWater init CSimulation2 Simulation2; CObjectManager ObjectManager; // Keep this after Simulation2 - it needs it for initialisation. CLOSTexture LOSTexture; @@ -206,6 +209,11 @@ Simulation2.RenderSubmit(*c, frustum, false); } + virtual const CWorld& GetWorld() const + { + return World; + } + virtual CLOSTexture& GetLOSTexture() { return LOSTexture; Index: source/tools/atlas/GameInterface/Handlers/EnvironmentHandlers.cpp =================================================================== --- source/tools/atlas/GameInterface/Handlers/EnvironmentHandlers.cpp +++ source/tools/atlas/GameInterface/Handlers/EnvironmentHandlers.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -23,6 +23,7 @@ #include "graphics/LightEnv.h" #include "graphics/Terrain.h" +#include "graphics/Water.h" #include "maths/MathUtil.h" #include "ps/CStr.h" #include "ps/Game.h" @@ -41,21 +42,17 @@ { sEnvironmentSettings s; - CmpPtr cmpWaterManager(*g_Game->GetSimulation2(), SYSTEM_ENTITY); - ENSURE(cmpWaterManager); - - s.waterheight = cmpWaterManager->GetExactWaterLevel(0, 0) / (65536.f * HEIGHT_SCALE); - - const WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager(); - s.watertype = waterManager.m_WaterType; - s.waterwaviness = waterManager.m_Waviness; - s.watermurkiness = waterManager.m_Murkiness; - s.windangle = waterManager.m_WindAngle; + CWater& water = g_Game->GetWorld()->GetWater(); + s.waterheight = water.GetWaterHeight() / (65536.f * HEIGHT_SCALE); + s.watertype = water.m_WaterType; + s.waterwaviness = water.m_Waviness; + s.watermurkiness = water.m_Murkiness; + s.windangle = water.m_WindAngle; // CColor colors #define COLOR(A, B) A = Color((int)(B.r*255), (int)(B.g*255), (int)(B.b*255)) - COLOR(s.watercolor, waterManager.m_WaterColor); - COLOR(s.watertint, waterManager.m_WaterTint); + COLOR(s.watercolor, water.m_WaterColor); + COLOR(s.watertint, water.m_WaterTint); #undef COLOR float sunrotation = g_LightEnv.GetRotation(); @@ -100,21 +97,23 @@ cmpWaterManager->SetWaterLevel(entity_pos_t::FromFloat(s.waterheight * (65536.f * HEIGHT_SCALE))); - WaterManager& waterManager = g_Renderer.GetSceneRenderer().GetWaterManager(); - waterManager.m_Waviness = s.waterwaviness; - waterManager.m_Murkiness = s.watermurkiness; - waterManager.m_WindAngle = s.windangle; - if (waterManager.m_WaterType != *s.watertype) + CWater& water = g_Game->GetWorld()->GetWater(); + water.m_Waviness = s.waterwaviness; + water.m_Murkiness = s.watermurkiness; + water.m_WindAngle = s.windangle; + if (water.m_WaterType != *s.watertype) { - waterManager.m_WaterType = *s.watertype; - waterManager.ReloadWaterNormalTextures(); + water.m_WaterType = *s.watertype; + g_Renderer.GetSceneRenderer().GetWaterManager().ReloadWaterNormalTextures(water.m_WaterType); } #define COLOR(A, B) B = CColor(A->r/255.f, A->g/255.f, A->b/255.f, 1.f) - COLOR(s.watercolor, waterManager.m_WaterColor); - COLOR(s.watertint, waterManager.m_WaterTint); + COLOR(s.watercolor, water.m_WaterColor); + COLOR(s.watertint, water.m_WaterTint); #undef COLOR + cmpWaterManager->RecomputeWaterData(); + g_LightEnv.SetRotation(s.sunrotation); g_LightEnv.SetElevation(s.sunelevation); @@ -142,8 +141,6 @@ COLOR(s.ambientcolor, g_LightEnv.m_AmbientColor); COLOR(s.fogcolor, g_LightEnv.m_FogColor); #undef COLOR - - cmpWaterManager->RecomputeWaterData(); } BEGIN_COMMAND(SetEnvironmentSettings) @@ -229,7 +226,6 @@ ENSURE(cmpWaterManager); cmpWaterManager->SetWaterLevel(height); - cmpWaterManager->RecomputeWaterData(); } }; END_COMMAND(PickWaterHeight) Index: source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp =================================================================== --- source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp +++ source/tools/atlas/GameInterface/Handlers/MapHandlers.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -31,6 +31,7 @@ #include "graphics/Terrain.h" #include "graphics/TerrainTextureEntry.h" #include "graphics/TerrainTextureManager.h" +#include "graphics/Water.h" #include "lib/bits.h" #include "lib/file/vfs/vfs_path.h" #include "lib/status.h" @@ -43,7 +44,6 @@ #include "ps/World.h" #include "renderer/Renderer.h" #include "renderer/SceneRenderer.h" -#include "renderer/WaterManager.h" #include "scriptinterface/Object.h" #include "scriptinterface/JSON.h" #include "simulation2/Simulation2.h" @@ -226,7 +226,7 @@ VfsPath pathname = VfsPath(*msg->filename).ChangeExtension(L".pmp"); writer.SaveMap(pathname, g_Game->GetWorld()->GetTerrain(), - &g_Renderer.GetSceneRenderer().GetWaterManager(), &g_Renderer.GetSceneRenderer().GetSkyManager(), + &g_Game->GetWorld()->GetWater(), &g_Renderer.GetSceneRenderer().GetSkyManager(), &g_LightEnv, g_Game->GetView()->GetCamera(), g_Game->GetView()->GetCinema(), &g_Renderer.GetPostprocManager(), g_Game->GetSimulation2()); @@ -298,7 +298,7 @@ ssize_t w = dimension; ssize_t h = dimension; - const float waterHeight = g_Renderer.GetSceneRenderer().GetWaterManager().m_WaterHeight; + const float waterHeight = g_Game->GetWorld()->GetWater().GetWaterHeight(); for (ssize_t j = 0; j < h; ++j) { Index: source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp =================================================================== --- source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp +++ source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 Wildfire Games. +/* Copyright (C) 2023 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -38,8 +38,6 @@ #include "ps/CLogger.h" #include "ps/Game.h" #include "ps/World.h" -#include "renderer/Renderer.h" -#include "renderer/WaterManager.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpObstruction.h" #include "simulation2/components/ICmpOwnership.h"