Symphony Of Empires
map_render.cpp
Go to the documentation of this file.
1 // Symphony of Empires
2 // Copyright (C) 2021, Symphony of Empires contributors
3 //
4 // This program 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 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
16 //
17 // ----------------------------------------------------------------------------
18 // Name:
19 // client/map_render.cpp
20 //
21 // Abstract:
22 // Does some important stuff.
23 // ----------------------------------------------------------------------------
24 
25 #include <algorithm>
26 #include <cstdlib>
27 #include <cstring>
28 #include <functional>
29 #include <iostream>
30 #include <mutex>
31 #include <memory>
32 #include <chrono>
33 #include <ctime>
34 #include <glm/gtc/matrix_transform.hpp>
35 #include <tbb/blocked_range.h>
36 #include <tbb/concurrent_vector.h>
37 #include <tbb/parallel_for.h>
38 #include <tbb/combinable.h>
39 
40 #ifdef E3D_BACKEND_OPENGL
41 # include <GL/glew.h>
42 # include <GL/gl.h>
43 #elif defined E3D_BACKEND_GLES
44 # include <GLES3/gl3.h>
45 #endif
46 
47 #include "eng3d/texture.hpp"
48 #include "eng3d/primitive.hpp"
49 #include "eng3d/shader.hpp"
50 #include "eng3d/framebuffer.hpp"
51 #include "eng3d/state.hpp"
52 #include "eng3d/utils.hpp"
53 #include "eng3d/log.hpp"
54 #include "eng3d/orbit_camera.hpp"
55 #include "eng3d/flat_camera.hpp"
56 #include "eng3d/camera.hpp"
57 
58 #include "game_state.hpp"
59 #include "map.hpp"
60 #include "world.hpp"
61 #include "province.hpp"
62 #include "client/map_render.hpp"
63 #include "client/map.hpp"
64 
66  : Eng3D::BaseMap(_gs, glm::ivec2{ _gs.world->width, _gs.world->height }),
67  gs{ _gs },
68  map{ _map }
69 {
70  if(this->gs.world->width != this->terrain_map->width || this->gs.world->height != this->terrain_map->height)
71  CXX_THROW(std::runtime_error, "Color map differs from province map!");
72 
73  // The terrain_map has 16 bits available for usage, so naturally we use them
74  // ------------------------------------------------------------
75  // | 16 bit Province id | 8 bit terrain index | 8 bit "flags" |
76  // ------------------------------------------------------------
77  Eng3D::Log::debug("game", "Creating tile map & tile sheet");
78  assert((this->terrain_map->width* this->terrain_map->height) % 5400 == 0);
79 
80  tbb::parallel_for(static_cast<size_t>(0), (this->terrain_map->width* this->terrain_map->height) / 5400, [this](const auto y) {
81  const auto i = y * 5400;
82  for(size_t x = 0; x < 5400; x++)
83  this->terrain_map->buffer.get()[i + x] |= static_cast<size_t>(this->gs.world->tiles[i + x]) & 0xffff;
84  });
85 
86  Eng3D::TextureOptions terrain_map_options{};
87  terrain_map_options.internal_format = Eng3D::TextureOptions::Format::RGBA;
88  terrain_map_options.editable = true;
89  terrain_map_options.compressed = false;
90  this->terrain_map->upload(terrain_map_options);
91  // After this snippet of code we won't ever need tiles ever again
92  this->gs.world->tiles.reset();
93 
94  // Texture holding each province color
95  // The x & y coords are the province Red & Green color of the tile_map
96  tile_sheet = std::make_unique<Eng3D::Texture>(256, 256);
97  std::fill_n(tile_sheet->buffer.get(), 256 * 256, 0xffdddddd);
98  tile_sheet_nation = std::make_unique<Eng3D::Texture>(256, 256);
99  std::fill_n(tile_sheet_nation->buffer.get(), 256 * 256, 0xffdddddd);
100 
101  // By default textures will be dropped from the CPU in order to save memory, however we're trying
102  // to make a buffer-texture so we have to keep it or we will have trouble
103  {
104  Eng3D::TextureOptions no_drop_options{};
105  no_drop_options.editable = true;
106 #ifdef E3D_BACKEND_OPENGL
107  no_drop_options.internal_format = Eng3D::TextureOptions::Format::SRGB_ALPHA;
108 #elif defined E3D_BACKEND_GLES
109  no_drop_options.internal_format = Eng3D::TextureOptions::Format::RGBA;
110 #endif
111  no_drop_options.compressed = false;
112  tile_sheet->upload(no_drop_options);
113  }
114 
115  // Province options
116  province_opt = std::make_unique<Eng3D::Texture>(256, 256);
117  for(size_t i = 0; i < 256 * 256; i++)
118  province_opt->buffer.get()[i] = 0x000000ff;
119  {
120  Eng3D::TextureOptions no_drop_options{};
121  no_drop_options.editable = true;
122  province_opt->upload(no_drop_options);
123  }
124 
125  std::vector<ProvinceId> province_ids;
126  province_ids.reserve(this->gs.world->provinces.size());
127  for(auto const& province : this->gs.world->provinces)
128  province_ids.push_back(province);
129  this->update_nations(province_ids);
130 }
131 
133  border_gen_shader = std::make_unique<Eng3D::OpenGL::Program>();
134  {
135  auto vs_shader = Eng3D::OpenGL::VertexShader(gs.package_man.get_unique("shaders/2d_scale.vs")->read_all());
136  border_gen_shader->attach_shader(vs_shader);
137  auto fs_shader = Eng3D::OpenGL::FragmentShader(gs.package_man.get_unique("shaders/border_gen.fs")->read_all());
138  border_gen_shader->attach_shader(fs_shader);
139  border_gen_shader->attach_shader(*gs.builtin_shaders["fs_lib"].get());
140  border_gen_shader->link();
141  }
142 
143  sdf_shader = std::make_unique<Eng3D::OpenGL::Program>();
144  {
145  auto vs_shader = Eng3D::OpenGL::VertexShader(gs.package_man.get_unique("shaders/2d_scale.vs")->read_all());
146  sdf_shader->attach_shader(vs_shader);
147  auto fs_shader = Eng3D::OpenGL::FragmentShader(gs.package_man.get_unique("shaders/border_sdf.fs")->read_all());
148  sdf_shader->attach_shader(fs_shader);
149  sdf_shader->attach_shader(*gs.builtin_shaders["fs_lib"].get());
150  sdf_shader->link();
151  }
152 
153  output_shader = std::make_unique<Eng3D::OpenGL::Program>();
154  {
155  output_shader->attach_shader(*gs.builtin_shaders["vs_2d"].get());
156  auto fs_shader = Eng3D::OpenGL::FragmentShader(gs.package_man.get_unique("shaders/border_sdf_output.fs")->read_all());
157  output_shader->attach_shader(fs_shader);
158  output_shader->attach_shader(*gs.builtin_shaders["fs_lib"].get());
159  output_shader->link();
160  }
161  this->update_options(this->options);
162 }
163 
165  map_shader = std::make_unique<Eng3D::OpenGL::Program>();
166  {
167  std::vector<Eng3D::GLSL::Define> defined_options;
168  for(auto& option : options.get_options()) {
169  if(option.used) {
170  Eng3D::GLSL::Define defined_option;
171  defined_option.name = option.get_option();
172  defined_options.push_back(defined_option);
173  }
174  }
175  auto vs_shader = Eng3D::OpenGL::VertexShader(gs.package_man.get_unique("shaders/map.vs")->read_all());
176  map_shader->attach_shader(vs_shader);
177  auto fs_shader = Eng3D::OpenGL::FragmentShader(gs.package_man.get_unique("shaders/map.fs")->read_all(), true, defined_options);
178  map_shader->attach_shader(fs_shader);
179  map_shader->attach_shader(*gs.builtin_shaders["fs_lib"]);
180  map_shader->link();
181  }
182 
183  if(this->options.rivers.used) {
184  Eng3D::TextureOptions mipmap_options{};
185  mipmap_options.wrap_s = Eng3D::TextureOptions::Wrap::REPEAT;
186  mipmap_options.wrap_t = Eng3D::TextureOptions::Wrap::REPEAT;
187  mipmap_options.min_filter = Eng3D::TextureOptions::Filter::LINEAR_MIPMAP;
188  mipmap_options.mag_filter = Eng3D::TextureOptions::Filter::LINEAR;
189  mipmap_options.compressed = this->options.compress.used;
190  mipmap_options.internal_format = Eng3D::TextureOptions::Format::RED;
191  if(this->bathymethry.get() == nullptr)
192  this->bathymethry = gs.tex_man.load(gs.package_man.get_unique("map/bathymethry.png"), mipmap_options);
193  if(this->river_tex.get() == nullptr)
194  this->river_tex = gs.tex_man.load(gs.package_man.get_unique("map/river_smooth.png"), mipmap_options);
195  } else {
196  this->bathymethry.reset(new Eng3D::Texture(1, 1));
197  this->river_tex.reset(new Eng3D::Texture(1, 1));
198  }
199 
200  // Load normal and topographic maps only w lighting
201  if(this->options.lighting.used) {
202  // If reload is required
203  if(this->normal_topo.get() == nullptr) {
204  auto topo_map = std::make_unique<Eng3D::Texture>(gs.package_man.get_unique("map/topo.png")->get_abs_path());
205  this->normal_topo = std::make_unique<Eng3D::Texture>(gs.package_man.get_unique("map/normal.png")->get_abs_path());
206  size_t map_size = topo_map->width * topo_map->height;
207  for(size_t i = 0; i < map_size; i++) {
208  this->normal_topo->buffer.get()[i] &= (0x00FFFFFF);
209  this->normal_topo->buffer.get()[i] |= (topo_map->buffer.get()[i] & 0xFF) << 24;
210  }
211  Eng3D::TextureOptions mipmap_options{};
212  mipmap_options.internal_format = Eng3D::TextureOptions::Format::RGBA;
213  mipmap_options.min_filter = Eng3D::TextureOptions::Filter::LINEAR_MIPMAP;
214  mipmap_options.mag_filter = Eng3D::TextureOptions::Filter::LINEAR;
215  mipmap_options.compressed = this->options.compress.used;
216  this->normal_topo->upload(mipmap_options);
217  }
218  }
219 
220  // Only perform the updates/generation on the SDF map when SDF is actually used
221  if(this->options.sdf.used) {
222  // If reload is required
223  if(this->border_sdf.get() == nullptr) {
224  Eng3D::Log::debug("game", "Creating border textures");
225  std::unique_ptr<FILE, int(*)(FILE*)> fp(::fopen("sdf_cache.png", "rb"), ::fclose);
226  if(fp.get() == nullptr) {
227  this->update_border_sdf(Eng3D::Rect(0, 0, this->gs.world->width, this->gs.world->height), glm::vec2(gs.width, gs.height));
228  this->border_sdf->to_file("sdf_cache.png");
229  } else {
230  Eng3D::TextureOptions sdf_options{};
231  sdf_options.wrap_s = Eng3D::TextureOptions::Wrap::REPEAT;
232  sdf_options.wrap_t = Eng3D::TextureOptions::Wrap::REPEAT;
233  sdf_options.internal_format = Eng3D::TextureOptions::Format::RGB32F;
234  sdf_options.min_filter = Eng3D::TextureOptions::Filter::LINEAR_MIPMAP;
235  sdf_options.mag_filter = Eng3D::TextureOptions::Filter::LINEAR;
236  sdf_options.compressed = this->options.compress.used;
237  this->border_sdf = std::make_unique<Eng3D::Texture>("sdf_cache.png");
238  this->border_sdf->upload(sdf_options);
239  }
240  // We are already updating the whole map, don't do it twice
241  this->gs.world->province_manager.clear();
242  }
243  }
244 }
245 
246 #include "eng3d/framebuffer.hpp"
247 
251 void MapRender::update_border_sdf(Eng3D::Rect update_area, glm::ivec2 window_size) {
252  glEnable(GL_SCISSOR_TEST);
253  glViewport(update_area.left, update_area.top, update_area.width(), update_area.height());
254  glScissor(update_area.left, update_area.top, update_area.width(), update_area.height());
255 
256  float width = this->gs.world->width;
257  float height = this->gs.world->height;
258 
259  Eng3D::TextureOptions border_tex_options{};
260  border_tex_options.internal_format = Eng3D::TextureOptions::Format::RGB32F;
261  border_tex_options.min_filter = Eng3D::TextureOptions::Filter::LINEAR_MIPMAP;
262  border_tex_options.mag_filter = Eng3D::TextureOptions::Filter::LINEAR;
263  border_tex_options.editable = true;
264  Eng3D::Texture border_tex(width, height);
265  border_tex.upload(border_tex_options);
266  border_tex.gen_mipmaps();
267 
268  auto tex_coord_scale = update_area;
269  tex_coord_scale.scale(1.f / glm::vec2(width, height));
270 
271  Eng3D::Log::debug("game", "Creating border framebuffer");
272  Eng3D::OpenGL::Framebuffer border_fbuffer{};
273  border_fbuffer.use();
274  border_fbuffer.set_texture(0, border_tex);
275 
276  Eng3D::Log::debug("game", "Drawing border with border shader");
277  border_gen_shader->use();
278  border_gen_shader->set_uniform("map_size", width, height);
279  border_gen_shader->set_uniform("tex_coord_scale", tex_coord_scale.left, tex_coord_scale.top, tex_coord_scale.right, tex_coord_scale.bottom);
280  border_gen_shader->set_texture(0, "terrain_map", *terrain_map);
281  border_gen_shader->set_texture(1, "tile_sheet_nation", *tile_sheet_nation);
282  map_2d_quad.draw();
283 
284  glBindFramebuffer(GL_FRAMEBUFFER, 0);
285  border_tex.gen_mipmaps();
286 
287  sdf_shader->use();
288  sdf_shader->set_uniform("map_size", width, height);
289  sdf_shader->set_uniform("tex_coord_scale", tex_coord_scale.left, tex_coord_scale.top, tex_coord_scale.right, tex_coord_scale.bottom);
290 
291  Eng3D::TextureOptions fbo_mipmap_options{};
292  fbo_mipmap_options.internal_format = Eng3D::TextureOptions::Format::RGB32F;
293  fbo_mipmap_options.min_filter = Eng3D::TextureOptions::Filter::LINEAR_MIPMAP;
294  fbo_mipmap_options.mag_filter = Eng3D::TextureOptions::Filter::LINEAR;
295  fbo_mipmap_options.editable = true;
296  // The Red & Green color channels are the coords on the map
297  // The Blue is the distance to a border
298  if(border_sdf.get() == nullptr) {
299  border_sdf = std::make_unique<Eng3D::Texture>(border_tex.width, border_tex.height);
300  border_sdf->upload(fbo_mipmap_options);
301  }
302 
303  auto swap_tex = std::make_unique<Eng3D::Texture>(width, height);
304  swap_tex->upload(fbo_mipmap_options);
305 
307  fbo.use();
308 
309  // Jump flooding iterations, each step give a distance field 2^steps pixels away from the border
310  const float max_steps = 7.f;
311  const float max_dist = std::pow(2, max_steps);
312  sdf_shader->set_uniform("max_dist", max_dist);
313 
314  bool draw_on_tex0 = true;
315  for(int step = max_dist; step >= 1; step /= 2) {
316  // Swap read/write buffers
317  draw_on_tex0 = !draw_on_tex0;
318  border_sdf->gen_mipmaps();
319  swap_tex->gen_mipmaps();
320  sdf_shader->set_uniform("jump", (float)step);
321 
322  fbo.set_texture(0, draw_on_tex0 ? *border_sdf : *swap_tex);
323  if(step == max_dist) sdf_shader->set_texture(0, "tex", border_tex);
324  else sdf_shader->set_texture(0, "tex", draw_on_tex0 ? *swap_tex : *border_sdf);
325  // Draw a plane over the entire screen to invoke shaders
326  map_2d_quad.draw();
327  }
328 
329  // Delete the textures no used from memory
330  if(draw_on_tex0) {
331  swap_tex.reset();
332  } else {
333  border_sdf.reset();
334  border_sdf = std::move(swap_tex);
335  }
336  border_sdf->gen_mipmaps();
337  glDisable(GL_SCISSOR_TEST);
338  glViewport(0, 0, window_size.x, window_size.y);
339 }
340 
341 // Updates the province color texture with the changed provinces
342 void MapRender::update_mapmode(std::vector<ProvinceColor>& province_colors) {
343  // Water
344  for(size_t i = 0; i < this->gs.world->provinces.size(); i++)
345  if(this->gs.world->terrain_types[this->gs.world->provinces[i].terrain_type_id].is_water_body)
346  province_colors[i] = ProvinceColor(ProvinceId(i), Eng3D::Color{});
347 
348  for(const auto province_color : province_colors)
349  tile_sheet->buffer.get()[static_cast<size_t>(province_color.id)] = province_color.color.get_value();
350  Eng3D::TextureOptions no_drop_options{};
351  no_drop_options.editable = true;
352  no_drop_options.internal_format = Eng3D::TextureOptions::Format::SRGB;
353  this->tile_sheet->upload(no_drop_options);
354 }
355 
356 // Updates nations
357 void MapRender::update_nations(std::vector<ProvinceId>& province_ids) {
358  std::vector<NationId> nation_ids;
359  for(const auto province_id : province_ids) {
360  const auto& province = this->gs.world->provinces[province_id];
361  this->tile_sheet_nation->buffer.get()[province] = static_cast<size_t>(province.controller_id);
362  nation_ids.push_back(province.controller_id);
363  }
364  std::sort(nation_ids.begin(), nation_ids.end());
365  auto last = std::unique(nation_ids.begin(), nation_ids.end());
366  nation_ids.erase(last, nation_ids.end());
367 
368  Eng3D::TextureOptions no_drop_options{};
369  no_drop_options.editable = true;
370  this->tile_sheet_nation->upload(no_drop_options);
371 
372  // Update labels of the nations
373  for(const auto nation_id : nation_ids)
374  this->map.update_nation_label(this->gs.world->nations[nation_id]);
375 }
376 
377 void MapRender::update_city_lights() {
378 
379 }
380 
382  this->req_update_vision = true;
383 }
384 
385 void MapRender::update_visibility() {
386  // Fill out information for visability
387  if(gs.curr_nation == nullptr || gs.curr_nation == &gs.world->nations[0]) {
388  std::fill_n(province_opt->buffer.get(), gs.world->provinces.size(), 0x000000ff);
389  return;
390  }
391  std::fill_n(province_opt->buffer.get(), gs.world->provinces.size(), 0x00000080);
392 
393  // Fill out density information for city lights
394  for(const auto& province : gs.world->provinces) {
395  const auto total = glm::max(province.total_pops(), 0.1f);
396  const auto density = glm::clamp(total / 100'000.f, 0.f, 1.f) * 255.f;
397  this->province_opt->buffer[province] |= (static_cast<uint8_t>(density) & 0xff) << 8;
398  }
399 
400  for(const auto& nation : gs.world->nations) {
401  const auto nation_id = nation;
402  // If it's our own nation or an ally of ours we can see them
403  if(nation_id == gs.curr_nation->get_id() || gs.world->get_relation(nation_id, gs.curr_nation->get_id()).is_allied()) {
404  for(const auto province_id : gs.world->nations[nation_id].controlled_provinces) {
405  const auto& province = gs.world->provinces[province_id];
406  this->province_opt->buffer[province_id] |= 0x000000ff;
407  for(const auto neighbour_id : province.neighbour_ids)
408  this->province_opt->buffer[neighbour_id] |= 0x000000ff;
409  }
410  }
411  }
412  gs.world->unit_manager.units.for_each([this](Unit& unit) {
413  auto &_gs = this->gs;
414  // Unit must be ours or be owned by our ally
415  if(unit.owner_id != _gs.curr_nation->get_id() && !_gs.world->get_relation(unit.owner_id, _gs.curr_nation->get_id()).is_allied())
416  return;
417  auto prov_id = _gs.world->unit_manager.get_unit_current_province(unit.cached_id);
418  this->province_opt->buffer[prov_id] |= 0x000000ff;
419  for(const auto neighbour_id : _gs.world->provinces[prov_id].neighbour_ids)
420  this->province_opt->buffer[neighbour_id] |= 0x000000ff;
421  });
422  if(gs.map->province_selected)
423  this->province_opt->buffer[gs.map->selected_province_id] |= 0x400000ff;
424 }
425 
428  this->req_update_vision = true;
429 
430  Eng3D::Rect update_area{ 0, 0, 0, 0 };
431 
432  std::vector<ProvinceId> update_provinces;
433  auto& changed_owner_provinces = gs.world->province_manager.get_changed_owner_provinces();
434  update_provinces.insert(update_provinces.end(), changed_owner_provinces.cbegin(), changed_owner_provinces.cend());
435 
436  auto& changed_control_provinces = gs.world->province_manager.get_changed_control_provinces();
437  update_provinces.insert(update_provinces.end(), changed_control_provinces.cbegin(), changed_control_provinces.cend());
438 
439  std::sort(update_provinces.begin(), update_provinces.end());
440  auto last = std::unique(update_provinces.begin(), update_provinces.end());
441  update_provinces.erase(last, update_provinces.end());
442 
443  if(!update_provinces.empty()) {
444  for(const auto province_id : update_provinces) {
445  auto& province = gs.world->provinces[province_id];
446  update_area = update_area.join(province.box_area);
447  if(this->options.sdf.used)
448  this->update_border_sdf(province.box_area, glm::ivec2(gs.width, gs.height));
449  }
450  this->update_nations(update_provinces);
451  }
452 
453  if(this->req_update_vision) {
454  this->update_visibility();
455  this->req_update_vision = false;
456  }
457  this->update_city_lights();
458  Eng3D::TextureOptions no_drop_options{};
459  no_drop_options.editable = true;
460  this->province_opt->upload(no_drop_options);
461 }
462 
463 void MapRender::draw(const Eng3D::Camera& camera, MapView view_mode) {
464  map_shader->use();
465  const auto view = camera.get_view();
466  map_shader->set_uniform("view", view);
467  const auto cam_pos = camera.get_world_pos();
468  map_shader->set_uniform("view_pos", cam_pos.x, cam_pos.y, cam_pos.z);
469  const auto projection = camera.get_projection();
470  map_shader->set_uniform("projection", projection);
471  const auto map_pos = camera.get_map_pos();
472  float distance_to_map = map_pos.z / this->gs.world->width;
473  map_shader->set_uniform("dist_to_map", distance_to_map);
474  map_shader->set_uniform("map_size", static_cast<float>(this->gs.world->width), static_cast<float>(this->gs.world->height));
475  // A time uniform to send to the shader
476  const auto now = std::chrono::system_clock::now().time_since_epoch();
477  const auto millisec_since_epoch = std::chrono::duration_cast<std::chrono::milliseconds>(now).count();
478  const auto time = static_cast<float>(millisec_since_epoch % 1000000) / 1000.f;
479  map_shader->set_uniform("time", time);
480  map_shader->set_uniform("ticks", this->gs.world->time);
481  // Map should have no "model" matrix since it's always static
482  map_shader->set_texture(0, "tile_sheet", *tile_sheet);
483  map_shader->set_texture(1, "tile_sheet_nation", *tile_sheet_nation);
484  if(options.water.used)
485  map_shader->set_texture(2, "water_texture", *water_tex);
486  if(options.noise.used)
487  map_shader->set_texture(3, "noise_texture", *noise_tex);
488  map_shader->set_texture(4, "terrain_map", *terrain_map); // 4 col
489  if(options.sdf.used)
490  map_shader->set_texture(5, "border_sdf", *(border_sdf.get())); // 1 col
491  if(options.rivers.used)
492  map_shader->set_texture(6, "river_texture", *river_tex); // 1 col
493  if(options.lighting.used) {
494  map_shader->set_texture(7, "wave1", *wave1);
495  map_shader->set_texture(8, "wave2", *wave2);
496  map_shader->set_texture(9, "normal", *normal_topo); // 3 col
497  }
498  map_shader->set_texture(10, "bathymethry", *bathymethry); // 1 col
499  map_shader->set_texture(11, "paper_tex", *paper_tex);
500  //map_shader->set_texture(12, "stripes", *stripes_tex);
501  map_shader->set_texture(13, "province_opt", *province_opt);
502  map_shader->set_texture(14, "terrain_sheet", *terrain_sheet);
503 
504  if(view_mode == MapView::PLANE_VIEW) {
505  for(const auto& quad : this->map_quads)
506  quad->draw();
507  } else if(view_mode == MapView::SPHERE_VIEW) {
508  map_sphere.draw();
509  }
510 }
friend MapRender
Definition: map.hpp:65
virtual glm::mat4 get_view() const =0
Get the view matrix.
virtual glm::vec3 get_map_pos() const =0
Get the map position of the camera.
virtual glm::mat4 get_projection() const
Get the projection matrix.
Definition: camera.hpp:91
glm::vec3 get_world_pos() const
Get the world positions of the camera.
Definition: camera.hpp:78
std::shared_ptr< Eng3D::IO::Asset::Base > get_unique(const Eng3D::IO::Path &path)
Obtaining an unique asset means the "first-found" policy applies.
Definition: io.cpp:146
Eng3D::TextureManager tex_man
Definition: state.hpp:124
Eng3D::IO::PackageManager package_man
Definition: state.hpp:122
void upload(TextureOptions options=default_options)
Frontend for uploading (schedules or instantly uploads)
Definition: texture.hpp:128
void gen_mipmaps() const
Definition: texture.cpp:324
std::shared_ptr< Eng3D::Texture > load(const std::string &path, TextureOptions options=default_options)
Finds a texture in the list of a texture manager if the texture is already in the list we load the sa...
Definition: texture.cpp:432
enum Eng3D::TextureOptions::Wrap wrap_s
Nation * curr_nation
Definition: game_state.hpp:158
std::unique_ptr< Map > map
Definition: game_state.hpp:159
World * world
Definition: game_state.hpp:156
Definition: map.hpp:89
void update_nation_label(const Nation &nation)
Definition: map.cpp:167
void request_update_visibility()
Definition: map_render.cpp:381
void reload_shaders()
Definition: map_render.cpp:132
void update_nations(std::vector< ProvinceId > &nations)
Definition: map_render.cpp:357
void update_options(MapOptions options)
Definition: map_render.cpp:164
void update_border_sdf(Eng3D::Rect update_area, glm::ivec2 window_size)
Creates the "waving" border around the continent to give it a 19th century map feel Generate a distan...
Definition: map_render.cpp:251
void update()
Definition: map_render.cpp:426
void draw(const Eng3D::Camera &camera, MapView view_mode)
Definition: map_render.cpp:463
MapOptions options
Definition: map_render.hpp:112
void update_mapmode(std::vector< ProvinceColor > &province_colors)
Definition: map_render.cpp:342
const std::vector< ProvinceId > & get_changed_control_provinces() const
Definition: province.hpp:196
const std::vector< ProvinceId > & get_changed_owner_provinces() const
Definition: province.hpp:192
bool is_provinces_changed() const
Definition: province.hpp:200
Roughly a batallion, consisting of approximately 500 soldiers each.
Definition: unit.hpp:80
NationId owner_id
Definition: unit.hpp:128
Eng3D::Freelist< Unit > units
Definition: unit.hpp:173
ProvinceId get_unit_current_province(UnitId unit_id) const
Definition: unit.hpp:169
UnitManager unit_manager
Definition: world.hpp:145
Nation::Relation & get_relation(NationId a, NationId b)
Definition: world.hpp:192
size_t width
Definition: world.hpp:220
ProvinceManager province_manager
Definition: world.hpp:146
std::unique_ptr< ProvinceId[]> tiles
Definition: world.hpp:219
int time
Definition: world.hpp:221
size_t height
Definition: world.hpp:220
MapView
Definition: map.hpp:63
void debug(const std::string_view category, const std::string_view msg)
Definition: log.cpp:58
void parallel_for(T range, F &&func)
Primitive color type used through the engine.
Definition: color.hpp:32
void for_each(const F &lambda) const
Definition: freelist.hpp:75
constexpr float height() const
Obtains the height.
Definition: rectangle.hpp:62
constexpr void scale(glm::vec2 factor)
Scales the rectangle by factor.
Definition: rectangle.hpp:104
constexpr float width() const
Obtains the width.
Definition: rectangle.hpp:56
constexpr Id get_id() const
Definition: entity.hpp:152
Id cached_id
Id used to speed up Id lookups on any context.
Definition: entity.hpp:106
Option noise
Definition: map_render.hpp:60
Option sdf
Definition: map_render.hpp:61
Option lighting
Definition: map_render.hpp:62
std::vector< Option > get_options()
Definition: map_render.hpp:73
Option rivers
Definition: map_render.hpp:65
Option water
Definition: map_render.hpp:66
Option compress
Definition: map_render.hpp:71
#define CXX_THROW(class,...)
Definition: utils.hpp:98