Line data Source code
1 : /* Copyright (C) 2022 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #include "precompiled.h"
19 :
20 : #include "simulation2/system/Component.h"
21 : #include "ICmpTerrain.h"
22 :
23 : #include "graphics/Terrain.h"
24 : #include "renderer/Renderer.h"
25 : #include "renderer/SceneRenderer.h"
26 : #include "renderer/WaterManager.h"
27 : #include "maths/Vector3D.h"
28 : #include "simulation2/components/ICmpObstructionManager.h"
29 : #include "simulation2/components/ICmpRangeManager.h"
30 : #include "simulation2/MessageTypes.h"
31 :
32 9 : class CCmpTerrain final : public ICmpTerrain
33 : {
34 : public:
35 116 : static void ClassInit(CComponentManager& UNUSED(componentManager))
36 : {
37 116 : }
38 :
39 6 : DEFAULT_COMPONENT_ALLOCATOR(Terrain)
40 :
41 : CTerrain* m_Terrain; // not null
42 :
43 116 : static std::string GetSchema()
44 : {
45 116 : return "<a:component type='system'/><empty/>";
46 : }
47 :
48 3 : void Init(const CParamNode& UNUSED(paramNode)) override
49 : {
50 3 : m_Terrain = &GetSimContext().GetTerrain();
51 3 : }
52 :
53 3 : void Deinit() override
54 : {
55 3 : }
56 :
57 0 : void Serialize(ISerializer& UNUSED(serialize)) override
58 : {
59 0 : }
60 :
61 0 : void Deserialize(const CParamNode& paramNode, IDeserializer& UNUSED(deserialize)) override
62 : {
63 0 : Init(paramNode);
64 0 : }
65 :
66 0 : bool IsLoaded() const override
67 : {
68 0 : return m_Terrain->GetVerticesPerSide() != 0;
69 : }
70 :
71 0 : CFixedVector3D CalcNormal(entity_pos_t x, entity_pos_t z) const override
72 : {
73 0 : CFixedVector3D normal;
74 0 : m_Terrain->CalcNormalFixed((x / (int)TERRAIN_TILE_SIZE).ToInt_RoundToZero(), (z / (int)TERRAIN_TILE_SIZE).ToInt_RoundToZero(), normal);
75 0 : return normal;
76 : }
77 :
78 0 : CVector3D CalcExactNormal(float x, float z) const override
79 : {
80 0 : return m_Terrain->CalcExactNormal(x, z);
81 : }
82 :
83 0 : entity_pos_t GetGroundLevel(entity_pos_t x, entity_pos_t z) const override
84 : {
85 : // TODO: this can crash if the terrain heightmap isn't initialised yet
86 :
87 0 : return m_Terrain->GetExactGroundLevelFixed(x, z);
88 : }
89 :
90 0 : float GetExactGroundLevel(float x, float z) const override
91 : {
92 0 : return m_Terrain->GetExactGroundLevel(x, z);
93 : }
94 :
95 0 : u16 GetTilesPerSide() const override
96 : {
97 0 : ssize_t tiles = m_Terrain->GetTilesPerSide();
98 :
99 0 : if (tiles == -1)
100 0 : return 0;
101 0 : ENSURE(1 <= tiles && tiles <= 65535);
102 0 : return (u16)tiles;
103 : }
104 :
105 0 : u32 GetMapSize() const override
106 : {
107 0 : return GetTilesPerSide() * TERRAIN_TILE_SIZE;
108 : }
109 :
110 0 : u16 GetVerticesPerSide() const override
111 : {
112 0 : ssize_t vertices = m_Terrain->GetVerticesPerSide();
113 0 : ENSURE(1 <= vertices && vertices <= 65535);
114 0 : return (u16)vertices;
115 : }
116 :
117 0 : CTerrain* GetCTerrain() override
118 : {
119 0 : return m_Terrain;
120 : }
121 :
122 0 : void ReloadTerrain(bool ReloadWater) override
123 : {
124 : // TODO: should refactor this code to be nicer
125 :
126 0 : u16 tiles = GetTilesPerSide();
127 0 : u16 vertices = GetVerticesPerSide();
128 :
129 0 : CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
130 0 : if (cmpObstructionManager)
131 : {
132 0 : cmpObstructionManager->SetBounds(entity_pos_t::Zero(), entity_pos_t::Zero(),
133 : entity_pos_t::FromInt(tiles*(int)TERRAIN_TILE_SIZE),
134 0 : entity_pos_t::FromInt(tiles*(int)TERRAIN_TILE_SIZE));
135 : }
136 :
137 0 : CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity());
138 0 : if (cmpRangeManager)
139 : {
140 0 : cmpRangeManager->SetBounds(entity_pos_t::Zero(), entity_pos_t::Zero(),
141 : entity_pos_t::FromInt(tiles*(int)TERRAIN_TILE_SIZE),
142 0 : entity_pos_t::FromInt(tiles*(int)TERRAIN_TILE_SIZE));
143 : }
144 :
145 0 : if (ReloadWater && CRenderer::IsInitialised())
146 : {
147 0 : g_Renderer.GetSceneRenderer().GetWaterManager().SetMapSize(vertices);
148 0 : g_Renderer.GetSceneRenderer().GetWaterManager().RecomputeWaterData();
149 : }
150 0 : MakeDirty(0, 0, tiles+1, tiles+1);
151 0 : }
152 :
153 0 : void MakeDirty(i32 i0, i32 j0, i32 i1, i32 j1) override
154 : {
155 0 : CMessageTerrainChanged msg(i0, j0, i1, j1);
156 0 : GetSimContext().GetComponentManager().BroadcastMessage(msg);
157 0 : }
158 : };
159 :
160 119 : REGISTER_COMPONENT_TYPE(Terrain)
|