8#include <glm/mat3x3.hpp>
9#include <unordered_map>
10#include <glm/gtc/type_ptr.hpp>
11#include <glm/gtx/intersect.hpp>
12#include <glm/gtx/polar_coordinates.hpp>
13#include <glm/gtc/constants.hpp>
14#include <glm/gtx/transform.hpp>
26 auto pt = state.world.province_get_port_to(p);
30 auto adj = state.world.get_province_adjacency_by_province_pair(p, pt);
32 auto id = adj.index();
33 auto& map_data = state.map_state.map_data;
34 auto& border = map_data.borders[id];
35 auto& vertex = map_data.border_vertices[border.start_index + border.count / 2];
36 glm::vec2 map_size = glm::vec2(map_data.size_x, map_data.size_y);
38 return vertex.position * map_size;
42 return prov_id.index() >= state.province_definitions.first_sea_province.index();
47 return state.world.province_get_mid_point(prov_id);
53 return state.world.province_get_mid_point(prov_id);
64 for(
auto pc : state.world.nation_get_province_control_as_nation(n))
65 list.push_back(pc.get_province());
66 for(
auto ac : state.world.nation_get_army_control_as_controller(n))
67 list.push_back(ac.get_army().get_location_from_army_location());
68 for(
auto nc : state.world.nation_get_navy_control_as_controller(n))
69 list.push_back(nc.get_navy().get_location_from_navy_location());
73 std::vector<dcon::province_id> direct_provinces;
75 for(
auto urel : state.world.nation_get_overlord_as_ruler(state.local_player_nation))
77 for(
auto rel : state.world.nation_get_diplomatic_relation(state.local_player_nation)) {
78 if(rel.get_are_allied()) {
79 auto n = rel.get_related_nations(0) == state.local_player_nation ? rel.get_related_nations(1) : rel.get_related_nations(0);
81 for(
auto urel : state.world.nation_get_overlord_as_ruler(n))
87 std::vector<uint32_t> province_fows(state.world.province_size() + 1, 0xFFFFFFFF);
89 state.map_state.visible_provinces.clear();
90 state.map_state.visible_provinces.resize(state.world.province_size() + 1,
false);
91 for(
auto p : direct_provinces) {
94 for(
auto c : state.world.province_get_province_adjacency(p)) {
95 auto pc = c.get_connected_provinces(0) == p ? c.get_connected_provinces(1) : c.get_connected_provinces(0);
102 for(
auto p : state.world.in_province)
106 state.map_state.visible_provinces.clear();
107 state.map_state.visible_provinces.resize(state.world.province_size() + 1,
true);
114 glBindBuffer(GL_ARRAY_BUFFER, vbo);
116 glBufferData(GL_ARRAY_BUFFER,
sizeof(
textured_line_vertex) * data.size(), data.data(), GL_STATIC_DRAW);
122 glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE, offsetof(
textured_line_vertex, normal_direction_));
124 glVertexAttribFormat(2, 1, GL_FLOAT, GL_FALSE, offsetof(
textured_line_vertex, texture_coordinate_));
127 glEnableVertexAttribArray(0);
128 glEnableVertexAttribArray(1);
129 glEnableVertexAttribArray(2);
130 glEnableVertexAttribArray(3);
131 glVertexAttribBinding(0, 0);
132 glVertexAttribBinding(1, 0);
133 glVertexAttribBinding(2, 0);
134 glVertexAttribBinding(3, 0);
139 glBindBuffer(GL_ARRAY_BUFFER, vbo);
154 glEnableVertexAttribArray(0);
155 glEnableVertexAttribArray(1);
156 glEnableVertexAttribArray(2);
157 glEnableVertexAttribArray(3);
158 glEnableVertexAttribArray(4);
159 glVertexAttribBinding(0, 0);
160 glVertexAttribBinding(1, 0);
161 glVertexAttribBinding(2, 0);
162 glVertexAttribBinding(3, 0);
163 glVertexAttribBinding(4, 0);
168 glBindBuffer(GL_ARRAY_BUFFER, vbo);
178 glEnableVertexAttribArray(0);
179 glEnableVertexAttribArray(1);
180 glEnableVertexAttribArray(2);
181 glEnableVertexAttribArray(3);
182 glEnableVertexAttribArray(4);
183 glVertexAttribBinding(0, 0);
184 glVertexAttribBinding(1, 0);
185 glVertexAttribBinding(2, 0);
186 glVertexAttribBinding(3, 0);
187 glVertexAttribBinding(4, 0);
192 glBindBuffer(GL_ARRAY_BUFFER, vbo);
194 glBufferData(GL_ARRAY_BUFFER,
sizeof(
curved_line_vertex) * data.size(), data.data(), GL_STATIC_DRAW);
198 glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, offsetof(
curved_line_vertex, position_));
200 glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE, offsetof(
curved_line_vertex, normal_direction_));
202 glVertexAttribFormat(2, 2, GL_FLOAT, GL_FALSE, offsetof(
curved_line_vertex, direction_));
204 glVertexAttribFormat(3, 2, GL_FLOAT, GL_FALSE, offsetof(
curved_line_vertex, texture_coord_));
207 glEnableVertexAttribArray(0);
208 glEnableVertexAttribArray(1);
209 glEnableVertexAttribArray(2);
210 glEnableVertexAttribArray(3);
211 glEnableVertexAttribArray(4);
212 glVertexAttribBinding(0, 0);
213 glVertexAttribBinding(1, 0);
214 glVertexAttribBinding(2, 0);
215 glVertexAttribBinding(3, 0);
216 glVertexAttribBinding(4, 0);
221 glBindBuffer(GL_ARRAY_BUFFER, vbo);
225 glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, offsetof(
text_line_vertex, position_));
227 glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE, offsetof(
text_line_vertex, normal_direction_));
229 glVertexAttribFormat(2, 2, GL_FLOAT, GL_FALSE, offsetof(
text_line_vertex, direction_));
231 glVertexAttribFormat(3, 3, GL_FLOAT, GL_FALSE, offsetof(
text_line_vertex, texture_coord_));
232 glVertexAttribFormat(4, 1, GL_FLOAT, GL_FALSE, offsetof(
text_line_vertex, thickness_));
233 glEnableVertexAttribArray(0);
234 glEnableVertexAttribArray(1);
235 glEnableVertexAttribArray(2);
236 glEnableVertexAttribArray(3);
237 glEnableVertexAttribArray(4);
238 glEnableVertexAttribArray(5);
239 glVertexAttribBinding(0, 0);
240 glVertexAttribBinding(1, 0);
241 glVertexAttribBinding(2, 0);
242 glVertexAttribBinding(3, 0);
243 glVertexAttribBinding(4, 0);
244 glVertexAttribBinding(5, 0);
249 glBindBuffer(GL_ARRAY_BUFFER, vbo);
253 glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, offsetof(
screen_vertex, position_));
254 glEnableVertexAttribArray(0);
255 glVertexAttribBinding(0, 0);
263 std::vector<map_vertex> land_vertices;
265 auto add_vertex = [map_size = glm::vec2(
float(
size_x),
float(
size_y))](std::vector<map_vertex>& vertices, glm::vec2 pos0) {
266 vertices.emplace_back(pos0.x, pos0.y);
269 glm::vec2 last_pos(0, 0);
272 glm::ivec2 sections(200, 200);
273 for(
int y = 0; y <= sections.y; y++) {
274 pos.y = float(y) / float(sections.y);
275 for(
int x = 0; x <= sections.x; x++) {
276 pos.x = float(x) / float(sections.x);
277 add_vertex(land_vertices, pos);
282 for(
int y = 0; y < sections.y; y++) {
283 auto top_row_start = y * (sections.x + 1);
284 auto bottom_row_start = (y + 1) * (sections.x + 1);
285 map_indices.push_back(uint16_t(bottom_row_start + 0));
286 map_indices.push_back(uint16_t(top_row_start + 0));
287 for(
int x = 0; x < sections.x; x++) {
288 map_indices.push_back(uint16_t(bottom_row_start + 1 + x));
289 map_indices.push_back(uint16_t(top_row_start + 1 + x));
291 map_indices.push_back(std::numeric_limits<uint16_t>::max());
300 glBufferData(GL_ARRAY_BUFFER,
sizeof(
map_vertex) * land_vertices.size(), land_vertices.data(), GL_STATIC_DRAW);
304 glVertexAttribFormat(0, 2, GL_FLOAT, GL_FALSE, offsetof(
map_vertex, position_));
305 glEnableVertexAttribArray(0);
306 glVertexAttribBinding(0, 0);
335 glBindVertexArray(0);
354 for(
const auto shader :
shaders) {
356 glDeleteProgram(shader);
369 auto vshader_string = std::string_view(vshader_content.data, vshader_content.file_size);
371 auto fshader_string = std::string_view(fshader_content.data, fshader_content.file_size);
383 auto line_unit_arrow_vshader =
try_load_shader(root,
NATIVE(
"assets/shaders/glsl/line_unit_arrow_v.glsl"));
384 auto line_unit_arrow_fshader =
try_load_shader(root,
NATIVE(
"assets/shaders/glsl/line_unit_arrow_f.glsl"));
390 auto tline_width_vshader =
try_load_shader(root,
NATIVE(
"assets/shaders/glsl/textured_line_variable_width_v.glsl"));
392 auto river_fshader =
try_load_shader(root,
NATIVE(
"assets/shaders/glsl/textured_line_river_f.glsl"));
450 glEnable(GL_CULL_FACE);
454 glBindFramebuffer(GL_FRAMEBUFFER, state.open_gl.msaa_framebuffer);
455 glClearColor(1.f, 1.f, 1.f, 0.f);
456 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
459 glActiveTexture(GL_TEXTURE0);
461 glActiveTexture(GL_TEXTURE1);
463 glActiveTexture(GL_TEXTURE3);
465 glActiveTexture(GL_TEXTURE4);
467 glActiveTexture(GL_TEXTURE5);
469 glActiveTexture(GL_TEXTURE6);
471 glActiveTexture(GL_TEXTURE7);
473 glActiveTexture(GL_TEXTURE8);
475 glActiveTexture(GL_TEXTURE9);
477 glActiveTexture(GL_TEXTURE10);
479 glActiveTexture(GL_TEXTURE11);
481 glActiveTexture(GL_TEXTURE13);
483 glActiveTexture(GL_TEXTURE14);
485 glActiveTexture(GL_TEXTURE15);
489 auto load_shader = [&](GLuint program) {
490 glUseProgram(
shaders[program]);
501 glEnable(GL_PRIMITIVE_RESTART);
503 glPrimitiveRestartIndex(std::numeric_limits<uint16_t>::max());
524 GLuint fragment_subroutines = 0;
526 fragment_subroutines = 0;
528 fragment_subroutines = 1;
530 fragment_subroutines = 2;
534 glDrawElements(GL_TRIANGLE_STRIP, GLsizei(
map_indices.size() - 1), GL_UNSIGNED_SHORT,
map_indices.data());
537 glDisable(GL_PRIMITIVE_RESTART);
540 if(state.user_settings.rivers_enabled) {
541 glActiveTexture(GL_TEXTURE0);
543 glActiveTexture(GL_TEXTURE1);
545 glActiveTexture(GL_TEXTURE2);
547 glActiveTexture(GL_TEXTURE3);
564 glActiveTexture(GL_TEXTURE0);
566 glActiveTexture(GL_TEXTURE1);
581 constexpr float border_type_national = 0.f;
582 constexpr float border_type_provincial = 1.f;
583 constexpr float border_type_regional = 2.f;
584 constexpr float border_type_coastal = 3.f;
598 glActiveTexture(GL_TEXTURE0);
600 glActiveTexture(GL_TEXTURE1);
605 glActiveTexture(GL_TEXTURE2);
610 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
616 glActiveTexture(GL_TEXTURE2);
620 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
626 glActiveTexture(GL_TEXTURE2);
630 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
637 glActiveTexture(GL_TEXTURE2);
641 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
648 glActiveTexture(GL_TEXTURE2);
652 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
658 glActiveTexture(GL_TEXTURE2);
662 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
669 glActiveTexture(GL_TEXTURE2);
673 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
680 glActiveTexture(GL_TEXTURE2);
684 auto p0 = state.world.province_adjacency_get_connected_provinces(b.adj, 0);
685 auto p1 = state.world.province_adjacency_get_connected_provinces(b.adj, 1);
686 if((state.world.province_get_nation_from_province_ownership(p0) == state.local_player_nation
687 || state.world.province_get_nation_from_province_ownership(p1) == state.local_player_nation)
689 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
693 auto owner = state.world.province_get_nation_from_province_ownership(state.map_state.selected_province);
695 auto siid = state.world.province_get_state_membership(state.map_state.selected_province);
698 auto p0 = state.world.province_adjacency_get_connected_provinces(b.adj, 0);
699 auto p1 = state.world.province_adjacency_get_connected_provinces(b.adj, 1);
700 if((state.world.province_get_state_membership(p0) == siid
701 || state.world.province_get_state_membership(p1) == siid)
703 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
709 auto p0 = state.world.province_adjacency_get_connected_provinces(b.adj, 0);
710 auto p1 = state.world.province_adjacency_get_connected_provinces(b.adj, 1);
711 if(p0 == state.map_state.selected_province || p1 == state.map_state.selected_province) {
712 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
717 dcon::province_id prov{};
719 if(!state.ui_state.under_mouse && state.map_state.screen_to_map(glm::vec2(state.mouse_x_position, state.mouse_y_position), screen_size, state.map_state.current_view(state), map_pos)) {
720 map_pos *= glm::vec2(
float(state.map_state.map_data.size_x),
float(state.map_state.map_data.size_y));
721 auto idx = int32_t(state.map_state.map_data.size_y - map_pos.y) * int32_t(state.map_state.map_data.size_x) + int32_t(map_pos.x);
722 if(0 <= idx &&
size_t(idx) < state.map_state.map_data.province_id_map.size() && state.map_state.map_data.province_id_map[idx] <
province::to_map_id(state.province_definitions.first_sea_province)) {
726 glActiveTexture(GL_TEXTURE2);
728 auto owner = state.world.province_get_nation_from_province_ownership(prov);
732 auto p0 = state.world.province_adjacency_get_connected_provinces(b.adj, 0);
733 auto p1 = state.world.province_adjacency_get_connected_provinces(b.adj, 1);
734 if((state.world.province_get_nation_from_province_ownership(p0) == owner
735 || state.world.province_get_nation_from_province_ownership(p1) == owner)
737 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
741 auto siid = state.world.province_get_state_membership(prov);
744 auto p0 = state.world.province_adjacency_get_connected_provinces(b.adj, 0);
745 auto p1 = state.world.province_adjacency_get_connected_provinces(b.adj, 1);
746 if((state.world.province_get_state_membership(p0) == siid
747 || state.world.province_get_state_membership(p1) == siid)
749 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
755 auto p0 = state.world.province_adjacency_get_connected_provinces(b.adj, 0);
756 auto p1 = state.world.province_adjacency_get_connected_provinces(b.adj, 1);
757 if(p0 == prov || p1 == prov) {
758 glDrawArrays(GL_TRIANGLE_STRIP, b.start_index, b.count);
767 glActiveTexture(GL_TEXTURE2);
782 glActiveTexture(GL_TEXTURE0);
789 glActiveTexture(GL_TEXTURE0);
796 glActiveTexture(GL_TEXTURE0);
803 glActiveTexture(GL_TEXTURE0);
810 glActiveTexture(GL_TEXTURE0);
817 glActiveTexture(GL_TEXTURE0);
843 glActiveTexture(GL_TEXTURE0);
845 glDrawArrays(GL_TRIANGLES, i * 6, 6);
861 constexpr float dist_step = 1.77777f;
863 glEnable(GL_DEPTH_TEST);
864 glClear(GL_DEPTH_BUFFER_BIT);
866 glDepthFunc(GL_GREATER);
881 glActiveTexture(GL_TEXTURE0);
883 for(
uint32_t i = 0; i <
uint32_t(state.province_definitions.first_sea_province.index()); i++) {
884 dcon::province_id p = dcon::province_id(dcon::province_id::value_base_t(i));
887 auto center = state.world.province_get_mid_point(p);
888 auto pos = center + glm::vec2(-dist_step, dist_step);
901 static const model_tier nbe_tiers[] = {
906 for(
const auto& tier : nbe_tiers) {
907 glActiveTexture(GL_TEXTURE0);
909 for(
uint32_t i = 0; i <
uint32_t(state.province_definitions.first_sea_province.index()); i++) {
910 dcon::province_id p = dcon::province_id(dcon::province_id::value_base_t(i));
911 auto units = state.world.province_get_navy_location_as_location(p);
913 if(level >= tier.min && level <= tier.max && units.begin() == units.end()) {
915 auto p2 = state.world.province_get_mid_point(p);
917 auto theta = glm::atan(p2.y - p1.y, p2.x - p1.x);
925 static const model_tier nbf_tiers[] = {
930 for(
const auto& tier : nbf_tiers) {
931 glActiveTexture(GL_TEXTURE0);
933 for(
uint32_t i = 0; i <
uint32_t(state.province_definitions.first_sea_province.index()); i++) {
934 dcon::province_id p = dcon::province_id(dcon::province_id::value_base_t(i));
935 auto units = state.world.province_get_navy_location_as_location(p);
937 if(level >= tier.min && level <= tier.max && units.begin() != units.end()) {
939 auto p2 = state.world.province_get_mid_point(p);
941 auto theta = glm::atan(p2.y - p1.y, p2.x - p1.x);
949 static const model_tier fort_tiers[] = {
954 for(
const auto& tier : fort_tiers) {
955 glActiveTexture(GL_TEXTURE0);
957 for(
uint32_t i = 0; i <
uint32_t(state.province_definitions.first_sea_province.index()); i++) {
958 dcon::province_id p = dcon::province_id(dcon::province_id::value_base_t(i));
960 if(level >= tier.min && level <= tier.max) {
961 auto center = state.world.province_get_mid_point(p);
962 auto pos = center + glm::vec2(dist_step, -dist_step);
971 if(canal_id >=
uint32_t(state.province_definitions.canals.size())
972 && canal_id >=
uint32_t(state.province_definitions.canal_provinces.size()))
974 auto const adj = state.province_definitions.canals[canal_id];
977 glActiveTexture(GL_TEXTURE0);
979 glm::vec2 pos = state.world.province_get_mid_point(state.province_definitions.canal_provinces[canal_id]);
985 render_canal(3, 0, 0.f);
986 render_canal(4, 1, glm::pi<float>() / 2.f),
987 render_canal(2, 2, 0.f);
989 glActiveTexture(GL_TEXTURE0);
991 for(
uint32_t i = 0; i <
uint32_t(state.province_definitions.first_sea_province.index()); i++) {
992 dcon::province_id p = dcon::province_id(dcon::province_id::value_base_t(i));
993 auto factories = state.world.province_get_factory_location_as_province(p);
994 if(factories.begin() != factories.end()) {
995 auto center = state.world.province_get_mid_point(p);
996 auto pos = center + glm::vec2(-dist_step, -dist_step);
1004 glActiveTexture(GL_TEXTURE0);
1006 for(
uint32_t i = 0; i <
uint32_t(state.province_definitions.first_sea_province.index()); i++) {
1007 dcon::province_id p = dcon::province_id(dcon::province_id::value_base_t(i));
1010 auto p2 = state.world.province_get_mid_point(p);
1012 auto theta = glm::atan(p2.y - p1.y, p2.x - p1.x);
1020 glActiveTexture(GL_TEXTURE0);
1022 for(
uint32_t i = 0; i <
uint32_t(state.province_definitions.first_sea_province.index()); i++) {
1023 dcon::province_id p = dcon::province_id(dcon::province_id::value_base_t(i));
1024 auto units = state.world.province_get_army_location_as_location(p);
1026 && units.begin() != units.end()) {
1027 auto p1 = state.world.province_get_mid_point(p);
1029 bool has_unit =
false;
1030 for(
const auto unit : units) {
1031 for(
const auto sm : unit.get_army().get_army_membership()) {
1032 auto& t = state.military_definitions.unit_base_definitions[sm.get_regiment().get_type()];
1033 if(t.type == type) {
1039 if(
auto path = unit.get_army().get_path(); path.size() > 0) {
1040 p2 = state.world.province_get_mid_point(path[path.size() - 1]);
1047 auto theta = glm::atan(p2.y - p1.y, p2.x - p1.x);
1063 glActiveTexture(GL_TEXTURE0);
1065 for(
uint32_t i =
uint32_t(state.province_definitions.first_sea_province.index()); i < state.world.province_size(); i++) {
1066 dcon::province_id p = dcon::province_id(dcon::province_id::value_base_t(i));
1067 auto units = state.world.province_get_navy_location_as_location(p);
1069 && units.begin() != units.end()) {
1072 bool has_unit =
false;
1073 for(
const auto unit : units) {
1074 for(
const auto sm : unit.get_navy().get_navy_membership()) {
1075 auto& t = state.military_definitions.unit_base_definitions[sm.get_ship().get_type()];
1076 if(t.type == type && t.min_port_level <= min_port) {
1082 if(
auto path = unit.get_navy().get_path(); path.size() > 0) {
1090 auto theta = glm::atan(p2.y - p1.y, p2.x - p1.x);
1117 glActiveTexture(GL_TEXTURE0);
1119 for(
uint32_t i = 0; i < state.world.province_size(); i++) {
1120 dcon::province_id p = dcon::province_id(dcon::province_id::value_base_t(i));
1121 auto units = state.world.province_get_navy_location_as_location(p);
1123 && units.begin() != units.end()) {
1124 auto p1 = state.world.province_get_mid_point(p);
1126 auto theta = glm::atan(0.f, 0.f);
1132 glActiveTexture(GL_TEXTURE0);
1134 for(
uint32_t i = 0; i < state.world.province_size(); i++) {
1135 dcon::province_id p = dcon::province_id(dcon::province_id::value_base_t(i));
1136 auto units = state.world.province_get_navy_location_as_location(p);
1138 && units.begin() != units.end()) {
1139 auto p1 = state.world.province_get_mid_point(p);
1141 auto theta = glm::atan(0.f, 0.f);
1148 for(
uint32_t i = 0; i < 3 * 3; i++) {
1149 auto index = 19 + i;
1150 glActiveTexture(GL_TEXTURE0);
1152 for(
uint32_t j = 0; j <
uint32_t(state.province_definitions.first_sea_province.index()); j++) {
1153 dcon::province_id p = dcon::province_id(dcon::province_id::value_base_t(j));
1154 if(state.world.province_get_demographics(p,
demographics::total) >=
float(i * 100000.f)) {
1158 auto center = state.world.province_get_mid_point(p);
1160 pos.x += i == 0 ? 0.f : float(i % 3) * 2.5f;
1161 pos.y += i == 0 ? 0.f : float(i / 3) * 2.5f;
1175 glDisable(GL_DEPTH_TEST);
1179 glBindVertexArray(0);
1180 glDisable(GL_CULL_FACE);
1183 glBindFramebuffer(GL_READ_FRAMEBUFFER, state.open_gl.msaa_framebuffer);
1184 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, state.open_gl.msaa_interbuffer);
1185 glBlitFramebuffer(0, 0, GLint(screen_size.x), GLint(screen_size.y), 0, 0, GLint(screen_size.x), GLint(screen_size.y), GL_COLOR_BUFFER_BIT, GL_NEAREST);
1187 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1189 glUseProgram(state.open_gl.msaa_shader_program);
1190 glUniform1f(state.open_gl.msaa_uniform_gaussian_blur, state.user_settings.gaussianblur_level);
1191 glUniform2f(state.open_gl.msaa_uniform_screen_size, screen_size.x, screen_size.y);
1193 glActiveTexture(GL_TEXTURE0);
1194 glBindTexture(GL_TEXTURE_2D, state.open_gl.msaa_texture);
1195 glBindVertexArray(state.open_gl.msaa_vao);
1197 glDrawArrays(GL_TRIANGLES, 0, 6);
1202 GLuint texture_handle;
1203 glGenTextures(1, &texture_handle);
1204 if(texture_handle) {
1205 glBindTexture(GL_TEXTURE_2D, texture_handle);
1208 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RG8, size_x, size_y);
1209 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size_x, size_y, GL_RG, GL_UNSIGNED_BYTE, &province_index[0]);
1210 glBindTexture(GL_TEXTURE_2D, 0);
1213 return texture_handle;
1218 glBindTexture(GL_TEXTURE_2D, texture_handle);
1220 glBindTexture(GL_TEXTURE_2D_ARRAY, texture_handle);
1231 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &prov_color[0]);
1234 for(
int i = 0; i < layers; i++) {
1235 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, x, y, i, width, height / layers, 1, GL_RGBA, GL_UNSIGNED_BYTE, &prov_color[i * (prov_color.size() / layers)]);
1241 width = left_on_last_row;
1246 if(left_on_last_row > 0 && layers == 1)
1247 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &prov_color[rows * 256]);
1249 glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
1250 glBindTexture(GL_TEXTURE_2D, 0);
1254 std::vector<uint32_t> province_highlights(state.world.province_size() + 1, 0);
1255 state.current_scene.update_highlight_texture(state, province_highlights, prov_id);
1263void add_drag_box_line(std::vector<screen_vertex>& drag_box_vertices, glm::vec2 pos1, glm::vec2 pos2, glm::vec2 size,
bool vertical) {
1273 drag_box_vertices.emplace_back(pos1.x + size.x, pos1.y - size.y);
1274 drag_box_vertices.emplace_back(pos1.x - size.x, pos1.y + size.y);
1275 drag_box_vertices.emplace_back(pos2.x - size.x, pos2.y + size.y);
1277 drag_box_vertices.emplace_back(pos2.x - size.x, pos2.y + size.y);
1278 drag_box_vertices.emplace_back(pos2.x + size.x, pos2.y - size.y);
1279 drag_box_vertices.emplace_back(pos1.x + size.x, pos1.y - size.y);
1288 std::swap(pos1.x, pos2.x);
1290 std::swap(pos1.y, pos2.y);
1292 glm::vec2 size = pixel_size;
1304 glBindBuffer(GL_ARRAY_BUFFER, 0);
1307void add_arrow_to_buffer(std::vector<map::curved_line_vertex>& buffer, glm::vec2 start, glm::vec2 end, glm::vec2 prev_normal_dir, glm::vec2 next_normal_dir,
float fill_progress,
bool end_arrow,
float size_x,
float size_y) {
1308 constexpr float type_filled = 2.f;
1309 constexpr float type_unfilled = 0.f;
1310 constexpr float type_end = 3.f;
1311 glm::vec2 curr_dir = glm::normalize(end - start);
1312 start /= glm::vec2(size_x, size_y);
1313 end /= glm::vec2(size_x, size_y);
1315 if(fill_progress != 0) {
1316 if(fill_progress < 1.0f) {
1317 auto pos3 = glm::mix(start, end, fill_progress);
1318 auto midd_normal_dir = glm::vec2(-curr_dir.y, curr_dir.x);
1320 buffer.emplace_back(pos3, +midd_normal_dir, -curr_dir, glm::vec2(1.0f, 0.0f), type_filled);
1321 buffer.emplace_back(pos3, -midd_normal_dir, -curr_dir, glm::vec2(1.0f, 1.0f), type_filled);
1322 buffer.emplace_back(pos3, +midd_normal_dir, -curr_dir, glm::vec2(1.0f, 0.0f), type_unfilled);
1323 buffer.emplace_back(pos3, -midd_normal_dir, -curr_dir, glm::vec2(1.0f, 1.0f), type_unfilled);
1326 buffer.emplace_back(end, +next_normal_dir, -curr_dir, glm::vec2(1.0f, 0.0f), type_unfilled);
1327 buffer.emplace_back(end, -next_normal_dir, -curr_dir, glm::vec2(1.0f, 1.0f), type_unfilled);
1330 buffer.emplace_back(end, +next_normal_dir, -curr_dir, glm::vec2(1.0f, 0.0f), type_filled);
1331 buffer.emplace_back(end, -next_normal_dir, -curr_dir, glm::vec2(1.0f, 1.0f), type_filled);
1335 if(buffer.back().type_ == type_filled) {
1336 buffer.emplace_back(buffer[buffer.size() - 2]);
1337 buffer.emplace_back(buffer[buffer.size() - 2]);
1338 buffer[buffer.size() - 2].type_ = type_unfilled;
1339 buffer[buffer.size() - 1].type_ = type_unfilled;
1341 buffer.emplace_back(end, +next_normal_dir, -curr_dir, glm::vec2(1.0f, 0.0f), type_unfilled);
1342 buffer.emplace_back(end, -next_normal_dir, -curr_dir, glm::vec2(1.0f, 1.0f), type_unfilled);
1345 if(buffer.back().type_ == type_filled) {
1346 buffer.emplace_back(buffer[buffer.size() - 2]);
1347 buffer.emplace_back(buffer[buffer.size() - 2]);
1348 buffer[buffer.size() - 2].type_ = type_unfilled;
1349 buffer[buffer.size() - 1].type_ = type_unfilled;
1351 buffer.emplace_back(end, +next_normal_dir, -curr_dir, glm::vec2(1.0f, 0.0f), type_end);
1352 buffer.emplace_back(end, -next_normal_dir, -curr_dir, glm::vec2(1.0f, 1.0f), type_end);
1359void add_bezier_to_buffer(std::vector<map::curved_line_vertex>& buffer, glm::vec2 start, glm::vec2 end, glm::vec2 start_per, glm::vec2 end_per,
float progress,
bool last_curve,
float size_x,
float size_y,
uint32_t num_b_segments) {
1362 auto start_control_point = start_per * control_point_length + start;
1363 auto end_control_point = end_per * control_point_length + end;
1365 auto bpoint = [=](
float t) {
1368 + (u * u * u) * start
1369 + (3.0f * u * u * t) * start_control_point
1370 + (3.0f * u * t * t) * end_control_point
1371 + (t * t * t) * end;
1374 auto last_normal = glm::vec2(-start_per.y, start_per.x);
1375 glm::vec2 next_normal{ 0.0f, 0.0f };
1377 for(
uint32_t i = 0; i < num_b_segments - 1; ++i) {
1378 auto t_start = float(i) / float(num_b_segments);
1379 auto t_end = float(i + 1) / float(num_b_segments);
1380 auto t_next = float(i + 2) / float(num_b_segments);
1382 auto start_point = bpoint(t_start);
1383 auto end_point = bpoint(t_end);
1384 auto next_point = bpoint(t_next);
1386 next_normal = glm::normalize(end_point - start_point) + glm::normalize(end_point - next_point);
1387 auto temp = glm::normalize(end_point - start_point);
1388 if(glm::length(next_normal) < 0.00001f) {
1389 next_normal = glm::normalize(glm::vec2(-temp.y, temp.x));
1391 next_normal = glm::normalize(next_normal);
1392 if(glm::dot(glm::vec2(-temp.y, temp.x), next_normal) < 0) {
1393 next_normal = -next_normal;
1397 if(progress > 0.0f) {
1398 if(t_end <= progress) {
1399 add_arrow_to_buffer(buffer, start_point, end_point, last_normal, next_normal, 1.0f,
false, size_x, size_y);
1400 }
else if(progress < t_start) {
1401 add_arrow_to_buffer(buffer, start_point, end_point, last_normal, next_normal, 0.0f,
false, size_x, size_y);
1403 auto effective_progress = (progress - t_start) *
float(num_b_segments);
1404 add_arrow_to_buffer(buffer, start_point, end_point, last_normal, next_normal, effective_progress,
false, size_x, size_y);
1407 add_arrow_to_buffer(buffer, start_point, end_point, last_normal, next_normal, 0.0f,
false, size_x, size_y);
1410 last_normal = next_normal;
1413 next_normal = glm::vec2(end_per.y, -end_per.x);
1414 auto t_start = float(num_b_segments - 1) / float(num_b_segments);
1416 auto start_point = bpoint(t_start);
1417 auto end_point = bpoint(t_end);
1419 if(progress > 0.0f) {
1420 if(t_end <= progress) {
1421 add_arrow_to_buffer(buffer, start_point, end_point, last_normal, next_normal, 1.0f, last_curve, size_x, size_y);
1422 }
else if(progress < t_start) {
1423 add_arrow_to_buffer(buffer, start_point, end_point, last_normal, next_normal, 0.0f, last_curve, size_x, size_y);
1425 auto effective_progress = (progress - t_start) *
float(num_b_segments);
1426 add_arrow_to_buffer(buffer, start_point, end_point, last_normal, next_normal, effective_progress, last_curve, size_x, size_y);
1429 add_arrow_to_buffer(buffer, start_point, end_point, last_normal, next_normal, 0.0f, last_curve, size_x, size_y);
1434void add_tl_segment_buffer(std::vector<map::textured_line_vertex>& buffer, glm::vec2 start, glm::vec2 end, glm::vec2 next_normal_dir,
float size_x,
float size_y,
float& distance) {
1435 start /= glm::vec2(size_x, size_y);
1436 end /= glm::vec2(size_x, size_y);
1437 auto d = start - end;
1439 distance += 0.5f * glm::length(d);
1444void add_tl_segment_buffer(std::vector<map::textured_line_with_width_vertex>& buffer, glm::vec2 start, glm::vec2 end, glm::vec2 next_normal_dir,
float size_x,
float size_y,
float& distance,
float width) {
1445 start /= glm::vec2(size_x, size_y);
1446 end /= glm::vec2(size_x, size_y);
1447 auto d = start - end;
1448 distance += glm::length(d);
1453void add_tl_bezier_to_buffer(std::vector<map::textured_line_vertex>& buffer, glm::vec2 start, glm::vec2 end, glm::vec2 start_per, glm::vec2 end_per,
float progress,
bool last_curve,
float size_x,
float size_y,
uint32_t num_b_segments,
float& distance) {
1456 auto start_control_point = start_per * control_point_length + start;
1457 auto end_control_point = end_per * control_point_length + end;
1459 auto bpoint = [=](
float t) {
1462 + (u * u * u) * start
1463 + (3.0f * u * u * t) * start_control_point
1464 + (3.0f * u * t * t) * end_control_point
1465 + (t * t * t) * end;
1468 auto last_normal = glm::vec2(-start_per.y, start_per.x);
1469 glm::vec2 next_normal{ 0.0f, 0.0f };
1471 for(
uint32_t i = 0; i < num_b_segments - 1; ++i) {
1472 auto t_start = float(i) / float(num_b_segments);
1473 auto t_end = float(i + 1) / float(num_b_segments);
1474 auto t_next = float(i + 2) / float(num_b_segments);
1476 auto start_point = bpoint(t_start);
1477 auto end_point = bpoint(t_end);
1478 auto next_point = bpoint(t_next);
1480 next_normal = glm::normalize(end_point - start_point) + glm::normalize(end_point - next_point);
1481 auto temp = glm::normalize(end_point - start_point);
1482 if(glm::length(next_normal) < 0.00001f) {
1483 next_normal = glm::normalize(glm::vec2(-temp.y, temp.x));
1485 next_normal = glm::normalize(next_normal);
1486 if(glm::dot(glm::vec2(-temp.y, temp.x), next_normal) < 0) {
1487 next_normal = -next_normal;
1493 last_normal = next_normal;
1496 next_normal = glm::vec2(end_per.y, -end_per.x);
1497 auto t_start = float(num_b_segments - 1) / float(num_b_segments);
1499 auto start_point = bpoint(t_start);
1500 auto end_point = bpoint(t_end);
1506void add_tl_bezier_to_buffer(std::vector<map::textured_line_with_width_vertex>& buffer, glm::vec2 start, glm::vec2 end, glm::vec2 start_tangent, glm::vec2 end_tangent,
float progress,
bool last_curve,
float size_x,
float size_y,
uint32_t num_b_segments,
float& distance,
float width_start,
float width_end) {
1509 auto start_control_point = start_tangent * control_point_length + start;
1510 auto end_control_point = -end_tangent * control_point_length + end;
1512 auto bpoint = [=](
float t) {
1515 + (u * u * u) * start
1516 + (3.0f * u * u * t) * start_control_point
1517 + (3.0f * u * t * t) * end_control_point
1518 + (t * t * t) * end;
1521 auto last_normal = glm::vec2(-start_tangent.y, start_tangent.x);
1522 glm::vec2 current_normal{ 0.0f, 0.0f };
1524 for(
uint32_t i = 0; i < num_b_segments - 1; ++i) {
1525 auto t_start = float(i) / float(num_b_segments);
1526 auto t_end = float(i + 1) / float(num_b_segments);
1527 auto t_next = float(i + 2) / float(num_b_segments);
1529 auto start_point = bpoint(t_start);
1530 auto end_point = bpoint(t_end);
1531 auto next_point = bpoint(t_next);
1533 auto tangent_part_1 = glm::normalize(end_point - start_point);
1534 auto tangent_part_2 = glm::normalize(next_point - end_point);
1535 auto current_tangent = glm::normalize(tangent_part_1 + tangent_part_2);
1537 current_normal = glm::vec2(-current_tangent.y, current_tangent.x);
1539 auto width = t_start * width_end + (1.f - t_start) * width_start;
1541 if(width != width_end) {
1545 add_tl_segment_buffer(buffer, start_point, end_point, current_normal, size_x, size_y, distance, width);
1547 last_normal = current_normal;
1550 current_normal = glm::vec2(-end_tangent.y, end_tangent.x);
1551 auto t_start = float(num_b_segments - 1) / float(num_b_segments);
1553 auto start_point = bpoint(t_start);
1554 auto end_point = bpoint(t_end);
1555 auto width = t_start * width_end + (1.f - t_start) * width_start;
1557 add_tl_segment_buffer(buffer, start_point, end_point, current_normal, size_x, size_y, distance, width);
1561glm::vec2
put_in_local(glm::vec2 new_point, glm::vec2 base_point,
float size_x) {
1562 auto uadjx = std::abs(new_point.x - base_point.x);
1563 auto ladjx = std::abs(new_point.x - size_x - base_point.x);
1564 auto radjx = std::abs(new_point.x + size_x - base_point.x);
1566 return uadjx < radjx ? new_point : glm::vec2{ new_point.x + size_x, new_point.y };
1568 return ladjx < radjx ? glm::vec2{ new_point.x - size_x, new_point.y } : glm::vec2{ new_point.x + size_x, new_point.y };
1572void make_navy_path(
sys::state& state, std::vector<map::curved_line_vertex>& buffer, dcon::navy_id selected_navy,
float size_x,
float size_y) {
1573 auto path = state.world.navy_get_path(selected_navy);
1574 if(
auto ps = path.size(); ps > 0) {
1579 glm::vec2 prev_perpendicular = glm::normalize(next_pos - current_pos);
1581 auto start_normal = glm::vec2(-prev_perpendicular.y, prev_perpendicular.x);
1582 auto norm_pos = current_pos / glm::vec2(size_x, size_y);
1584 buffer.emplace_back(norm_pos, +start_normal, glm::vec2{ 0,0 }, glm::vec2(0.0f, 0.0f), progress > 0.0f ? 2.0f : 0.0f);
1585 buffer.emplace_back(norm_pos, -start_normal, glm::vec2{ 0,0 }, glm::vec2(0.0f, 1.0f), progress > 0.0f ? 2.0f : 0.0f);
1586 for(
auto i = ps; i-- > 0;) {
1587 glm::vec2 next_perpendicular{ 0.0f, 0.0f };
1592 glm::vec2 a_per = glm::normalize(next_pos - current_pos);
1593 glm::vec2 b_per = glm::normalize(next_pos - next_next_pos);
1594 glm::vec2 temp = a_per + b_per;
1595 if(glm::length(temp) < 0.00001f) {
1596 next_perpendicular = -a_per;
1598 next_perpendicular = glm::normalize(glm::vec2{ -temp.y, temp.x });
1599 if(glm::dot(a_per, -next_perpendicular) < glm::dot(a_per, next_perpendicular)) {
1600 next_perpendicular *= -1.0f;
1604 next_perpendicular = glm::normalize(current_pos - next_pos);
1609 prev_perpendicular = -1.0f * next_perpendicular;
1616void make_army_path(
sys::state& state, std::vector<map::curved_line_vertex>& buffer, dcon::army_id selected_army,
float size_x,
float size_y) {
1617 auto path = state.world.army_get_path(selected_army);
1618 if(
auto ps = path.size(); ps > 0) {
1623 glm::vec2 prev_perpendicular = glm::normalize(next_pos - current_pos);
1625 auto start_normal = glm::vec2(-prev_perpendicular.y, prev_perpendicular.x);
1626 auto norm_pos = current_pos / glm::vec2(size_x, size_y);
1628 buffer.emplace_back(norm_pos, +start_normal, glm::vec2{0,0}, glm::vec2(0.0f, 0.0f), progress > 0.0f ? 2.0f : 0.0f);
1629 buffer.emplace_back(norm_pos, -start_normal, glm::vec2{ 0,0 }, glm::vec2(0.0f, 1.0f), progress > 0.0f ? 2.0f : 0.0f);
1630 for(
auto i = ps; i-- > 0;) {
1631 glm::vec2 next_perpendicular{ 0.0f, 0.0f };
1636 glm::vec2 a_per = glm::normalize(next_pos - current_pos);
1637 glm::vec2 b_per = glm::normalize(next_pos - next_next_pos);
1638 glm::vec2 temp = a_per + b_per;
1639 if(glm::length(temp) < 0.00001f) {
1640 next_perpendicular = -a_per;
1642 next_perpendicular = glm::normalize(glm::vec2{ -temp.y, temp.x });
1643 if(glm::dot(a_per, -next_perpendicular) < glm::dot(a_per, next_perpendicular)) {
1644 next_perpendicular *= -1.0f;
1648 next_perpendicular = glm::normalize(current_pos - next_pos);
1653 prev_perpendicular = -1.0f * next_perpendicular;
1660 auto const m1 = state.world.province_get_mid_point(p1);
1661 auto const m2 = state.world.province_get_mid_point(p2);
1662 railroad.emplace_back(m1);
1664 auto mid = ((m1 + m2) / glm::vec2(2.f, 2.f));
1665 const auto rp =
rng::get_random(state, p1.index(), p2.index() ^ p1.index());
1667 auto const perpendicular = glm::normalize(m2 - m1) * glm::vec2(rf, rf);
1668 railroad.emplace_back(mid + glm::vec2(-perpendicular.y, perpendicular.x));
1674 if(visited_prov[p.index()])
1676 visited_prov[p.index()] =
true;
1677 provinces.push_back(p);
1679 std::vector<dcon::province_adjacency_id> valid_adj;
1680 for(
const auto adj : state.world.province_get_province_adjacency_as_connected_provinces(p)) {
1681 auto const pa = adj.get_connected_provinces(adj.get_connected_provinces(0) == p ? 1 : 0);
1683 || visited_prov[pa.id.index()])
1689 valid_adj.push_back(adj.id);
1691 std::sort(valid_adj.begin(), valid_adj.end(), [&](
auto const a,
auto const b) ->
bool {
1692 auto const ad = state.world.province_adjacency_get_distance(a);
1693 auto const bd = state.world.province_adjacency_get_distance(b);
1696 for(
const auto a : valid_adj) {
1698 auto const pa = adj.get_connected_provinces(adj.get_connected_provinces(0) == p ? 1 : 0);
1700 visited_adj[adj.id.index()] =
true;
1709 std::vector<bool> visited_prov(state.world.province_size() + 1,
false);
1710 std::vector<bool> rr_ends(state.world.province_size() + 1,
false);
1711 std::vector<bool> visited_adj(state.world.province_adjacency_size() + 1,
false);
1712 std::vector<std::vector<glm::vec2>> railroads;
1713 for(
const auto p : state.world.in_province) {
1714 std::vector<dcon::province_id> provinces;
1716 if(provinces.size() > 1) {
1717 std::vector<glm::vec2> railroad;
1720 railroad.emplace_back(state.world.province_get_mid_point(provinces.back()));
1721 assert(!railroad.empty());
1722 railroads.push_back(railroad);
1723 rr_ends[provinces.front().index()] =
true;
1724 rr_ends[provinces.back().index()] =
true;
1731 for(
const auto p1 : state.world.in_province) {
1732 if(visited_prov[p1.id.index()]) {
1735 auto max_adj = std::max<uint32_t>(
uint32_t(admin_efficiency * 2.75f), rr_ends[p1.id.index()] ? 3 : 1);
1736 std::vector<dcon::province_adjacency_id> valid_adj;
1737 for(
const auto adj : p1.get_province_adjacency_as_connected_provinces()) {
1740 auto p2 = adj.get_connected_provinces(adj.get_connected_provinces(0) == p1.id ? 1 : 0);
1744 if(visited_adj[adj.id.index()])
1746 if(rr_ends[p1.id.index()] != rr_ends[p2.id.index()]
1747 && rr_ends[p1.id.index()] ==
false)
1749 visited_adj[adj.id.index()] =
true;
1750 valid_adj.push_back(adj.id);
1752 std::sort(valid_adj.begin(), valid_adj.end(), [&](
auto const a,
auto const b) ->
bool {
1753 auto const ad = state.world.province_adjacency_get_distance(a);
1754 auto const bd = state.world.province_adjacency_get_distance(b);
1757 for(
const auto a : valid_adj) {
1759 auto const p2 = adj.get_connected_provinces(adj.get_connected_provinces(0) == p1.id ? 1 : 0);
1761 std::vector<glm::vec2> railroad;
1763 railroad.emplace_back(state.world.province_get_mid_point(p2.id));
1764 assert(!railroad.empty());
1765 railroads.push_back(railroad);
1773 for(
const auto& railroad : railroads) {
1775 glm::vec2 current_pos = railroad.back();
1776 glm::vec2 next_pos =
put_in_local(railroad[railroad.size() - 2], current_pos,
float(
size_x));
1777 glm::vec2 prev_perpendicular = glm::normalize(next_pos - current_pos);
1778 auto start_normal = glm::vec2(-prev_perpendicular.y, prev_perpendicular.x);
1779 auto norm_pos = current_pos / glm::vec2(
size_x,
size_y);
1782 float distance = 0.0f;
1783 for(
auto i = railroad.size() - 1; i-- > 0;) {
1784 glm::vec2 next_perpendicular{ 0.0f, 0.0f };
1788 glm::vec2 a_per = glm::normalize(next_pos - current_pos);
1789 glm::vec2 b_per = glm::normalize(next_pos - next_next_pos);
1790 glm::vec2 temp = a_per + b_per;
1791 if(glm::length(temp) < 0.00001f) {
1792 next_perpendicular = -a_per;
1794 next_perpendicular = glm::normalize(glm::vec2{ -temp.y, temp.x });
1795 if(glm::dot(a_per, -next_perpendicular) < glm::dot(a_per, next_perpendicular))
1796 next_perpendicular *= -1.0f;
1799 next_perpendicular = glm::normalize(current_pos - next_pos);
1801 add_tl_bezier_to_buffer(
railroad_vertices, current_pos, next_pos, prev_perpendicular, next_perpendicular, 0.0f,
false,
float(
size_x),
float(
size_y),
default_num_b_segments, distance);
1802 prev_perpendicular = -1.0f * next_perpendicular;
1803 current_pos = railroad[i];
1813 glBindBuffer(GL_ARRAY_BUFFER, 0);
1821 const auto map_x_scaling = float(
size_x) / float(
size_y);
1824 for(
const auto& e : data) {
1826 if(!std::isfinite(e.coeff[0]) || !std::isfinite(e.coeff[1]) || !std::isfinite(e.coeff[2]) || !std::isfinite(e.coeff[3]))
1829 bool is_linear =
true;
1830 if((e.coeff[2] != 0) || (e.coeff[3] != 0)) {
1836 auto poly_fn = [&](
float x) {
1837 return e.coeff[0] + e.coeff[1] * x + e.coeff[2] * x * x + e.coeff[3] * x * x * x;
1839 auto dpoly_fn = [&](
float x) {
1842 return e.coeff[1] + 2.f * e.coeff[2] * x + 3.f * e.coeff[3] * x * x;
1852 if(e.coeff[1] > 0.01f) {
1853 left = (-e.coeff[0]) / e.coeff[1];
1854 right = (1.f - e.coeff[0]) / e.coeff[1];
1855 }
else if(e.coeff[1] < -0.01f) {
1856 left = (1.f - e.coeff[0]) / e.coeff[1];
1857 right = (- e.coeff[0]) / e.coeff[1];
1860 while(((poly_fn(left) < 0.f) || (poly_fn(left) > 1.f)) && (left < 1.f)) {
1861 left += 1.f / 300.f;
1863 while(((poly_fn(right) < 0.f) || (poly_fn(right) > 1.f)) && (right > 0.f)) {
1864 right -= 1.f / 300.f;
1869 left = std::clamp(left, 0.f, 1.f);
1870 right = std::clamp(right, 0.f, 1.f);
1877 float result_interval = right - left;
1878 float center = (right + left) / 2.f;
1880 glm::vec2 ratio = e.ratio;
1881 glm::vec2 basis = e.basis;
1883 auto effective_ratio = ratio.x * map_x_scaling / ratio.y;
1885 float text_length = f.text_extent(state, e.text, 0,
uint32_t(e.text.glyph_info.size()), 1);
1886 assert(std::isfinite(text_length) && text_length != 0.f);
1887 float x_step = (result_interval / float(e.text.glyph_info.size() * 32.f));
1888 float curve_length = 0.f;
1890 float height = poly_fn(right) - poly_fn(left);
1891 curve_length = 2.f * glm::length(glm::vec2(height * ratio.y, result_interval * ratio.x));
1892 }
else for(
float x = left; x <= right; x += x_step) {
1893 curve_length += 2.0f * glm::length(glm::vec2(x_step * ratio.x, (poly_fn(x) - poly_fn(x + x_step)) * ratio.y));
1895 float size = (curve_length / text_length) * 0.8f;
1899 float font_size_index = std::round(5.f * log(size) / log(1.618034f));
1901 if(font_size_index > 45.f) {
1902 font_size_index = 45.f;
1904 if (font_size_index > 5.f)
1905 font_size_index = 5.f * std::round(font_size_index / 5.f);
1907 size = std::pow(1.618034f, font_size_index / 5.f);
1932 auto real_text_size = size / (
size_x * 2.0f);
1934 float letter_spacing_map = std::clamp((0.8f * curve_length / text_length - size) / 2.f, 0.f, size * 2.f);
1935 if(state.world.locale_get_prevent_letterspace(state.font_collection.get_current_locale())) {
1936 letter_spacing_map = 0.f;
1939 float margin = (curve_length - text_length * (size + letter_spacing_map * 2.f) + letter_spacing_map) / 2.0f;
1941 for(
float accumulated_length = 0.f; ; x += x_step) {
1942 auto added_distance = 2.0f * glm::length(glm::vec2(x_step * ratio.x, (poly_fn(x) - poly_fn(x + x_step)) * e.ratio.y));
1943 if(accumulated_length + added_distance >= margin) {
1944 x += x_step * (margin - accumulated_length) / added_distance;
1947 accumulated_length += added_distance;
1951 unsigned int glyph_count =
static_cast<unsigned int>(e.text.glyph_info.size());
1952 for(
unsigned int i = 0; i < glyph_count; i++) {
1953 hb_codepoint_t glyphid = e.text.glyph_info[i].codepoint;
1954 auto gso = f.glyph_positions[glyphid];
1958 if(glyphid != FT_Get_Char_Index(f.font_face,
' ')) {
1960 glm::vec2 glyph_positions{ x_offset / 64.f, -y_offset / 64.f };
1962 glm::vec2 curr_dir = glm::normalize(glm::vec2(effective_ratio, dpoly_fn(x)));
1963 glm::vec2 curr_normal_dir = glm::vec2(-curr_dir.y, curr_dir.x);
1965 curr_normal_dir.x *= 0.5f;
1967 glm::vec2 shader_direction = glm::normalize(glm::vec2(ratio.x, dpoly_fn(x) * ratio.y));
1969 auto p0 = glm::vec2(x, poly_fn(x)) * ratio + basis;
1971 p0 -= (1.5f - 2.f * glyph_positions.y) * curr_normal_dir * real_text_size;
1972 p0 += (1.0f + 2.f * glyph_positions.x) * curr_dir * real_text_size;
1975 float step = 1.f / 8.f;
1976 float tx = float(gso.texture_slot & 7) * step;
1977 float ty = float((gso.texture_slot & 63) >> 3) * step;
1979 text_line_vertices.emplace_back(p0, glm::vec2(-1, 1), shader_direction, glm::vec3(tx, ty, type), real_text_size);
1980 text_line_vertices.emplace_back(p0, glm::vec2(-1, -1), shader_direction, glm::vec3(tx, ty + step, type), real_text_size);
1981 text_line_vertices.emplace_back(p0, glm::vec2(1, -1), shader_direction, glm::vec3(tx + step, ty + step, type), real_text_size);
1983 text_line_vertices.emplace_back(p0, glm::vec2(1, -1), shader_direction, glm::vec3(tx + step, ty + step, type), real_text_size);
1984 text_line_vertices.emplace_back(p0, glm::vec2(1, 1), shader_direction, glm::vec3(tx + step, ty, type), real_text_size);
1985 text_line_vertices.emplace_back(p0, glm::vec2(-1, 1), shader_direction, glm::vec3(tx, ty, type), real_text_size);
1988 float glyph_advance = x_advance * size / 64.f;
1989 for(
float glyph_length = 0.f; ; x += x_step) {
1990 auto added_distance = 2.0f * glm::length(glm::vec2(x_step * ratio.x, (poly_fn(x) - poly_fn(x + x_step)) * ratio.y));
1991 if(glyph_length + added_distance >= glyph_advance + letter_spacing_map) {
1992 x += x_step * (glyph_advance + letter_spacing_map - glyph_length) / added_distance;
1995 glyph_length += added_distance;
2002 glBindBuffer(GL_ARRAY_BUFFER, 0);
2008 const auto map_x_scaling = float(
size_x) / float(
size_y);
2011 for(
const auto& e : data) {
2013 if(!std::isfinite(e.coeff[0]) || !std::isfinite(e.coeff[1]) || !std::isfinite(e.coeff[2]) || !std::isfinite(e.coeff[3]))
2016 auto effective_ratio = e.ratio.x * map_x_scaling / e.ratio.y;
2018 float text_length = f.text_extent(state, e.text, 0,
uint32_t(e.text.glyph_info.size()), 1);
2019 assert(std::isfinite(text_length) && text_length != 0.f);
2022 auto poly_fn = [&](
float x) {
2023 return e.coeff[0] + e.coeff[1] * x + e.coeff[2] * x * x + e.coeff[3] * x * x * x;
2025 float x_step = (1.f / float(e.text.glyph_info.size() * 32.f));
2026 float curve_length = 0.f;
2027 for(
float x = 0.f; x <= 1.f; x += x_step)
2028 curve_length += 2.0f * glm::length(glm::vec2(x_step * e.ratio.x, (poly_fn(x) - poly_fn(x + x_step)) * e.ratio.y));
2030 float size = (curve_length / text_length) * 0.85f;
2032 size = 200.0f + (size - 200.0f) * 0.5f;
2034 auto real_text_size = size / (
size_x * 2.0f);
2035 float margin = (curve_length - text_length * size) / 2.0f;
2037 for(
float accumulated_length = 0.f; ; x += x_step) {
2038 auto added_distance = 2.0f * glm::length(glm::vec2(x_step * e.ratio.x, (poly_fn(x) - poly_fn(x + x_step)) * e.ratio.y));
2039 if(accumulated_length + added_distance >= margin) {
2040 x += x_step * (margin - accumulated_length) / added_distance;
2043 accumulated_length += added_distance;
2046 unsigned int glyph_count =
uint32_t(e.text.glyph_info.size());
2047 for(
unsigned int i = 0; i < glyph_count; i++) {
2048 hb_codepoint_t glyphid = e.text.glyph_info[i].codepoint;
2049 auto gso = f.glyph_positions[glyphid];
2050 float x_advance = float(gso.x_advance);
2051 float x_offset = float(e.text.glyph_info[i].x_offset) / 4.f + float(gso.x);
2052 float y_offset = float(gso.y) - float(e.text.glyph_info[i].y_offset) / 4.f;
2053 if(glyphid != FT_Get_Char_Index(f.font_face,
' ')) {
2055 glm::vec2 glyph_positions{ x_offset / 64.f, -y_offset / 64.f };
2056 auto dpoly_fn = [&](
float x) {
2059 return e.coeff[1] + 2.f * e.coeff[2] * x + 3.f * e.coeff[3] * x * x;
2061 glm::vec2 curr_dir = glm::normalize(glm::vec2(effective_ratio, dpoly_fn(x)));
2062 glm::vec2 curr_normal_dir = glm::vec2(-curr_dir.y, curr_dir.x);
2064 curr_normal_dir.x *= 0.5f;
2066 glm::vec2 shader_direction = glm::normalize(glm::vec2(e.ratio.x, dpoly_fn(x) * e.ratio.y));
2068 auto p0 = glm::vec2(x, poly_fn(x)) * e.ratio + e.basis;
2070 p0 -= (1.5f - 2.f * glyph_positions.y) * curr_normal_dir * real_text_size;
2071 p0 += (1.0f + 2.f * glyph_positions.x) * curr_dir * real_text_size;
2074 float step = 1.f / 8.f;
2075 float tx = float(gso.texture_slot & 7) * step;
2076 float ty = float((gso.texture_slot & 63) >> 3) * step;
2079 province_text_line_vertices.emplace_back(p0, glm::vec2(-1, -1), shader_direction, glm::vec3(tx, ty + step, type), real_text_size);
2080 province_text_line_vertices.emplace_back(p0, glm::vec2(1, -1), shader_direction, glm::vec3(tx + step, ty + step, type), real_text_size);
2082 province_text_line_vertices.emplace_back(p0, glm::vec2(1, -1), shader_direction, glm::vec3(tx + step, ty + step, type), real_text_size);
2086 float glyph_advance = x_advance * size / 64.f;
2087 for(
float glyph_length = 0.f; ; x += x_step) {
2088 auto added_distance = 2.0f * glm::length(glm::vec2(x_step * e.ratio.x, (poly_fn(x) - poly_fn(x + x_step)) * e.ratio.y));
2089 if(glyph_length + added_distance >= glyph_advance) {
2090 x += x_step * (glyph_advance - glyph_length) / added_distance;
2093 glyph_length += added_distance;
2100 glBindBuffer(GL_ARRAY_BUFFER, 0);
2109 OutputDebugStringA(full_message.c_str());
2111 std::fprintf(stderr,
"%s", full_message.c_str());
2122 for(
const auto& layer : mat.
layers) {
2127 for(
const auto& layer : mat.
layers) {
2128 if(strstr(layer.texture.c_str(),
"spec") == NULL) {
2132 return mat.
layers.empty()
2139 struct static_mesh_vertex {
2140 glm::vec3 position_;
2142 glm::vec2 texture_coord_;
2144 std::vector<static_mesh_vertex> static_mesh_vertices;
2145 static const std::array<native_string_view, display_data::max_static_meshes> xac_model_names = {
2146 NATIVE(
"capital_bigben"),
2147 NATIVE(
"capital_eiffeltower"),
2152 NATIVE(
"Navalbase_Late_Empty"),
2153 NATIVE(
"Navalbase_Late_Full"),
2157 NATIVE(
"generic_euro_infantry"),
2158 NATIVE(
"Generic_Frigate"),
2159 NATIVE(
"Generic_Manowar"),
2160 NATIVE(
"Generic_Transport_Ship"),
2163 NATIVE(
"Infantry_shadowblob"),
2164 NATIVE(
"Generic_Euro_Infantry2"),
2165 NATIVE(
"buildings_01_1"),
2166 NATIVE(
"buildings_01_2"),
2167 NATIVE(
"buildings_01_3"),
2168 NATIVE(
"buildings_02_1"),
2169 NATIVE(
"buildings_02_2"),
2170 NATIVE(
"buildings_02_3"),
2171 NATIVE(
"buildings_03_1"),
2172 NATIVE(
"buildings_03_2"),
2173 NATIVE(
"buildings_03_3"),
2176 NATIVE(
"Navalbase_Early_Empty"),
2177 NATIVE(
"Navalbase_Early_Full"),
2178 NATIVE(
"Navalbase_Mid_Empty"),
2179 NATIVE(
"Navalbase_Mid_Full"),
2180 NATIVE(
"Generic_Battleship"),
2181 NATIVE(
"Generic_Cruiser"),
2182 NATIVE(
"Generic_Ironclad"),
2183 NATIVE(
"Generic_Raider"),
2187 static const std::array<float, display_data::max_static_meshes> scaling_factor = {
2231 constexpr float no_elim = 9999.f + 0.1f;
2232 constexpr float quad_elim = 9999.f + 0.2f;
2233 static const std::array<float, display_data::max_static_meshes> elim_factor = {
2283 auto old_size = static_mesh_vertices.size();
2289 emfx::parse_xac(context, contents.data, contents.data + contents.file_size, err);
2292 auto& texid = state.map_state.map_data.static_mesh_textures[k];
2293 for(
auto const& node : context.nodes) {
2294 int32_t mesh_index = 0;
2295 for(
auto const& mesh : node.meshes) {
2296 bool is_collision = node.collision_mesh == mesh_index;
2297 bool is_visual = node.visual_mesh == mesh_index;
2300 for(
auto const& sub : mesh.submeshes) {
2302 static_mesh_vertex triangle_vertices[3];
2304 static_mesh_vertex smv;
2305 auto index = sub.indices[i + j] + vertex_offset;
2306 auto vv = mesh.vertices[index % mesh.vertices.size()];
2307 auto vn = mesh.normals.empty()
2309 : mesh.normals[index % mesh.normals.size()];
2310 auto vt = mesh.texcoords.empty()
2312 : mesh.texcoords[index % mesh.texcoords.size()];
2313 smv.position_ = glm::vec3(vv.x, vv.y, vv.z);
2314 smv.normal_ = glm::vec3(vn.x, vn.y, vn.z);
2315 smv.texture_coord_ = glm::vec2(vt.x, vt.y);
2316 triangle_vertices[j] = smv;
2320 bool keep = is_visual;
2321 if(elim_factor[k] == no_elim) {
2323 for(
const auto& smv : triangle_vertices) {
2324 static_mesh_vertex tmp = smv;
2325 tmp.position_ *= scaling_factor[k];
2326 static_mesh_vertices.push_back(tmp);
2329 }
else if(elim_factor[k] == quad_elim) {
2330 if(triangle_vertices[0].position_.y <= -0.1f
2331 || triangle_vertices[1].position_.y <= -0.1f
2332 || triangle_vertices[2].position_.y <= -0.1f) {
2333 for(
const auto& smv : triangle_vertices) {
2334 static_mesh_vertex tmp = smv;
2335 tmp.position_ *= scaling_factor[k];
2336 static_mesh_vertices.push_back(tmp);
2340 if(triangle_vertices[0].position_.y <= elim_factor[k]
2341 && triangle_vertices[1].position_.y <= elim_factor[k]
2342 && triangle_vertices[2].position_.y <= elim_factor[k]) {
2343 for(
const auto& smv : triangle_vertices) {
2344 static_mesh_vertex tmp = smv;
2345 tmp.position_ *= scaling_factor[k];
2346 static_mesh_vertices.push_back(tmp);
2351 vertex_offset += sub.num_vertices;
2354 auto const& mat = context.materials[sub.material_id];
2356 if(layer.texture.empty()) {
2379 state.map_state.map_data.static_mesh_starts[k] = GLint(old_size);
2380 state.map_state.map_data.static_mesh_counts[k] = GLsizei(static_mesh_vertices.size() - old_size);
2382 state.map_state.map_data.static_mesh_starts[k] = GLint(old_size);
2383 state.map_state.map_data.static_mesh_counts[k] = GLsizei(0);
2387 if(!static_mesh_vertices.empty()) {
2388 glBindBuffer(GL_ARRAY_BUFFER, state.map_state.map_data.vbo_array[state.map_state.map_data.vo_static_mesh]);
2389 glBufferData(GL_ARRAY_BUFFER,
sizeof(static_mesh_vertex) * static_mesh_vertices.size(), &static_mesh_vertices[0], GL_STATIC_DRAW);
2391 glBindVertexArray(state.map_state.map_data.vao_array[state.map_state.map_data.vo_static_mesh]);
2392 glBindVertexBuffer(0, state.map_state.map_data.vbo_array[state.map_state.map_data.vo_static_mesh], 0,
sizeof(static_mesh_vertex));
2393 glVertexAttribFormat(0, 3, GL_FLOAT, GL_FALSE, offsetof(static_mesh_vertex, position_));
2394 glVertexAttribFormat(1, 2, GL_FLOAT, GL_FALSE, offsetof(static_mesh_vertex, normal_));
2395 glVertexAttribFormat(2, 2, GL_FLOAT, GL_FALSE, offsetof(static_mesh_vertex, texture_coord_));
2396 glEnableVertexAttribArray(0);
2397 glEnableVertexAttribArray(1);
2398 glEnableVertexAttribArray(2);
2399 glVertexAttribBinding(0, 0);
2400 glVertexAttribBinding(1, 0);
2401 glVertexAttribBinding(2, 0);
2402 glBindVertexArray(0);
2423 glTexStorage2D(GL_TEXTURE_2D, 1, GL_R8UI,
size_x,
size_y);
2425 glBindTexture(GL_TEXTURE_2D, 0);
2433 auto texturesheet = open_file(map_terrain_dir,
NATIVE(
"texturesheet.tga"));
2435 texturesheet = open_file(map_terrain_dir,
NATIVE(
"texturesheet.dds"));
2492 glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 256, 256, 2);
2498 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 256, 256);
2504 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 256, 256);
2510 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 256, 256);
2513 for(
auto p : state.world.in_province) {
2514 if(p.id.index() >= state.province_definitions.first_sea_province.index()) {
2523 glBindTexture(GL_TEXTURE_2D, 0);
2525 uint32_t province_size = state.world.province_size() + 1;
2526 province_size += 256 - province_size % 256;
2528 std::vector<uint32_t> test_highlight(province_size);
2530 for(
uint32_t i = 0; i < test_highlight.size(); ++i) {
2531 test_highlight[i] = 255;
2533 std::vector<uint32_t> test_color(province_size * 4);
2534 for(
uint32_t i = 0; i < test_color.size(); ++i) {
2535 test_color[i] = 255;
std::vector< textured_line_with_width_vertex > river_vertices
static constexpr uint32_t texture_diag_border_identifier
static constexpr uint32_t uniform_texture_sampler
void update_railroad_paths(sys::state &state)
static constexpr uint32_t uniform_colormap_water
static constexpr uint32_t shader_textured_line
static constexpr uint32_t texture_strategy_unit_arrow
std::vector< GLsizei > river_counts
void load_shaders(simple_fs::directory &root)
static constexpr uint32_t texture_array_province_color
GLuint texture_arrays[texture_array_count]
static constexpr uint32_t uniform_rotation
static constexpr uint32_t uniform_overlay
static constexpr uint32_t texture_sea_mask
static constexpr uint32_t vo_coastal
std::vector< GLsizei > coastal_counts
void update_fog_of_war(sys::state &state)
GLuint vao_array[vo_count]
static constexpr uint32_t uniform_water_normal
static constexpr uint32_t uniform_stripes_texture
static constexpr uint32_t texture_colormap_water
static constexpr uint32_t texture_coastal_border
std::vector< GLint > coastal_starts
std::vector< text_line_vertex > province_text_line_vertices
std::vector< GLsizei > static_mesh_counts
std::vector< curved_line_vertex > retreat_unit_arrow_vertices
static constexpr uint32_t shader_map_standing_object
void load_map(sys::state &state)
void set_selected_province(sys::state &state, dcon::province_id province_id)
static constexpr uint32_t shader_count
std::vector< GLuint > text_line_texture_per_quad
static constexpr uint32_t shader_text_line
std::vector< text_line_vertex > text_line_vertices
static constexpr uint32_t uniform_diag_border_identifier
static constexpr uint32_t texture_imp_border
static constexpr uint32_t vo_count
static constexpr uint32_t texture_province_fow
static constexpr uint32_t uniform_provinces_sea_mask
std::vector< GLsizei > strategy_unit_arrow_counts
static constexpr uint32_t uniform_opaque
static constexpr uint32_t texture_national_border
static constexpr uint32_t vo_land
static constexpr uint32_t vo_objective_unit_arrow
static constexpr uint32_t texture_hover_border
static constexpr uint32_t uniform_border_width
std::vector< border > borders
static constexpr uint32_t shader_line_unit_arrow
static constexpr uint32_t vo_province_text_line
std::vector< curved_line_vertex > attack_unit_arrow_vertices
static constexpr uint32_t vo_unit_arrow
std::vector< GLint > objective_unit_arrow_starts
static constexpr uint32_t shader_railroad_line
std::vector< GLint > river_starts
static constexpr uint32_t uniform_province_highlight
static constexpr uint32_t texture_unit_arrow
void set_province_text_lines(sys::state &state, std::vector< text_line_generator_data > const &data)
std::vector< uint16_t > province_id_map
static constexpr uint32_t uniform_province_color
std::vector< uint8_t > diagonal_borders
void gen_prov_color_texture(GLuint texture_handle, std::vector< uint32_t > const &prov_color, uint8_t layers=1)
std::vector< textured_line_vertex_b > border_vertices
std::vector< curved_line_vertex > other_objective_unit_arrow_vertices
std::vector< GLint > static_mesh_starts
static constexpr uint32_t texture_prov_border
std::vector< GLsizei > other_objective_unit_arrow_counts
static constexpr uint32_t texture_terrain
GLuint static_mesh_textures[max_static_meshes]
std::vector< uint16_t > map_indices
static constexpr uint32_t vo_drag_box
static constexpr uint32_t vo_border
static constexpr uint32_t texture_overlay
std::vector< curved_line_vertex > unit_arrow_vertices
std::vector< GLsizei > retreat_unit_arrow_counts
std::vector< curved_line_vertex > strategy_unit_arrow_vertices
static constexpr uint32_t uniform_colormap_terrain
static constexpr uint32_t uniform_aspect_ratio
void update_borders(sys::state &state)
static constexpr uint32_t uniform_time
std::vector< textured_line_vertex_b > coastal_vertices
static constexpr uint32_t uniform_province_fow
static constexpr uint32_t uniform_offset
static constexpr uint32_t vo_attack_unit_arrow
static constexpr uint32_t uniform_terrain_texture_sampler
static constexpr uint32_t vo_other_objective_unit_arrow
std::vector< GLint > retreat_unit_arrow_starts
static constexpr uint32_t uniform_zoom
static constexpr uint32_t texture_array_terrainsheet
std::vector< uint8_t > terrain_id_map
static constexpr uint32_t texture_stripes
static constexpr uint32_t uniform_width
std::vector< GLsizei > objective_unit_arrow_counts
static constexpr uint32_t texture_retreat_unit_arrow
static constexpr uint32_t uniform_is_black
static constexpr uint32_t uniform_subroutines_index_2
static constexpr uint32_t max_static_meshes
GLuint shader_uniforms[shader_count][uniform_count]
static constexpr uint32_t uniform_target_topview_fixup
static constexpr uint32_t texture_provinces
static constexpr uint32_t vo_static_mesh
static constexpr uint32_t uniform_map_size
static constexpr uint32_t texture_railroad
GLuint shaders[shader_count]
static constexpr uint32_t vo_railroad
static constexpr uint32_t texture_water_normal
std::vector< GLint > attack_unit_arrow_starts
std::vector< GLsizei > unit_arrow_counts
static constexpr uint32_t texture_other_objective_unit_arrow
static constexpr uint32_t uniform_target_facing
static constexpr uint32_t shader_borders
void render(sys::state &state, glm::vec2 screen_size, glm::vec2 offset, float zoom, map_view map_view_mode, map_mode::mode active_map_mode, glm::mat3 globe_rotation, float time_counter)
static constexpr uint32_t uniform_line_texture
static constexpr uint32_t texture_objective_unit_arrow
static constexpr uint32_t vo_retreat_unit_arrow
void set_text_lines(sys::state &state, std::vector< text_line_generator_data > const &data)
static constexpr uint32_t uniform_gamma
void create_border_ogl_objects()
static constexpr uint32_t vo_strategy_unit_arrow
static constexpr uint32_t uniform_model_offset
static constexpr uint32_t texture_attack_unit_arrow
static constexpr uint32_t texture_province_highlight
uint32_t land_vertex_count
GLuint vbo_array[vo_count]
std::vector< GLint > railroad_starts
std::vector< GLsizei > attack_unit_arrow_counts
std::vector< GLint > strategy_unit_arrow_starts
std::vector< GLint > unit_arrow_starts
static constexpr uint32_t texture_river_body
static constexpr uint32_t uniform_subroutines_index
std::vector< GLint > other_objective_unit_arrow_starts
static constexpr uint32_t shader_drag_box
static constexpr uint32_t uniform_colormap_political
void set_drag_box(bool draw_box, glm::vec2 pos1, glm::vec2 pos2, glm::vec2 pixel_size)
static constexpr uint32_t uniform_provinces_texture_sampler
static constexpr uint32_t texture_count
std::vector< screen_vertex > drag_box_vertices
static constexpr uint32_t vo_river
GLuint textures[texture_count]
std::vector< uint32_t > province_id_sea_mask
static constexpr uint32_t vo_text_line
static constexpr uint32_t texture_colormap_terrain
std::vector< GLsizei > railroad_counts
std::vector< curved_line_vertex > objective_unit_arrow_vertices
void set_province_color(std::vector< uint32_t > const &prov_color)
static constexpr uint32_t shader_textured_line_with_variable_width
static constexpr uint32_t uniform_terrainsheet_texture_sampler
static constexpr uint32_t texture_colormap_political
static constexpr uint32_t texture_state_border
std::vector< textured_line_vertex > railroad_vertices
static constexpr uint32_t uniform_unit_arrow
static constexpr uint32_t shader_terrain
#define assert(condition)
pop_satisfaction_wrapper_fat fatten(data_container const &c, pop_satisfaction_wrapper_id id) noexcept
constexpr dcon::demographics_key total(0)
glm::vec2 get_navy_location(sys::state &state, dcon::province_id prov_id)
bool is_sea_province(sys::state &state, dcon::province_id prov_id)
glm::vec2 get_army_location(sys::state &state, dcon::province_id prov_id)
glm::vec2 get_port_location(sys::state &state, dcon::province_id p)
void parse_xac(xac_context &context, const char *start, const char *end, parsers::error_handler &err)
void finish(xac_context &context)
constexpr float zoom_close
glm::vec2 put_in_local(glm::vec2 new_point, glm::vec2 base_point, float size_x)
void create_railroad_connection(sys::state &state, std::vector< glm::vec2 > &railroad, dcon::province_id p1, dcon::province_id p2)
GLuint create_program(simple_fs::file &vshader_file, simple_fs::file &fshader_file)
void make_army_path(sys::state &state, std::vector< map::curved_line_vertex > &buffer, dcon::army_id selected_army, float size_x, float size_y)
GLuint load_dds_texture(simple_fs::directory const &dir, native_string_view file_name, int soil_flags=ogl::SOIL_FLAG_TEXTURE_REPEATS)
void load_static_meshes(sys::state &state)
std::optional< simple_fs::file > try_load_shader(simple_fs::directory &root, native_string_view name)
emfx::xac_pp_actor_material_layer get_diffuse_layer(emfx::xac_pp_actor_material const &mat)
void add_bezier_to_buffer(std::vector< map::curved_line_vertex > &buffer, glm::vec2 start, glm::vec2 end, glm::vec2 start_per, glm::vec2 end_per, float progress, bool last_curve, float size_x, float size_y, uint32_t num_b_segments)
void create_unit_arrow_vbo(GLuint vbo, std::vector< curved_line_vertex > &data)
bool get_provinces_part_of_rr_path(sys::state &state, std::vector< bool > &visited_adj, std::vector< bool > &visited_prov, std::vector< dcon::province_id > &provinces, dcon::province_id p)
void create_drag_box_vbo(GLuint vbo)
void add_nation_visible_provinces(sys::state &state, std::vector< dcon::province_id > &list, dcon::nation_id n)
constexpr uint32_t default_num_b_segments
constexpr float control_point_length_factor
void make_navy_path(sys::state &state, std::vector< map::curved_line_vertex > &buffer, dcon::navy_id selected_navy, float size_x, float size_y)
void create_text_line_vbo(GLuint vbo)
constexpr float zoom_very_close
void create_textured_line_b_vbo(GLuint vbo, std::vector< textured_line_vertex_b > &data)
void create_textured_line_vbo(GLuint vbo, std::vector< textured_line_vertex > &data)
void add_tl_segment_buffer(std::vector< map::textured_line_vertex > &buffer, glm::vec2 start, glm::vec2 end, glm::vec2 next_normal_dir, float size_x, float size_y, float &distance)
void add_arrow_to_buffer(std::vector< map::curved_line_vertex > &buffer, glm::vec2 start, glm::vec2 end, glm::vec2 prev_normal_dir, glm::vec2 next_normal_dir, float fill_progress, bool end_arrow, float size_x, float size_y)
GLuint load_province_map(std::vector< uint16_t > &province_index, uint32_t size_x, uint32_t size_y)
void add_drag_box_line(std::vector< screen_vertex > &drag_box_vertices, glm::vec2 pos1, glm::vec2 pos2, glm::vec2 size, bool vertical)
void add_tl_bezier_to_buffer(std::vector< map::textured_line_vertex > &buffer, glm::vec2 start, glm::vec2 end, glm::vec2 start_per, glm::vec2 end_per, float progress, bool last_curve, float size_x, float size_y, uint32_t num_b_segments, float &distance)
float fractional_distance_covered(sys::state &state, dcon::army_id a)
bool province_is_blockaded(sys::state const &state, dcon::province_id ids)
GLuint make_gl_texture(uint8_t *data, uint32_t size_x, uint32_t size_y, uint32_t channels)
bool msaa_enabled(sys::state const &state)
GLuint load_texture_array_from_file(simple_fs::file &file, int32_t tiles_x, int32_t tiles_y)
void set_gltex_parameters(GLuint texture_handle, GLuint texture_type, GLuint filter, GLuint wrap)
GLuint create_program(std::string_view vertex_shader, std::string_view fragment_shader)
GLuint SOIL_direct_load_DDS_from_memory(unsigned char const *const buffer, uint32_t buffer_length, uint32_t &width, uint32_t &height, int soil_flags)
@ SOIL_FLAG_TEXTURE_REPEATS
void notify_user_of_fatal_opengl_error(std::string message)
constexpr uint8_t impassible_bit
constexpr uint8_t non_adjacent_bit
constexpr uint8_t state_bit
constexpr uint8_t national_bit
constexpr uint8_t coastal_bit
constexpr dcon::province_id from_map_id(uint16_t id)
float state_admin_efficiency(sys::state &state, dcon::state_instance_id id)
constexpr uint16_t to_map_id(dcon::province_id id)
uint32_t reduce(uint32_t value_in, uint32_t upper_bound)
uint64_t get_random(sys::state const &state, uint32_t value_in)
directory open_directory(directory const &dir, native_string_view directory_name)
native_string utf8_to_native(std::string_view data_in)
directory get_root(file_system const &fs)
native_string get_full_name(directory const &f)
std::optional< file > open_file(directory const &dir, native_string_view file_name)
std::string native_to_utf8(native_string_view data_in)
file_contents view_contents(file const &f)
constexpr int magnification_factor
constexpr uint32_t max_texture_layers
std::string_view native_string_view
std::string native_string
std::vector< xac_pp_actor_material_layer > layers