Line data Source code
1 : /* Copyright (C) 2023 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 : #ifndef INCLUDED_MINIMAPTEXTURE
19 : #define INCLUDED_MINIMAPTEXTURE
20 :
21 : #include "graphics/Color.h"
22 : #include "graphics/ShaderTechniquePtr.h"
23 : #include "graphics/Texture.h"
24 : #include "maths/Vector2D.h"
25 : #include "renderer/backend/IDeviceCommandContext.h"
26 : #include "renderer/backend/IShaderProgram.h"
27 : #include "renderer/backend/ITexture.h"
28 : #include "renderer/VertexArray.h"
29 :
30 : #include <memory>
31 : #include <string>
32 : #include <unordered_map>
33 : #include <vector>
34 :
35 : class CLOSTexture;
36 : class CSimulation2;
37 : class CTerrain;
38 : class CTerritoryTexture;
39 :
40 : class CMiniMapTexture
41 : {
42 : NONCOPYABLE(CMiniMapTexture);
43 : public:
44 : CMiniMapTexture(CSimulation2& simulation);
45 : ~CMiniMapTexture();
46 :
47 : /**
48 : * Marks the texture as dirty if it's old enough to redraw it on Render.
49 : */
50 : void Update(const float deltaRealTime);
51 :
52 : /**
53 : * Redraws the texture if it's dirty.
54 : */
55 : void Render(
56 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
57 : CLOSTexture& losTexture, CTerritoryTexture& territoryTexture);
58 :
59 0 : const CTexturePtr& GetTexture() const { return m_FinalTexture; }
60 :
61 0 : bool IsFlipped() const { return m_Flipped; }
62 :
63 : /**
64 : * @return The maximum height for unit passage in water.
65 : */
66 : static float GetShallowPassageHeight();
67 :
68 0 : struct Icon
69 : {
70 : CTexturePtr texture;
71 : CColor color;
72 : CVector2D worldPosition;
73 : float halfSize;
74 : };
75 : // Returns icons for corresponding entities on the minimap texture.
76 0 : const std::vector<Icon>& GetIcons() { return m_Icons; }
77 :
78 : private:
79 : void CreateTextures(
80 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
81 : const CTerrain* terrain);
82 : void DestroyTextures();
83 : void RebuildTerrainTexture(
84 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
85 : const CTerrain* terrain);
86 : void RenderFinalTexture(
87 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
88 : CLOSTexture& losTexture, CTerritoryTexture& territoryTexture);
89 : void UpdateAndUploadEntities(
90 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
91 : const float entityRadius, const double& currentTime);
92 : void DrawEntities(
93 : Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
94 : const float entityRadius);
95 :
96 : CSimulation2& m_Simulation;
97 :
98 : bool m_TerrainTextureDirty = true;
99 : bool m_FinalTextureDirty = true;
100 : double m_LastFinalTextureUpdate = 0.0;
101 : bool m_Flipped = false;
102 :
103 : // minimap texture handles
104 : std::unique_ptr<Renderer::Backend::ITexture> m_TerrainTexture;
105 :
106 : CTexturePtr m_FinalTexture;
107 :
108 : std::unique_ptr<Renderer::Backend::IFramebuffer>
109 : m_FinalTextureFramebuffer;
110 :
111 : // texture data
112 : std::unique_ptr<u32[]> m_TerrainData;
113 :
114 : // map size
115 : ssize_t m_MapSize = 0;
116 :
117 : // Maximal water height to allow the passage of a unit (for underwater shallows).
118 : float m_ShallowPassageHeight = 0.0f;
119 : float m_WaterHeight = 0.0f;
120 :
121 : Renderer::Backend::IVertexInputLayout* m_QuadVertexInputLayout = nullptr;
122 : Renderer::Backend::IVertexInputLayout* m_EntitiesVertexInputLayout = nullptr;
123 :
124 : VertexIndexArray m_IndexArray;
125 : VertexArray m_VertexArray;
126 : VertexArray::Attribute m_AttributePos;
127 : VertexArray::Attribute m_AttributeColor;
128 :
129 : bool m_UseInstancing = false;
130 : // Vertex data if instancing is supported.
131 : VertexArray m_InstanceVertexArray;
132 : VertexArray::Attribute m_InstanceAttributePosition;
133 :
134 : CShaderTechniquePtr m_TerritoryTechnique;
135 :
136 : size_t m_EntitiesDrawn = 0;
137 :
138 : double m_PingDuration = 25.0;
139 : double m_HalfBlinkDuration = 0.0;
140 : double m_NextBlinkTime = 0.0;
141 : bool m_BlinkState = false;
142 :
143 : std::vector<Icon> m_Icons;
144 : // We store the map as a member to avoid redundant reallocations on each
145 : // update. We use a grid approach to combine icons by distance.
146 0 : struct CellIconKey
147 : {
148 : std::string path;
149 : u8 r, g, b;
150 : };
151 : struct CellIconKeyHash
152 : {
153 : size_t operator()(const CellIconKey& key) const;
154 : };
155 : struct CellIconKeyEqual
156 : {
157 : bool operator()(const CellIconKey& lhs, const CellIconKey& rhs) const;
158 : };
159 : struct CellIcon
160 : {
161 : // TODO: use CVector2DI.
162 : u16 gridX, gridY;
163 : float halfSize;
164 : CVector2D worldPosition;
165 : };
166 : std::unordered_map<CellIconKey, std::vector<CellIcon>, CellIconKeyHash, CellIconKeyEqual> m_IconsCache;
167 : };
168 :
169 : #endif // INCLUDED_MINIMAPTEXTURE
|