Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
TerritoryTexture.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2012 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 "TerritoryTexture.h"
21 
22 #include "graphics/Terrain.h"
23 #include "lib/bits.h"
24 #include "ps/Overlay.h"
25 #include "ps/Profile.h"
26 #include "renderer/Renderer.h"
32 
33 // TODO: There's a lot of duplication with CLOSTexture - might be nice to refactor a bit
34 
36  m_Simulation(simulation), m_DirtyID(0), m_Texture(0), m_MapSize(0), m_TextureSize(0)
37 {
38 }
39 
41 {
42  if (m_Texture)
43  DeleteTexture();
44 }
45 
47 {
48  glDeleteTextures(1, &m_Texture);
49  m_Texture = 0;
50 }
51 
53 {
55  if (!cmpTerritoryManager)
56  return false;
57 
58  return cmpTerritoryManager->NeedUpdate(&m_DirtyID);
59 }
60 
62 {
63  if (UpdateDirty())
64  RecomputeTexture(unit);
65 
66  g_Renderer.BindTexture(unit, m_Texture);
67 }
68 
70 {
71  if (UpdateDirty())
73 
74  return m_Texture;
75 }
76 
78 {
79  ENSURE(!UpdateDirty());
80  return &m_TextureMatrix._11;
81 }
82 
84 {
85  ENSURE(!UpdateDirty());
87 }
88 
90 {
92  if (!cmpTerrain)
93  return;
94 
95  m_MapSize = cmpTerrain->GetVerticesPerSide() - 1;
96 
97  m_TextureSize = (GLsizei)round_up_to_pow2((size_t)m_MapSize);
98 
99  glGenTextures(1, &m_Texture);
100  g_Renderer.BindTexture(unit, m_Texture);
101 
102  // Initialise texture with transparency, for the areas we don't
103  // overwrite with glTexSubImage2D later
104  u8* texData = new u8[m_TextureSize * m_TextureSize * 4];
105  memset(texData, 0x00, m_TextureSize * m_TextureSize * 4);
106  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TextureSize, m_TextureSize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, texData);
107  delete[] texData;
108 
109  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
110  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
111  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
112  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
113 
114  {
115  // Texture matrix: We want to map
116  // world pos (0, y, 0) (i.e. bottom-left of first tile)
117  // onto texcoord (0, 0) (i.e. bottom-left of first texel);
118  // world pos (mapsize*cellsize, y, mapsize*cellsize) (i.e. top-right of last tile)
119  // onto texcoord (mapsize / texsize, mapsize / texsize) (i.e. top-right of last texel)
120 
121  float s = 1.f / (float)(m_TextureSize * TERRAIN_TILE_SIZE);
122  float t = 0.f;
124  m_TextureMatrix._11 = s;
125  m_TextureMatrix._23 = s;
126  m_TextureMatrix._14 = t;
127  m_TextureMatrix._24 = t;
128  m_TextureMatrix._44 = 1;
129  }
130 
131  {
132  // Minimap matrix: We want to map UV (0,0)-(1,1) onto (0,0)-(mapsize/texsize, mapsize/texsize)
133 
134  float s = m_MapSize / (float)m_TextureSize;
139  }
140 }
141 
143 {
144  // If the map was resized, delete and regenerate the texture
145  if (m_Texture)
146  {
148  if (cmpTerrain && m_MapSize != (ssize_t)cmpTerrain->GetVerticesPerSide())
149  DeleteTexture();
150  }
151 
152  if (!m_Texture)
153  ConstructTexture(unit);
154 
155  PROFILE("recompute territory texture");
156 
157  std::vector<u8> bitmap;
158  bitmap.resize(m_MapSize * m_MapSize * 4);
159 
161  if (!cmpTerritoryManager)
162  return;
163 
164  const Grid<u8> territories = cmpTerritoryManager->GetTerritoryGrid();
165 
166  GenerateBitmap(territories, &bitmap[0], m_MapSize, m_MapSize);
167 
168  g_Renderer.BindTexture(unit, m_Texture);
169  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize, m_MapSize, GL_BGRA_EXT, GL_UNSIGNED_BYTE, &bitmap[0]);
170 }
171 
172 void CTerritoryTexture::GenerateBitmap(const Grid<u8>& territories, u8* bitmap, ssize_t w, ssize_t h)
173 {
174  int alphaMax = 0xC0;
175  int alphaFalloff = 0x20;
176 
178 
179  std::vector<CColor> colors;
180  i32 numPlayers = cmpPlayerManager->GetNumPlayers();
181  for (i32 p = 0; p < numPlayers; ++p)
182  {
183  CColor color(1, 0, 1, 1);
184  CmpPtr<ICmpPlayer> cmpPlayer(m_Simulation, cmpPlayerManager->GetPlayerByID(p));
185  if (cmpPlayer)
186  color = cmpPlayer->GetColour();
187  colors.push_back(color);
188  }
189 
190  u8* p = bitmap;
191  for (ssize_t j = 0; j < h; ++j)
192  {
193  for (ssize_t i = 0; i < w; ++i)
194  {
195  u8 val = territories.get(i, j) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK;
196 
197  CColor color(1, 0, 1, 1);
198  // Force neutral territories to pure white, so that later we can omit them from the texture
199  if (val == 0)
200  color = CColor(1, 1, 1, 0);
201  else if (val < colors.size())
202  color = colors[val];
203 
204  *p++ = (int)(color.b*255.f);
205  *p++ = (int)(color.g*255.f);
206  *p++ = (int)(color.r*255.f);
207 
208  if ((i > 0 && (territories.get(i-1, j) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK) != val)
209  || (i < w-1 && (territories.get(i+1, j) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK) != val)
210  || (j > 0 && (territories.get(i, j-1) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK) != val)
211  || (j < h-1 && (territories.get(i, j+1) & ICmpTerritoryManager::TERRITORY_PLAYER_MASK) != val)
212  )
213  {
214  *p++ = alphaMax;
215  }
216  else
217  {
218  *p++ = 0x00;
219  }
220  }
221  }
222 
223  // Do a low-quality cheap blur effect
224 
225  for (ssize_t j = 0; j < h; ++j)
226  {
227  int a;
228 
229  a = 0;
230  for (ssize_t i = 0; i < w; ++i)
231  {
232  a = std::max(a - alphaFalloff, (int)bitmap[(j*w+i)*4 + 3]);
233  bitmap[(j*w+i)*4 + 3] = a;
234  }
235 
236  a = 0;
237  for (ssize_t i = w-1; i >= 0; --i)
238  {
239  a = std::max(a - alphaFalloff, (int)bitmap[(j*w+i)*4 + 3]);
240  bitmap[(j*w+i)*4 + 3] = a;
241  }
242  }
243 
244  for (ssize_t i = 0; i < w; ++i)
245  {
246  int a;
247 
248  a = 0;
249  for (ssize_t j = 0; j < w; ++j)
250  {
251  a = std::max(a - alphaFalloff, (int)bitmap[(j*w+i)*4 + 3]);
252  bitmap[(j*w+i)*4 + 3] = a;
253  }
254 
255  a = 0;
256  for (ssize_t j = w-1; j >= 0; --j)
257  {
258  a = std::max(a - alphaFalloff, (int)bitmap[(j*w+i)*4 + 3]);
259  bitmap[(j*w+i)*4 + 3] = a;
260  }
261  }
262 
263  // Add a gap between the boundaries, by deleting the max-alpha tiles
264  for (ssize_t j = 0; j < h; ++j)
265  {
266  for (ssize_t i = 0; i < w; ++i)
267  {
268  if (bitmap[(j*w+i)*4 + 3] == alphaMax)
269  bitmap[(j*w+i)*4 + 3] = 0;
270  }
271  }
272 
273  // Don't show neutral territory boundaries
274  for (ssize_t j = 0; j < h; ++j)
275  {
276  for (ssize_t i = 0; i < w; ++i)
277  {
278  ssize_t idx = (j*w+i)*4;
279  if (bitmap[idx] == 255 && bitmap[idx+1] == 255 && bitmap[idx+2] == 255)
280  bitmap[idx+3] = 0;
281  }
282  }
283 }
#define u8
Definition: types.h:39
CTerritoryTexture(CSimulation2 &simulation)
float g
Definition: Overlay.h:57
float _22
Definition: Matrix3D.h:43
const ssize_t TERRAIN_TILE_SIZE
metres [world space units] per tile in x and z
Definition: Terrain.h:40
float _44
Definition: Matrix3D.h:45
Definition: Overlay.h:34
#define i32
Definition: types.h:36
void SetZero()
Definition: Matrix3D.cpp:39
virtual const Grid< u8 > & GetTerritoryGrid()=0
For each tile, the TERRITORY_PLAYER_MASK bits are player ID; TERRITORY_CONNECTED_MASK is set if the t...
const float * GetMinimapTextureMatrix()
Returns a matrix to map (0,0)-(1,1) texture coordinates onto texture coordinates, in the form expecte...
virtual bool NeedUpdate(size_t *dirtyID)=0
void BindTexture(int unit)
Recomputes the territory texture if necessary, and binds it to the requested texture unit...
float _11
Definition: Matrix3D.h:42
const entity_id_t SYSTEM_ENTITY
Entity ID for singleton &#39;system&#39; components.
Definition: Entity.h:44
Public API for simulation system.
Definition: Simulation2.h:46
#define g_Renderer
Definition: Renderer.h:61
CMatrix3D m_TextureMatrix
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
T round_up_to_pow2(T x)
round up to next larger power of two.
Definition: bits.h:244
float b
Definition: Overlay.h:57
bool UpdateDirty()
Returns true if the territory state has changed since the last call to this function.
virtual entity_id_t GetPlayerByID(int32_t id)=0
void GenerateBitmap(const Grid< u8 > &territories, u8 *bitmap, ssize_t w, ssize_t h)
GLuint GetTexture()
Recomputes the territory texture if necessary, and returns the texture handle.
#define PROFILE(name)
Definition: Profile.h:195
virtual u16 GetVerticesPerSide()=0
Returns number of vertices per side on the terrain.
float _24
Definition: Matrix3D.h:45
CMatrix3D m_MinimapTextureMatrix
A simplified syntax for accessing entity components.
Definition: CmpPtr.h:55
intptr_t ssize_t
Definition: wposix_types.h:82
const float * GetTextureMatrix()
Returns a matrix to map (x,y,z) world coordinates onto (u,v) texture coordinates, in the form expecte...
static const int TERRITORY_PLAYER_MASK
float _23
Definition: Matrix3D.h:44
void RecomputeTexture(int unit)
T & get(int i, int j) const
Definition: Grid.h:93
void ConstructTexture(int unit)
virtual int32_t GetNumPlayers()=0
float r
Definition: Overlay.h:57
CSimulation2 & m_Simulation
float _14
Definition: Matrix3D.h:45