Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MiniMap.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2013 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 <math.h>
21 
22 #include "MiniMap.h"
23 
24 #include "graphics/GameView.h"
25 #include "graphics/LOSTexture.h"
26 #include "graphics/MiniPatch.h"
27 #include "graphics/Terrain.h"
31 #include "lib/ogl.h"
33 #include "lib/bits.h"
34 #include "lib/timer.h"
35 #include "ps/ConfigDB.h"
36 #include "ps/Game.h"
37 #include "ps/Profile.h"
38 #include "ps/World.h"
39 #include "renderer/Renderer.h"
40 #include "renderer/WaterManager.h"
45 
46 bool g_GameRestarted = false;
47 
48 // Set max drawn entities to UINT16_MAX for now, which is more than enough
49 // TODO: we should be cleverer about drawing them to reduce clutter
50 const u16 MAX_ENTITIES_DRAWN = 65535;
51 
52 static unsigned int ScaleColor(unsigned int color, float x)
53 {
54  unsigned int r = unsigned(float(color & 0xff) * x);
55  unsigned int g = unsigned(float((color>>8) & 0xff) * x);
56  unsigned int b = unsigned(float((color>>16) & 0xff) * x);
57  return (0xff000000 | r | g<<8 | b<<16);
58 }
59 
61  m_TerrainTexture(0), m_TerrainData(0), m_MapSize(0), m_Terrain(0), m_TerrainDirty(true), m_MapScale(1.f),
62  m_EntitiesDrawn(0), m_IndexArray(GL_STATIC_DRAW), m_VertexArray(GL_DYNAMIC_DRAW),
63  m_NextBlinkTime(0.0), m_PingDuration(25.0), m_BlinkState(false)
64 {
65  AddSetting(GUIST_CColor, "fov_wedge_color");
66  AddSetting(GUIST_CStrW, "tooltip");
67  AddSetting(GUIST_CStr, "tooltip_style");
68  m_Clicking = false;
69  m_MouseHovering = false;
70 
71  // Get the maximum height for unit passage in water.
72  CParamNode externalParamNode;
73  CParamNode::LoadXML(externalParamNode, L"simulation/data/pathfinder.xml");
74  const CParamNode pathingSettings = externalParamNode.GetChild("Pathfinder").GetChild("PassabilityClasses");
75  if (pathingSettings.GetChild("default").IsOk() && pathingSettings.GetChild("default").GetChild("MaxWaterDepth").IsOk())
76  m_ShallowPassageHeight = pathingSettings.GetChild("default").GetChild("MaxWaterDepth").ToFloat();
77  else
79 
80  m_AttributePos.type = GL_FLOAT;
83 
84  m_AttributeColor.type = GL_UNSIGNED_BYTE;
87 
90 
94  for (u16 i = 0; i < MAX_ENTITIES_DRAWN; ++i)
95  {
96  *index++ = i;
97  }
100 
101 
104  for (u16 i = 0; i < MAX_ENTITIES_DRAWN; i++)
105  {
106  (*attrColor)[0] = 0;
107  (*attrColor)[1] = 0;
108  (*attrColor)[2] = 0;
109  (*attrColor)[3] = 0;
110  ++attrColor;
111 
112  (*attrPos)[0] = -10000.0f;
113  (*attrPos)[1] = -10000.0f;
114 
115  ++attrPos;
116 
117  }
119 
120  double blinkDuration = 1.0;
121 
122  // Tests won't have config initialised
124  {
125  CFG_GET_VAL("gui.session.minimap.pingduration", Double, m_PingDuration);
126  CFG_GET_VAL("gui.session.minimap.blinkduration", Double, blinkDuration);
127  }
128  m_HalfBlinkDuration = blinkDuration/2;
129 }
130 
132 {
133  Destroy();
134 }
135 
137 {
138  switch(Message.type)
139  {
141  {
142  if (m_MouseHovering)
143  {
144  SetCameraPos();
145  m_Clicking = true;
146  }
147  break;
148  }
150  {
152  {
153  SetCameraPos();
154  }
155  m_Clicking = false;
156  break;
157  }
159  {
161  {
162  SetCameraPos();
163  }
164  m_Clicking = false;
165  break;
166  }
167  case GUIM_MOUSE_ENTER:
168  {
169  m_MouseHovering = true;
170  break;
171  }
172  case GUIM_MOUSE_LEAVE:
173  {
174  m_Clicking = false;
175  m_MouseHovering = false;
176  break;
177  }
179  {
181  break;
182  }
184  {
186  break;
187  }
188  case GUIM_MOUSE_MOTION:
189  {
191  {
192  SetCameraPos();
193  }
194  break;
195  }
197  case GUIM_MOUSE_WHEEL_UP:
198  Message.Skip();
199  break;
200 
201  default:
202  break;
203  } // switch
204 }
205 
206 void CMiniMap::GetMouseWorldCoordinates(float& x, float& z)
207 {
208  // Determine X and Z according to proportion of mouse position and minimap
209 
210  CPos mousePos = GetMousePos();
211 
212  float px = (mousePos.x - m_CachedActualSize.left) / m_CachedActualSize.GetWidth();
213  float py = (m_CachedActualSize.bottom - mousePos.y) / m_CachedActualSize.GetHeight();
214 
215  float angle = GetAngle();
216 
217  // Scale world coordinates for shrunken square map
218  x = TERRAIN_TILE_SIZE * m_MapSize * (m_MapScale * (cos(angle)*(px-0.5) - sin(angle)*(py-0.5)) + 0.5);
219  z = TERRAIN_TILE_SIZE * m_MapSize * (m_MapScale * (cos(angle)*(py-0.5) + sin(angle)*(px-0.5)) + 0.5);
220 }
221 
223 {
224  CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
225 
226  CVector3D target;
227  GetMouseWorldCoordinates(target.X, target.Z);
228  target.Y = terrain->GetExactGroundLevel(target.X, target.Z);
229  g_Game->GetView()->MoveCameraTarget(target);
230 }
231 
233 {
234  CVector3D cameraIn = m_Camera->m_Orientation.GetIn();
235  return -atan2(cameraIn.X, cameraIn.Z);
236 }
237 
238 void CMiniMap::FireWorldClickEvent(int button, int clicks)
239 {
240  float x, z;
242 
243  CScriptValRooted coords;
244  g_ScriptingHost.GetScriptInterface().Eval("({})", coords);
245  g_ScriptingHost.GetScriptInterface().SetProperty(coords.get(), "x", x, false);
246  g_ScriptingHost.GetScriptInterface().SetProperty(coords.get(), "z", z, false);
247  ScriptEvent("worldclick", coords);
248 
249  UNUSED2(button);
250  UNUSED2(clicks);
251 }
252 
253 #if CONFIG2_GLES
254 #warning TODO: implement minimap for GLES
255 void CMiniMap::Draw()
256 {
257 }
258 #else
259 
260 // render view rect : John M. Mena
261 // This sets up and draws the rectangle on the mini-map
262 // which represents the view of the camera in the world.
264 {
265  // Compute the camera frustum intersected with a fixed-height plane.
266  // TODO: Currently we hard-code the height, so this'll be dodgy when maps aren't the
267  // expected height - how can we make it better without the view rect wobbling in
268  // size while the player scrolls?
269  float h = 16384.f * HEIGHT_SCALE;
270 
271  CVector3D hitPt[4];
272  hitPt[0]=m_Camera->GetWorldCoordinates(0, g_Renderer.GetHeight(), h);
273  hitPt[1]=m_Camera->GetWorldCoordinates(g_Renderer.GetWidth(), g_Renderer.GetHeight(), h);
274  hitPt[2]=m_Camera->GetWorldCoordinates(g_Renderer.GetWidth(), 0, h);
275  hitPt[3]=m_Camera->GetWorldCoordinates(0, 0, h);
276 
277  float ViewRect[4][2];
278  const float invTileMapSize = 1.0f/float(TERRAIN_TILE_SIZE*m_MapSize);
279  for (int i=0;i<4;i++) {
280  // convert to minimap space
281  const float px=hitPt[i].X;
282  const float pz=hitPt[i].Z;
283  ViewRect[i][0]=(m_CachedActualSize.GetWidth()*px*invTileMapSize);
284  ViewRect[i][1]=(m_CachedActualSize.GetHeight()*pz*invTileMapSize);
285  }
286 
287  // Enable Scissoring as to restrict the rectangle
288  // to only the mini-map below by retrieving the mini-maps
289  // screen coords.
290  const float x = m_CachedActualSize.left, y = m_CachedActualSize.bottom;
291  glScissor((int)x, g_Renderer.GetHeight()-(int)y, (int)m_CachedActualSize.GetWidth(), (int)m_CachedActualSize.GetHeight());
292  glEnable(GL_SCISSOR_TEST);
293  glEnable(GL_LINE_SMOOTH);
294  glLineWidth(2.0f);
295  glColor3f(1.0f, 0.3f, 0.3f);
296 
297  // Draw the viewing rectangle with the ScEd's conversion algorithm
298  glBegin(GL_LINE_LOOP);
299  glVertex2f(ViewRect[0][0], -ViewRect[0][1]);
300  glVertex2f(ViewRect[1][0], -ViewRect[1][1]);
301  glVertex2f(ViewRect[2][0], -ViewRect[2][1]);
302  glVertex2f(ViewRect[3][0], -ViewRect[3][1]);
303  glEnd();
304 
305  // restore state
306  glDisable(GL_SCISSOR_TEST);
307  glDisable(GL_LINE_SMOOTH);
308  glLineWidth(1.0f);
309 }
310 
312 {
313  u8 r, g, b, a;
314  float x, y;
315 };
316 
317 // Adds a vertex to the passed VertexArray
318 static void inline addVertex(const MinimapUnitVertex& v,
319  VertexArrayIterator<u8[4]>& attrColor,
320  VertexArrayIterator<float[2]>& attrPos)
321 {
322  (*attrColor)[0] = v.r;
323  (*attrColor)[1] = v.g;
324  (*attrColor)[2] = v.b;
325  (*attrColor)[3] = v.a;
326  ++attrColor;
327 
328  (*attrPos)[0] = v.x;
329  (*attrPos)[1] = v.y;
330 
331  ++attrPos;
332 }
333 
334 
335 void CMiniMap::DrawTexture(float coordMax, float angle, float x, float y, float x2, float y2, float z)
336 {
337  // Rotate the texture coordinates (0,0)-(coordMax,coordMax) around their center point (m,m)
338  // Scale square maps to fit in circular minimap area
339  const float s = sin(angle) * m_MapScale;
340  const float c = cos(angle) * m_MapScale;
341  const float m = coordMax / 2.f;
342 
343  glBegin(GL_QUADS);
344  glTexCoord2f(m*(-c + s + 1.f), m*(-c + -s + 1.f));
345  glVertex3f(x, y, z);
346  glTexCoord2f(m*(c + s + 1.f), m*(-c + s + 1.f));
347  glVertex3f(x2, y, z);
348  glTexCoord2f(m*(c + -s + 1.f), m*(c + s + 1.f));
349  glVertex3f(x2, y2, z);
350  glTexCoord2f(m*(-c + -s + 1.f), m*(c + -s + 1.f));
351  glVertex3f(x, y2, z);
352  glEnd();
353 }
354 
355 // TODO: render the minimap in a framebuffer and just draw the frambuffer texture
356 // most of the time, updating the framebuffer twice a frame.
357 // Here it updates as ping-pong either texture or vertex array each sec to lower gpu stalling
358 // (those operations cause a gpu sync, which slows down the way gpu works)
360 {
361  PROFILE3("render minimap");
362 
363  // The terrain isn't actually initialized until the map is loaded, which
364  // happens when the game is started, so abort until then.
365  if(!(GetGUI() && g_Game && g_Game->IsGameStarted()))
366  return;
367 
369  CmpPtr<ICmpRangeManager> cmpRangeManager(*sim, SYSTEM_ENTITY);
370  ENSURE(cmpRangeManager);
371 
372  // Set our globals in case they hadn't been set before
378  m_TextureSize = (GLsizei)round_up_to_pow2((size_t)m_MapSize);
379  m_MapScale = (cmpRangeManager->GetLosCircular() ? 1.f : 1.414f);
380 
382  CreateTextures();
383 
384 
385  // only update 2x / second
386  // (note: since units only move a few pixels per second on the minimap,
387  // we can get away with infrequent updates; this is slow)
388  // TODO: store frequency in a config file?
389  static double last_time;
390  const double cur_time = timer_Time();
391  const bool doUpdate = cur_time - last_time > 0.5;
392  if(doUpdate)
393  {
394  last_time = cur_time;
395  if(m_TerrainDirty)
397  }
398 
399  glMatrixMode(GL_PROJECTION);
400  glPushMatrix();
401  glLoadIdentity();
402  glMatrixMode(GL_MODELVIEW);
403  glPushMatrix();
404  CMatrix3D matrix = GetDefaultGuiMatrix();
405  glLoadMatrixf(&matrix._11);
406 
407  // Disable depth updates to prevent apparent z-fighting-related issues
408  // with some drivers causing units to get drawn behind the texture
409  glDepthMask(0);
410 
411  CShaderProgramPtr shader;
412  CShaderTechniquePtr tech;
413 
414  if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
415  {
416  CShaderDefines defines;
417  defines.Add(str_MINIMAP_BASE, str_1);
418  tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, g_Renderer.GetSystemShaderDefines(), defines);
419  tech->BeginPass();
420  shader = tech->GetShader();
421  }
422 
423  const float x = m_CachedActualSize.left, y = m_CachedActualSize.bottom;
424  const float x2 = m_CachedActualSize.right, y2 = m_CachedActualSize.top;
425  const float z = GetBufferedZ();
426  const float texCoordMax = (float)(m_MapSize - 1) / (float)m_TextureSize;
427  const float angle = GetAngle();
428 
429  // Draw the main textured quad
430  if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
431  shader->BindTexture(str_baseTex, m_TerrainTexture);
432  else
433  g_Renderer.BindTexture(0, m_TerrainTexture);
434 
435  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
436  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
437  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
438  DrawTexture(texCoordMax, angle, x, y, x2, y2, z);
439 
440 
441  // Draw territory boundaries
442  CTerritoryTexture& territoryTexture = g_Game->GetView()->GetTerritoryTexture();
443 
444  if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
445  shader->BindTexture(str_baseTex, territoryTexture.GetTexture());
446  else
447  territoryTexture.BindTexture(0);
448 
449  glEnable(GL_BLEND);
450  glMatrixMode(GL_TEXTURE);
451  glLoadMatrixf(territoryTexture.GetMinimapTextureMatrix());
452  glMatrixMode(GL_MODELVIEW);
453 
454  DrawTexture(1.0f, angle, x, y, x2, y2, z);
455 
456  glMatrixMode(GL_TEXTURE);
457  glLoadIdentity();
458  glMatrixMode(GL_MODELVIEW);
459  glDisable(GL_BLEND);
460 
461 
462  // Draw the LOS quad in black, using alpha values from the LOS texture
463  CLOSTexture& losTexture = g_Game->GetView()->GetLOSTexture();
464 
465  if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
466  {
467  tech->EndPass();
468 
469  CShaderDefines defines;
470  defines.Add(str_MINIMAP_LOS, str_1);
471  tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, g_Renderer.GetSystemShaderDefines(), defines);
472  tech->BeginPass();
473  shader = tech->GetShader();
474  shader->BindTexture(str_baseTex, losTexture.GetTexture());
475  }
476  else
477  {
478  losTexture.BindTexture(0);
479  }
480 
481  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
482  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE);
483  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR_ARB);
484  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR);
485  glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE);
486  glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE);
487  glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_ONE_MINUS_SRC_ALPHA);
488  glEnable(GL_BLEND);
489  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
490  glColor3f(0.0f, 0.0f, 0.0f);
491 
492  glMatrixMode(GL_TEXTURE);
493  glLoadMatrixf(losTexture.GetMinimapTextureMatrix());
494  glMatrixMode(GL_MODELVIEW);
495 
496  DrawTexture(1.0f, angle, x, y, x2, y2, z);
497 
498  glMatrixMode(GL_TEXTURE);
499  glLoadIdentity();
500  glMatrixMode(GL_MODELVIEW);
501 
502  glDisable(GL_BLEND);
503 
504  if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
505  {
506  tech->EndPass();
507 
508  CShaderDefines defines;
509  defines.Add(str_MINIMAP_POINT, str_1);
510  tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, g_Renderer.GetSystemShaderDefines(), defines);
511  tech->BeginPass();
512  shader = tech->GetShader();
513  }
514 
515  // Set up the matrix for drawing points and lines
516  glPushMatrix();
517  glTranslatef(x, y, z);
518  // Rotate around the center of the map
519  glTranslatef((x2-x)/2.f, (y2-y)/2.f, 0.f);
520  // Scale square maps to fit in circular minimap area
521  float unitScale = (cmpRangeManager->GetLosCircular() ? 1.f : m_MapScale/2.f);
522  glScalef(unitScale, unitScale, 1.f);
523  glRotatef(angle * 180.f/M_PI, 0.f, 0.f, 1.f);
524  glTranslatef(-(x2-x)/2.f, -(y2-y)/2.f, 0.f);
525 
526  PROFILE_START("minimap units");
527 
528 
529  const float sx = (float)m_Width / ((m_MapSize - 1) * TERRAIN_TILE_SIZE);
530  const float sy = (float)m_Height / ((m_MapSize - 1) * TERRAIN_TILE_SIZE);
531 
533 
534  if (doUpdate)
535  {
536 
539 
540  m_EntitiesDrawn = 0;
542  std::vector<MinimapUnitVertex> pingingVertices;
543  pingingVertices.reserve(MAX_ENTITIES_DRAWN/2);
544 
545  const double time = timer_Time();
546 
547  if (time > m_NextBlinkTime)
548  {
551  }
552 
553  entity_pos_t posX, posZ;
554  for (CSimulation2::InterfaceList::const_iterator it = ents.begin(); it != ents.end(); ++it)
555  {
556  ICmpMinimap* cmpMinimap = static_cast<ICmpMinimap*>(it->second);
557  if (cmpMinimap->GetRenderData(v.r, v.g, v.b, posX, posZ))
558  {
559  ICmpRangeManager::ELosVisibility vis = cmpRangeManager->GetLosVisibility(it->first, g_Game->GetPlayerID());
560  if (vis != ICmpRangeManager::VIS_HIDDEN)
561  {
562  v.a = 255;
563  v.x = posX.ToFloat()*sx;
564  v.y = -posZ.ToFloat()*sy;
565 
566  // Check minimap pinging to indicate something
567  if (m_BlinkState && cmpMinimap->CheckPing(time, m_PingDuration))
568  {
569  v.r = 255; // ping color is white
570  v.g = 255;
571  v.b = 255;
572 
573  pingingVertices.push_back(v);
574  }
575  else
576  {
577  addVertex(v, attrColor, attrPos);
578  ++m_EntitiesDrawn;
579  }
580  }
581  }
582  }
583 
584  // Add the pinged vertices at the end, so they are drawn on top
585  for (size_t v = 0; v < pingingVertices.size(); ++v)
586  {
587  addVertex(pingingVertices[v], attrColor, attrPos);
588  ++m_EntitiesDrawn;
589  }
590 
591  ENSURE(m_EntitiesDrawn < MAX_ENTITIES_DRAWN);
593  }
594 
595  if (m_EntitiesDrawn > 0)
596  {
597  // Don't enable GL_POINT_SMOOTH because it's far too slow
598  // (~70msec/frame on a GF4 rendering a thousand points)
599  glPointSize(3.f);
600 
601  u8* indexBase = m_IndexArray.Bind();
602  u8* base = m_VertexArray.Bind();
603  const GLsizei stride = (GLsizei)m_VertexArray.GetStride();
604 
605  if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
606  {
607  shader->VertexPointer(2, GL_FLOAT, stride, base + m_AttributePos.offset);
608  shader->ColorPointer(4, GL_UNSIGNED_BYTE, stride, base + m_AttributeColor.offset);
609  shader->AssertPointersBound();
610  }
611  else
612  {
613  glEnableClientState(GL_VERTEX_ARRAY);
614  glEnableClientState(GL_COLOR_ARRAY);
615 
616  glDisable(GL_TEXTURE_2D);
617  glVertexPointer(2, GL_FLOAT, stride, base + m_AttributePos.offset);
618  glColorPointer(4, GL_UNSIGNED_BYTE, stride, base + m_AttributeColor.offset);
619  }
620 
621  if (!g_Renderer.m_SkipSubmit)
622  {
623  glDrawElements(GL_POINTS, (GLsizei)(m_EntitiesDrawn), GL_UNSIGNED_SHORT, indexBase);
624  }
625 
626 
627  g_Renderer.GetStats().m_DrawCalls++;
629  }
630 
631  PROFILE_END("minimap units");
632 
633  if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
634  {
635  tech->EndPass();
636 
637  CShaderDefines defines;
638  defines.Add(str_MINIMAP_LINE, str_1);
639  tech = g_Renderer.GetShaderManager().LoadEffect(str_minimap, g_Renderer.GetSystemShaderDefines(), defines);
640  tech->BeginPass();
641  shader = tech->GetShader();
642  }
643  else
644  {
645  glEnable(GL_TEXTURE_2D);
646  glDisableClientState(GL_VERTEX_ARRAY);
647  glDisableClientState(GL_COLOR_ARRAY);
648  }
649 
650  DrawViewRect();
651 
652  glPopMatrix();
653 
654  glMatrixMode(GL_PROJECTION);
655  glPopMatrix();
656  glMatrixMode(GL_MODELVIEW);
657  glPopMatrix();
658 
659  if (g_Renderer.GetRenderPath() == CRenderer::RP_SHADER)
660  {
661  tech->EndPass();
662  }
663 
664  // Reset everything back to normal
665  glPointSize(1.0f);
666  glEnable(GL_TEXTURE_2D);
667  glDepthMask(1);
668 }
669 
670 #endif // CONFIG2_GLES
671 
673 {
674  Destroy();
675 
676  // Create terrain texture
677  glGenTextures(1, &m_TerrainTexture);
678  g_Renderer.BindTexture(0, m_TerrainTexture);
679 
680  // Initialise texture with solid black, for the areas we don't
681  // overwrite with glTexSubImage2D later
682  u32* texData = new u32[m_TextureSize * m_TextureSize];
683  for (ssize_t i = 0; i < m_TextureSize * m_TextureSize; ++i)
684  texData[i] = 0xFF000000;
685  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_TextureSize, m_TextureSize, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, texData);
686  delete[] texData;
687 
688  m_TerrainData = new u32[(m_MapSize - 1) * (m_MapSize - 1)];
689  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
690  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
691  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
692  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
693 
694  // Rebuild and upload both of them
696 }
697 
698 
700 {
701  u32 x = 0;
702  u32 y = 0;
703  u32 w = m_MapSize - 1;
704  u32 h = m_MapSize - 1;
705  float waterHeight = g_Renderer.GetWaterManager()->m_WaterHeight;
706 
707  m_TerrainDirty = false;
708 
709  for(u32 j = 0; j < h; j++)
710  {
711  u32 *dataPtr = m_TerrainData + ((y + j) * (m_MapSize - 1)) + x;
712  for(u32 i = 0; i < w; i++)
713  {
714  float avgHeight = ( m_Terrain->GetVertexGroundLevel((int)i, (int)j)
715  + m_Terrain->GetVertexGroundLevel((int)i+1, (int)j)
716  + m_Terrain->GetVertexGroundLevel((int)i, (int)j+1)
717  + m_Terrain->GetVertexGroundLevel((int)i+1, (int)j+1)
718  ) / 4.0f;
719 
720  if(avgHeight < waterHeight && avgHeight > waterHeight - m_ShallowPassageHeight)
721  {
722  // shallow water
723  *dataPtr++ = 0xff7098c0;
724  } else if (avgHeight < waterHeight)
725  {
726  // Set water as constant color for consistency on different maps
727  *dataPtr++ = 0xff5078a0;
728  }
729  else
730  {
731  int hmap = ((int)m_Terrain->GetHeightMap()[(y + j) * m_MapSize + x + i]) >> 8;
732  int val = (hmap / 3) + 170;
733 
734  u32 color = 0xFFFFFFFF;
735 
736  CMiniPatch *mp = m_Terrain->GetTile(x + i, y + j);
737  if(mp)
738  {
740  if(tex)
741  {
742  // If the texture can't be loaded yet, set the dirty flags
743  // so we'll try regenerating the terrain texture again soon
744  if(!tex->GetTexture()->TryLoad())
745  m_TerrainDirty = true;
746 
747  color = tex->GetBaseColor();
748  }
749  }
750 
751  *dataPtr++ = ScaleColor(color, float(val) / 255.0f);
752  }
753  }
754  }
755 
756  // Upload the texture
757  g_Renderer.BindTexture(0, m_TerrainTexture);
758  glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_MapSize - 1, m_MapSize - 1, GL_BGRA_EXT, GL_UNSIGNED_BYTE, m_TerrainData);
759 }
760 
762 {
763  if(m_TerrainTexture)
764  {
765  glDeleteTextures(1, &m_TerrainTexture);
766  m_TerrainTexture = 0;
767  }
768 
769  delete[] m_TerrainData;
770  m_TerrainData = 0;
771 }
#define M_PI
Definition: wposix.h:64
GLuint m_TerrainTexture
Definition: MiniMap.h:64
An entity initialisation parameter node.
Definition: ParamNode.h:112
const u16 MAX_ENTITIES_DRAWN
Definition: MiniMap.cpp:50
void Add(CStrIntern name, CStrIntern value)
Add a name and associated value to the map of defines.
#define u8
Definition: types.h:39
A simple fixed-point number class.
Definition: Fixed.h:115
CTerrainTextureEntry * GetTextureEntry()
Definition: MiniPatch.h:42
CMatrix3D GetDefaultGuiMatrix()
Definition: GUIutil.cpp:253
virtual ~CMiniMap()
Definition: MiniMap.cpp:131
const ssize_t TERRAIN_TILE_SIZE
metres [world space units] per tile in x and z
Definition: Terrain.h:40
float GetAngle()
Definition: MiniMap.cpp:232
float top
Definition: Overlay.h:159
void ScriptEvent(const CStr &Action)
Execute the script for a particular action.
Definition: IGUIObject.cpp:480
void Destroy()
Calls Destroy on all children, and deallocates all memory.
Definition: MiniMap.cpp:761
bool IsOk() const
Returns true if this is a valid CParamNode, false if it represents a non-existent node...
Definition: ParamNode.cpp:193
VertexArrayIterator< u16 > GetIterator() const
Gets the iterator over the (only) attribute in this array, i.e. a u16.
float left
Returning CPos representing each corner.
Definition: Overlay.h:159
#define CFG_GET_VAL(name, type, destination)
Definition: ConfigDB.h:147
void RebuildTerrainTexture()
Definition: MiniMap.cpp:699
const CTerrain * m_Terrain
Definition: MiniMap.h:56
ssize_t GetVerticesPerSide() const
Definition: Terrain.h:65
void AddAttribute(Attribute *attr)
Definition: VertexArray.cpp:75
shared_ptr< CShaderTechnique > CShaderTechniquePtr
bool m_Clicking
Definition: MiniMap.h:61
const float * GetMinimapTextureMatrix()
Returns a matrix to map (0,0)-(1,1) texture coordinates onto texture coordinates, in the form expecte...
float GetExactGroundLevel(float x, float z) const
Definition: Terrain.cpp:353
VertexArray::Attribute m_AttributePos
Definition: MiniMap.h:96
CVector3D GetWorldCoordinates(int px, int py, bool aboveWater=false) const
Definition: Camera.cpp:204
void FreeBackingStore()
void BindTexture(int unit)
Recomputes the territory texture if necessary, and binds it to the requested texture unit...
#define PROFILE_END(name)
Definition: Profile.h:198
virtual void HandleMessage(SGUIMessage &Message)
Definition: MiniMap.cpp:136
float _11
Definition: Matrix3D.h:42
virtual bool CheckPing(double currentTime, double pingDuration)=0
Return true if entity is actively pinging based on the current time.
virtual bool GetLosCircular()=0
Returns whether the LOS is restricted to a circular map.
ssize_t m_Height
Definition: MiniMap.h:72
const entity_id_t SYSTEM_ENTITY
Entity ID for singleton &#39;system&#39; components.
Definition: Entity.h:44
virtual ELosVisibility GetLosVisibility(CEntityHandle ent, player_id_t player, bool forceRetainInFog=false)=0
Returns the visibility status of the given entity, with respect to the given player.
Public API for simulation system.
Definition: Simulation2.h:46
virtual float GetBufferedZ() const
Returns not the Z value, but the actual buffered Z value, i.e.
Definition: IGUIObject.cpp:406
virtual bool GetRenderData(u8 &r, u8 &g, u8 &b, entity_pos_t &x, entity_pos_t &z)=0
Get the data for rendering this entity on the minimap.
u32 * m_TerrainData
Definition: MiniMap.h:67
#define g_Renderer
Definition: Renderer.h:61
float GetWidth() const
Definition: Overlay.cpp:232
int GetPlayerID()
Definition: Game.cpp:249
CTerrain * GetTerrain()
Get the pointer to the terrain object.
Definition: World.h:88
static void LoadXML(CParamNode &ret, const XMBFile &file, const wchar_t *sourceIdentifier=NULL)
Loads the XML data specified by file into the node ret.
Definition: ParamNode.cpp:47
CVector3D GetIn() const
Definition: Matrix3D.cpp:253
CMiniMap()
Definition: MiniMap.cpp:60
std::vector< std::pair< entity_id_t, IComponent * > > InterfaceList
Definition: Simulation2.h:196
float m_ShallowPassageHeight
Definition: MiniMap.h:84
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
#define UNUSED2(param)
mark a function local variable or parameter as unused and avoid the corresponding compiler warning...
T round_up_to_pow2(T x)
round up to next larger power of two.
Definition: bits.h:244
#define g_ScriptingHost
const CParamNode & GetChild(const char *name) const
Returns the (unique) child node with the given name, or a node with IsOk() == false if there is none...
Definition: ParamNode.cpp:185
VertexArray::Attribute m_AttributeColor
Definition: MiniMap.h:97
float X
Definition: Vector3D.h:31
const float HEIGHT_SCALE
metres per u16 height unit
Definition: Terrain.h:46
float ToFloat() const
Parses the content of this node as a floating-point number.
Definition: ParamNode.cpp:227
float Y
Definition: Vector3D.h:31
double m_PingDuration
Definition: MiniMap.h:101
bool m_TerrainDirty
Definition: MiniMap.h:70
CMiniPatch * GetTile(ssize_t i, ssize_t j) const
Definition: Terrain.cpp:298
float ToFloat() const
Convert to float. May be lossy - float can&#39;t represent all values.
Definition: Fixed.h:161
void GetMouseWorldCoordinates(float &x, float &z)
Definition: MiniMap.cpp:206
GLsizei m_TextureSize
Definition: MiniMap.h:78
static unsigned int ScaleColor(unsigned int color, float x)
Definition: MiniMap.cpp:52
void DrawTexture(float coordMax, float angle, float x, float y, float x2, float y2, float z)
Definition: MiniMap.cpp:335
const CTexturePtr & GetTexture()
GLuint GetTexture()
Recomputes the LOS texture if necessary, and returns the texture handle.
Definition: LOSTexture.cpp:173
GLuint GetTexture()
Recomputes the territory texture if necessary, and returns the texture handle.
void SetNumVertices(size_t num)
Definition: VertexArray.cpp:64
CCamera * GetCamera()
Definition: GameView.cpp:390
void AddSetting(const EGUISettingType &Type, const CStr &Name)
Add a setting to m_Settings.
Definition: IGUIObject.cpp:172
bool g_GameRestarted
Definition: MiniMap.cpp:46
#define PROFILE_START(name)
Definition: Profile.h:197
CGame * g_Game
Globally accessible pointer to the CGame object.
Definition: Game.cpp:56
ssize_t m_MapSize
Definition: MiniMap.h:75
static bool IsInitialised()
Definition: Singleton.h:63
double timer_Time()
Definition: timer.cpp:98
virtual CTerritoryTexture & GetTerritoryTexture()
Return the territory texture to be used for rendering this scene.
Definition: GameView.cpp:405
double m_NextBlinkTime
Definition: MiniMap.h:103
void Skip(bool skip=true)
This method can be used to allow other event handlers to process this GUI event, by default an event ...
Definition: GUIbase.h:117
A simplified syntax for accessing entity components.
Definition: CmpPtr.h:55
VertexArrayIterator< T > GetIterator() const
CRect m_CachedActualSize
Cached size, real size m_Size is actually dependent on resolution and can have different real outcome...
Definition: IGUIObject.h:434
VertexIndexArray m_IndexArray
Definition: MiniMap.h:94
Made to represent screen positions and delta values.
Definition: Overlay.h:167
CSimulation2 * GetSimulation2()
Get the pointer to the simulation2 object.
Definition: Game.h:136
intptr_t ssize_t
Definition: wposix_types.h:82
float m_MapScale
Definition: MiniMap.h:81
Represents a mapping of name strings to value strings, for use with #if and #ifdef and similar condit...
#define u16
Definition: types.h:40
void FireWorldClickEvent(int button, int clicks)
Definition: MiniMap.cpp:238
CGameView * GetView()
Get the pointer to the game view object.
Definition: Game.h:128
const float * GetMinimapTextureMatrix()
Returns a matrix to map (0,0)-(1,1) texture coordinates onto LOS texture coordinates, in the form expected by glLoadMatrixf.
Definition: LOSTexture.cpp:190
Per-unit minimap data.
Definition: ICmpMinimap.h:28
float right
Definition: Overlay.h:159
#define PROFILE3(name)
Definition: Profile.h:201
#define u32
Definition: types.h:41
CPos GetMousePos() const
Get Mouse from CGUI.
Definition: IGUIObject.cpp:207
virtual CLOSTexture & GetLOSTexture()
Return the LOS texture to be used for rendering this scene.
Definition: GameView.cpp:400
InterfaceList GetEntitiesWithInterface(int iid)
Returns a list of components implementing the given interface, and their associated entities...
CGUI * GetGUI()
Definition: IGUIObject.h:388
float GetVertexGroundLevel(ssize_t i, ssize_t j) const
Definition: Terrain.cpp:308
bool IsGameStarted() const
Get m_GameStarted.
Definition: Game.h:110
void DrawViewRect()
Definition: MiniMap.cpp:263
void CreateTextures()
Definition: MiniMap.cpp:672
ssize_t m_Width
Definition: MiniMap.h:72
void BindTexture(int unit)
Recomputes the LOS texture if necessary, and binds it to the requested texture unit.
Definition: LOSTexture.cpp:95
CMatrix3D m_Orientation
Definition: Camera.h:112
float y
Definition: Overlay.h:195
jsval get() const
Returns the current value (or JSVAL_VOID if uninitialised).
Definition: ScriptVal.cpp:45
CWorld * GetWorld()
Get the pointer to the game world object.
Definition: Game.h:120
float GetHeight() const
Definition: Overlay.cpp:237
float Z
Definition: Vector3D.h:31
Maintains the LOS (fog-of-war / shroud-of-darkness) texture, used for rendering and for the minimap...
Definition: LOSTexture.h:32
bool m_MouseHovering
This is an array of true or false, each element is associated with a string representing a setting...
Definition: IGUIObject.h:539
static void Unbind()
Unbind any currently-bound buffer, so glVertexPointer etc calls will not attempt to use it...
u16 * GetHeightMap() const
Definition: Terrain.h:103
VertexArray m_VertexArray
Definition: MiniMap.h:95
Message send to IGUIObject::HandleMessage() in order to give life to Objects manually with a derived ...
Definition: GUIbase.h:106
EGUIMessageType type
Describes what the message regards.
Definition: GUIbase.h:122
float bottom
Definition: Overlay.h:159
bool m_BlinkState
Definition: MiniMap.h:104
float x
Position.
Definition: Overlay.h:195
void MoveCameraTarget(const CVector3D &target)
Definition: GameView.cpp:966
shared_ptr< CShaderProgram > CShaderProgramPtr
void SetCameraPos()
Definition: MiniMap.cpp:222
size_t GetStride() const
Definition: VertexArray.h:169
Maintains the territory boundary texture, used for rendering and for the minimap. ...
size_t m_EntitiesDrawn
Definition: MiniMap.h:99
const CCamera * m_Camera
Definition: MiniMap.h:58
virtual void Draw()
Draws the object.
Definition: MiniMap.cpp:359
static void addVertex(const MinimapUnitVertex &v, VertexArrayIterator< u8[4]> &attrColor, VertexArrayIterator< float[2]> &attrPos)
Definition: MiniMap.cpp:318
double m_HalfBlinkDuration
Definition: MiniMap.h:102