42bool extend_if_possible(
uint32_t x, int32_t border_id,
direction dir, std::vector<border_direction>& last_row, std::vector<border_direction>& current_row, glm::vec2 map_size, std::vector<curved_line_vertex>& border_vertices) {
49 direction_information = last_row[x].down;
52 direction_information = current_row[x].up;
55 direction_information = current_row[x - 1].right;
58 direction_information = current_row[x].left;
63 if(direction_information.
id != border_id)
66 auto border_index = direction_information.
index;
67 if(border_index == -1)
73 border_vertices[border_index + 2].position_.y += 0.5f / map_size.y;
74 border_vertices[border_index + 3].position_.y += 0.5f / map_size.y;
75 border_vertices[border_index + 4].position_.y += 0.5f / map_size.y;
79 border_vertices[border_index + 2].position_.x += 0.5f / map_size.x;
80 border_vertices[border_index + 3].position_.x += 0.5f / map_size.x;
81 border_vertices[border_index + 4].position_.x += 0.5f / map_size.x;
88 current_row[x].up = direction_information;
91 current_row[x].down = direction_information;
94 current_row[x].left = direction_information;
97 current_row[x].right = direction_information;
109 auto border_index = context.
state.
world.get_province_adjacency_by_province_pair(province_id1, province_id2);
111 border_index = context.
state.
world.force_create_province_adjacency(province_id1, province_id2);
112 if(!province_id1 || !province_id2) {
115 return border_index.index();
133 if(prov_id_ur == prov_id_ul && prov_id_dl == prov_id_ul && prov_id_dr != prov_id_ur) {
136 if(prov_id_ul == prov_id_dl && prov_id_dl == prov_id_dr && prov_id_ur != prov_id_dr) {
139 if(prov_id_ul == prov_id_ur && prov_id_ur == prov_id_dr && prov_id_dl != prov_id_ul) {
142 if(prov_id_dl == prov_id_dr && prov_id_ur == prov_id_dr && prov_id_ul != prov_id_dl) {
145 if(prov_id_ul == prov_id_dr && prov_id_ur == prov_id_dl && prov_id_ul != prov_id_ur) {
160 if(prov_id_ul != prov_id_ur || prov_id_ul != prov_id_dl || prov_id_ul != prov_id_dr) {
161 if(prov_id_ul != prov_id_ur && prov_id_ur != 0 && prov_id_ul != 0) {
169 if(prov_id_ul != prov_id_dl && prov_id_dl != 0 && prov_id_ul != 0) {
177 if(prov_id_ul != prov_id_dr && prov_id_dr != 0 && prov_id_ul != 0) {
195 if(prov_id_ur == prov_id_ul && prov_id_dl == prov_id_ul && prov_id_dr != prov_id_ur) {
198 if(prov_id_ul == prov_id_dl && prov_id_dl == prov_id_dr && prov_id_ur != prov_id_dr) {
201 if(prov_id_ul == prov_id_ur && prov_id_ur == prov_id_dr && prov_id_dl != prov_id_ul) {
204 if(prov_id_dl == prov_id_dr && prov_id_ur == prov_id_dr && prov_id_ul != prov_id_dl) {
207 if(prov_id_ul == prov_id_dr && prov_id_ur == prov_id_dl && prov_id_ul != prov_id_ur) {
222 if(prov_id_ul != prov_id_ur || prov_id_ul != prov_id_dl || prov_id_ul != prov_id_dr) {
224 if(prov_id_ul != prov_id_ur && prov_id_ur != 0 && prov_id_ul != 0) {
227 if(prov_id_ul != prov_id_dl && prov_id_dl != 0 && prov_id_ul != 0) {
230 if(prov_id_ul != prov_id_dr && prov_id_dr != 0 && prov_id_ul != 0) {
239 return river_data < 250;
242 auto result = 255 - (int32_t)(river_data) + 40;
247 return river_data == 0;
250 return river_data == 1;
257 while(pt.x >= int32_t(
size_x)) {
263 if(pt.y >= int32_t(
size_y)) {
264 pt.y = int32_t(
size_y - 1);
270 bool a_sea = a == 0 ||
province::from_map_id(a).index() >= state.province_definitions.first_sea_province.index();
271 bool b_sea = b == 0 ||
province::from_map_id(b).index() >= state.province_definitions.first_sea_province.index();
272 return a_sea != b_sea;
276 return (a == c && b == d) || (a == d && b == c);
280 std::vector<glm::vec2> points;
282 auto add_next = [&](int32_t i, int32_t j,
bool& next_found) {
284 return glm::ivec2(0, 0);
285 if(visited[i + j * dat.
size_x])
286 return glm::ivec2(0, 0);
289 visited[i + j * dat.
size_x] =
true;
291 points.push_back(glm::vec2(
float(i), 0.5f +
float(j) / 2.0f));
293 return glm::ivec2(i, j);
297 visited[i + j * dat.
size_x] =
true;
299 points.push_back(glm::vec2(
float(i) + 0.5f, 0.5f +
float(j) / 2.0f));
301 return glm::ivec2(i, j);
305 return glm::ivec2(0, 0);
309 points.push_back(glm::vec2(
float(start_x) + (start_y % 2 == 0 ? 0.0f : 0.5f), 0.5f +
float(start_y) / 2.0f));
310 visited[start_x + start_y * dat.
size_x] =
true;
312 int32_t cur_x = start_x;
313 int32_t cur_y = start_y;
315 bool progress =
false;
319 glm::ivec2 temp{ 0, 0 };
322 bool left_is_s = dat.
safe_get_province(glm::ivec2(cur_x - 1, cur_y / 2)) == prov_sec;
324 temp += add_next(cur_x, cur_y + 1, progress);
325 temp += add_next(cur_x, cur_y + 2, progress);
326 temp += add_next(cur_x - 1, cur_y + 1, progress);
328 temp += add_next(cur_x - 1, cur_y - 1, progress);
329 temp += add_next(cur_x, cur_y - 2, progress);
330 temp += add_next(cur_x, cur_y - 1, progress);
335 temp += add_next(cur_x, cur_y + 1, progress);
336 temp += add_next(cur_x - 1, cur_y, progress);
337 temp += add_next(cur_x, cur_y - 1, progress);
339 temp += add_next(cur_x + 1, cur_y - 1, progress);
340 temp += add_next(cur_x + 1, cur_y, progress);
341 temp += add_next(cur_x + 1, cur_y + 1, progress);
352 bool left_is_s = dat.
safe_get_province(glm::ivec2(cur_x - 1, cur_y / 2)) == prov_sec;
354 points.push_back(glm::vec2(
float(cur_x), 1.0f +
float(cur_y) / 2.0f));
356 points.push_back(glm::vec2(
float(cur_x), 0.0f +
float(cur_y) / 2.0f));
361 points.push_back(glm::vec2(
float(cur_x), 0.5f +
float(cur_y) / 2.0f));
363 points.push_back(glm::vec2(1.0f +
float(cur_x), 0.5f +
float(cur_y) / 2.0f));
370 std::reverse(points.begin(), points.end());
375 glm::ivec2 temp{ 0, 0 };
378 bool left_is_s = dat.
safe_get_province(glm::ivec2(cur_x - 1, cur_y / 2)) == prov_sec;
380 temp += add_next(cur_x, cur_y + 1, progress);
381 temp += add_next(cur_x, cur_y + 2, progress);
382 temp += add_next(cur_x - 1, cur_y + 1, progress);
384 temp += add_next(cur_x - 1, cur_y - 1, progress);
385 temp += add_next(cur_x, cur_y - 2, progress);
386 temp += add_next(cur_x, cur_y - 1, progress);
391 temp += add_next(cur_x, cur_y + 1, progress);
392 temp += add_next(cur_x - 1, cur_y, progress);
393 temp += add_next(cur_x, cur_y - 1, progress);
395 temp += add_next(cur_x + 1, cur_y - 1, progress);
396 temp += add_next(cur_x + 1, cur_y, progress);
397 temp += add_next(cur_x + 1, cur_y + 1, progress);
408 bool left_is_s = dat.
safe_get_province(glm::ivec2(cur_x - 1, cur_y / 2)) == prov_sec;
410 points.push_back(glm::vec2(
float(cur_x), 1.0f +
float(cur_y) / 2.0f));
412 points.push_back(glm::vec2(
float(cur_x), 0.0f +
float(cur_y) / 2.0f));
417 points.push_back(glm::vec2(
float(cur_x), 0.5f +
float(cur_y) / 2.0f));
419 points.push_back(glm::vec2(1.0f +
float(cur_x), 0.5f +
float(cur_y) / 2.0f));
427 if(points.size() < 3)
432 glm::vec2 current_pos = glm::vec2(points.back().x, points.back().y);
433 glm::vec2 next_pos =
put_in_local(glm::vec2(points[points.size() - 2].x, points[points.size() - 2].y), current_pos,
float(dat.
size_x));
435 float distance = 0.0f;
438 auto norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
441 old_pos = 2.0f * current_pos - next_pos;
446 raw_dist = (current_pos - next_pos) / glm::vec2(dat.
size_x, dat.
size_y);
448 distance += 0.5f * glm::length(raw_dist);
451 for(
auto i = points.size() - 1; i-- > 1; ) {
452 old_pos = current_pos;
453 current_pos = glm::vec2(points[i].x, points[i].y);
455 next_pos =
put_in_local(glm::vec2(points[i - 1].x, points[i - 1].y), current_pos,
float(dat.
size_x));
456 auto next_direction = glm::normalize(next_pos - current_pos);
458 norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
463 raw_dist = (current_pos - next_pos) / glm::vec2(dat.
size_x, dat.
size_y);
465 distance += 0.5f * glm::length(raw_dist);
470 old_pos = current_pos;
471 current_pos = glm::vec2(points[0].x, points[0].y);
473 next_pos = 2.0f * current_pos - old_pos;
475 auto next_direction = glm::normalize(next_pos - current_pos);
477 norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
482 raw_dist = (current_pos - next_pos) / glm::vec2(dat.
size_x, dat.
size_y);
484 distance += 0.5f * glm::length(raw_dist);
491 borders.resize(state.world.province_adjacency_size());
492 for(
auto adj : state.world.in_province_adjacency) {
493 borders[adj.id.index()].adj = adj;
496 for(int32_t j = 0; j < int32_t(
size_y); ++j) {
497 for(int32_t i = 0; i < int32_t(
size_x); ++i) {
500 bool was_visited = visited[i + (j * 2) *
size_x];
505 if(!was_visited && prim != sec && prim && sec) {
506 auto adj = state.world.get_province_adjacency_by_province_pair(prim, sec);
508 int32_t border_index = adj.index();
509 if(
borders[border_index].count != 0) {
510 border_index = int32_t(
borders.size());
525 if(j < int32_t(
size_y) - 1) {
526 bool was_visited = visited[i + (j * 2 + 1) *
size_x];
530 if(!was_visited && prim != sec && prim && sec) {
531 auto adj = state.world.get_province_adjacency_by_province_pair(prim, sec);
533 int32_t border_index = adj.index();
534 if(
borders[border_index].count != 0) {
535 border_index = int32_t(
borders.size());
553 std::vector<glm::vec2> points;
555 int32_t dropped_points_counter = 0;
556 constexpr int32_t dropped_points_max = 64;
558 auto add_next = [&](int32_t i, int32_t j,
bool& next_found) {
560 return glm::ivec2(0, 0);
561 if(visited[i + j * dat.
size_x])
562 return glm::ivec2(0, 0);
565 visited[i + j * dat.
size_x] =
true;
570 if(points.size() > 2) {
571 auto l = points[points.size() - 1];
572 auto n = points[points.size() - 2];
573 if(dropped_points_counter < dropped_points_max &&
574 std::sqrt((l.x - n.x) * (l.x - n.x) + (l.y - n.y) * (l.y - n.y)) + std::sqrt((l.x -
float(i)) * (l.x -
float(i)) + (l.y - 0.5f -
float(j) / 2.0f) * (l.y - 0.5f -
float(j) / 2.0f))
575 == std::sqrt((n.x -
float(i)) * (n.x -
float(i)) + (n.y - 0.5f -
float(j) / 2.0f) * (n.y - 0.5f -
float(j) / 2.0f))) {
576 ++dropped_points_counter;
579 dropped_points_counter = 0;
583 points.push_back(glm::vec2(
float(i), 0.5f +
float(j) / 2.0f));
585 return glm::ivec2(i, j);
589 visited[i + j * dat.
size_x] =
true;
594 if(points.size() > 2) {
595 auto l = points[points.size() - 1];
596 auto n = points[points.size() - 2];
597 if(dropped_points_counter < dropped_points_max &&
598 std::sqrt((l.x - n.x) * (l.x - n.x) + (l.y - n.y) * (l.y - n.y)) + std::sqrt((l.x - 0.5f -
float(i)) * (l.x - 0.5f -
float(i)) + (l.y - 0.5f -
float(j) / 2.0f) * (l.y - 0.5f -
float(j) / 2.0f))
599 == std::sqrt((n.x - 0.5f -
float(i)) * (n.x - 0.5f -
float(i)) + (n.y - 0.5f -
float(j) / 2.0f) * (n.y - 0.5f -
float(j) / 2.0f))) {
600 ++dropped_points_counter;
603 dropped_points_counter = 0;
607 points.push_back(glm::vec2(
float(i) + 0.5f, 0.5f +
float(j) / 2.0f));
609 return glm::ivec2(i, j);
613 return glm::ivec2(0, 0);
616 points.push_back(glm::vec2(
float(start_x) + (start_y % 2 == 0 ? 0.0f : 0.5f), 0.5f +
float(start_y) / 2.0f));
617 visited[start_x + start_y * dat.
size_x] =
true;
619 bool progress =
false;
622 glm::ivec2 temp{ 0, 0 };
624 if(start_y % 2 == 0) {
627 temp += add_next(start_x, start_y + 1, progress);
628 temp += add_next(start_x, start_y + 2, progress);
629 temp += add_next(start_x - 1, start_y + 1, progress);
631 temp += add_next(start_x - 1, start_y - 1, progress);
632 temp += add_next(start_x, start_y - 2, progress);
633 temp += add_next(start_x, start_y - 1, progress);
638 temp += add_next(start_x, start_y + 1, progress);
639 temp += add_next(start_x - 1, start_y, progress);
640 temp += add_next(start_x, start_y - 1, progress);
642 temp += add_next(start_x + 1, start_y - 1, progress);
643 temp += add_next(start_x + 1, start_y, progress);
644 temp += add_next(start_x + 1, start_y + 1, progress);
657 if(points.size() < 3)
663 glm::vec2 current_pos = glm::vec2(points.back().x, points.back().y);
664 glm::vec2 next_pos =
put_in_local(glm::vec2(points[points.size() - 2].x, points[points.size() - 2].y), current_pos,
float(dat.
size_x));
665 glm::vec2 prev_direction = glm::normalize(next_pos - current_pos);
666 float distance = 0.0f;
668 auto norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
669 auto old_pos = glm::vec2{ 0,0 };
674 auto raw_dist = (current_pos - next_pos) / glm::vec2(dat.
size_x, dat.
size_y);
676 distance += glm::length(raw_dist);
678 for(
auto i = points.size() - 1; i-- > 1; ) {
679 old_pos = current_pos;
680 current_pos = glm::vec2(points[i].x, points[i].y);
682 next_pos =
put_in_local(glm::vec2(points[i - 1].x, points[i - 1].y), current_pos,
float(dat.
size_x));
683 auto next_direction = glm::normalize(next_pos - current_pos);
685 norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
690 raw_dist = (current_pos - next_pos) / glm::vec2(dat.
size_x, dat.
size_y);
692 distance += glm::length(raw_dist);
697 old_pos = current_pos;
698 current_pos = glm::vec2(points[0].x, points[0].y);
700 next_pos =
put_in_local(glm::vec2(points.back().x, points.back().y), current_pos,
float(dat.
size_x));
701 auto next_direction = glm::normalize(next_pos - current_pos);
703 norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
708 raw_dist = (current_pos - next_pos) / glm::vec2(dat.
size_x, dat.
size_y);
710 distance += glm::length(raw_dist);
716 old_pos = current_pos;
717 current_pos = glm::vec2(points.back().x, points.back().y);
719 next_pos =
put_in_local(glm::vec2(points[points.size() - 2].x, points[points.size() - 2].y), current_pos,
float(dat.
size_x));
720 auto next_direction = glm::normalize(next_pos - current_pos);
721 auto next_normal = glm::vec2(-next_direction.y, next_direction.x);
723 norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
736 for(int32_t j = 0; j < int32_t(
size_y); ++j) {
737 for(int32_t i = 0; i < int32_t(
size_x); ++i) {
740 bool was_visited = visited[i + (j * 2) *
size_x];
748 if(j < int32_t(
size_y) - 1) {
749 bool was_visited = visited[i + (j * 2 + 1) *
size_x];
764 world.for_each_province_adjacency([&](dcon::province_adjacency_id
id) {
766 auto prov_a = frel.get_connected_provinces(0);
767 auto prov_b = frel.get_connected_provinces(1);
769 if(!prov_a || !prov_b)
772 glm::vec2 mid_point_a = world.province_get_mid_point(prov_a.id);
773 glm::vec2 mid_point_b = world.province_get_mid_point(prov_b.id);
774 glm::ivec2 tile_pos_a = glm::round(mid_point_a);
775 glm::ivec2 tile_pos_b = glm::round(mid_point_b);
776 glm::ivec2 diff = glm::abs(tile_pos_a - tile_pos_b);
778 bool is_river_crossing =
false;
779 if(diff.x > diff.y) {
780 if(tile_pos_a.x > tile_pos_b.x)
781 std::swap(tile_pos_a, tile_pos_b);
782 int x_difference = std::max(tile_pos_b.x - tile_pos_a.x, 1);
783 int y_difference = tile_pos_a.y - tile_pos_b.y;
784 int min_y = std::min(tile_pos_a.y, tile_pos_b.y);
785 int max_y = std::max(tile_pos_a.y, tile_pos_b.y);
786 for(
int x = tile_pos_a.x; x <= tile_pos_b.x; x++) {
787 float t = float(x - tile_pos_a.x) / x_difference;
788 for(
int k = -2; k <= 2; k++) {
789 int y = tile_pos_b.y + int(y_difference * t) + k;
790 y = std::clamp(y, min_y, max_y);
793 is_river_crossing |=
is_river(river_data[x + y * map_size.x]);
795 if(is_river_crossing)
799 if(tile_pos_a.y > tile_pos_b.y)
800 std::swap(tile_pos_a, tile_pos_b);
801 int y_difference = std::max(tile_pos_b.y - tile_pos_a.y, 1);
802 int x_difference = tile_pos_a.x - tile_pos_b.x;
803 int min_x = std::min(tile_pos_a.x, tile_pos_b.x);
804 int max_x = std::max(tile_pos_a.x, tile_pos_b.x);
805 for(
int y = tile_pos_a.y; y <= tile_pos_b.y; y++) {
806 float t = float(y - tile_pos_a.y) / y_difference;
807 for(
int k = -2; k <= 2; k++) {
808 int x = tile_pos_b.x + int(x_difference * t) + k;
809 x = std::clamp(x, min_x, max_x);
812 is_river_crossing |=
is_river(river_data[x + y * map_size.x]);
814 if(is_river_crossing)
819 uint8_t& buffer = world.province_adjacency_get_type(
id);
820 if(is_river_crossing)
835 return x == other.x &&
y == other.y;
849 for(
uint8_t index = 0; index < vertex->children.size(); index++) {
850 auto child = vertex->children[index];
851 if((child->x -
float(x) - 0.5f) > 0.1f) {
854 if((child->y -
float(y) - 0.5f) > 0.1f) {
863 for(
uint8_t index = 0; index < vertex->parents.size(); index++) {
864 auto parent = vertex->parents[index];
865 if(abs(parent->x -
float(x) - 0.5f) > 0.1f) {
868 if(abs(parent->y -
float(y) - 0.5f) > 0.1f) {
890 if(
is_river(river_data[x + y * size.x])) {
899 std::vector<glm::ivec2> results;
901 results.push_back({ runner.
x + 1, runner.
y });
904 results.push_back({ runner.
x - 1, runner.
y });
907 results.push_back({ runner.
x, runner.
y + 1 });
910 results.push_back({ runner.
x, runner.
y - 1});
1041 std::vector<river_vertex> rivers;
1046 std::vector<river_vertex*> sources;
1047 std::vector<river_vertex*> mouths;
1048 std::map<uint32_t, river_vertex*> vertex_by_pixel_index = {};
1049 std::vector<river_runner> runners;
1050 std::vector<river_runner> new_runners;
1053 auto size = glm::ivec2(int32_t(
size_x), int32_t(
size_y));
1059 auto index = x + y *
size_x;
1062 sources.push_back(source);
1063 vertex_by_pixel_index[index] = source;
1065 runners.push_back(r);
1071 bool exists_running_runner =
true;
1075 while(exists_running_runner) {
1076 exists_running_runner =
false;
1078 for(
auto & item : new_runners) {
1079 runners.push_back(item);
1081 new_runners.clear();
1084 for(
auto & runner : runners) {
1091 if(potential_children.size() == 0) {
1094 for(int32_t i = -1; i <= 1; i++) {
1095 for(int32_t j = -1; j <= 1; j++) {
1096 auto x = (int32_t)runner.x + i;
1097 auto y = (int32_t)runner.y + j;
1112 bool is_sea = terrain_data[index] == 255;
1117 if(!vertex_by_pixel_index.contains(index)) {
1121 runner.position->
width * 2.f
1123 vertex_by_pixel_index[index] = new_river_vertex;
1124 new_river_vertex->
parents.push_back(runner.position);
1125 runner.position->children.push_back(new_river_vertex);
1135 mouths.push_back(runner.position);
1136 }
else if(runner.waiting_for_merge) {
1137 for(
auto target_coord : potential_children) {
1138 auto target_index = target_coord.x + target_coord.y *
size_x;
1139 if(vertex_by_pixel_index.contains(target_index)) {
1140 auto target_vertex = vertex_by_pixel_index[target_index];
1141 target_vertex->parents.push_back(runner.position);
1142 runner.position->children.push_back(target_vertex);
1143 runner.waiting_for_merge =
false;
1148 exists_running_runner =
true;
1150 runner.waiting_for_merge =
true;
1152 bool first_child =
true;
1157 for(
auto candidate : potential_children) {
1160 auto index = x + y *
size_x;
1161 auto width = float(
river_width(river_data[index]));
1164 if(potential_children.size() > 1) {
1167 width = runner.position->width;
1172 bool we_will_move_forward =
false;
1174 if(vertex_by_pixel_index.contains(index)) {
1175 new_river_vertex = vertex_by_pixel_index[index];
1182 vertex_by_pixel_index[index] = new_river_vertex;
1183 we_will_move_forward =
true;
1186 new_river_vertex->
parents.push_back(runner.position);
1187 runner.position->children.push_back(new_river_vertex);
1189 if(we_will_move_forward) {
1193 next_position = new_river_vertex;
1194 first_child =
false;
1196 river_runner r = { new_river_vertex, x, y,
false,
false };
1197 new_runners.push_back(r);
1204 if(next_position !=
nullptr) {
1207 runner.position = next_position;
1308 std::vector<river_vertex*> current_path = { };
1309 std::vector<river_vertex*> nodes_to_skip = { };
1311 current_path.clear();
1319 for(
auto source : sources) {
1321 if(source->children.size() == 0) {
1325 current_path.push_back(source);
1329 while(current_path.size() > 0) {
1330 auto current_node = current_path.back();
1334 bool has_confluence_further =
false;
1336 for(
auto potential_confluence : current_node->children) {
1338 potential_confluence->parents.size() > 1
1339 && potential_confluence->children.size() > 0
1341 has_confluence_further =
true;
1345 if(has_confluence_further) {
1348 auto backrunner = current_path[current_path.size() - 1];
1349 for(
int steps = 0; steps < 2; steps++) {
1350 if(current_path.size() - 1 - steps <= 0) {
1353 if(backrunner->parents.size() == 0) {
1356 nodes_to_skip.push_back(backrunner);
1357 backrunner = current_path[current_path.size() - 1 - steps];
1361 if(current_path.size() > 2) {
1362 auto prev_node = current_path[current_path.size() - 2];
1364 if(current_node->parents.size() > 1 && current_node->children.size() > 0) {
1367 skip_nodes_counter = 2;
1371 bool node_was_skipped =
false;
1372 if(current_node->children.size() == 1)
1373 if(current_node->parents.size() == 1)
1374 if(current_node->children[0]->parents.size() == 1)
1375 if(current_node->parents[0]->children.size() == 1) {
1376 assert(current_node->children[0]->parents[0] == current_node);
1377 assert(current_node->parents[0]->children[0] == current_node);
1378 if(current_path.size() % 3 == 0) {
1379 nodes_to_skip.push_back(current_node);
1380 node_was_skipped =
true;
1381 if(skip_nodes_counter > 0) {
1382 skip_nodes_counter -= 1;
1386 if(current_node->children.size() > 0)
1387 if(current_node->parents.size() > 0)
1388 if(!node_was_skipped && skip_nodes_counter > 0) {
1390 skip_nodes_counter -= 1;
1394 bool pop_back =
true;
1395 for(
auto candidate : current_node->children) {
1396 if(!candidate->skip_visited) {
1397 current_path.push_back(candidate);
1403 current_path.pop_back();
1409 std::vector<river_vertex*> parents;
1410 std::vector<river_vertex*> children;
1411 std::vector<river_vertex*> temp;
1412 for(
auto item : nodes_to_skip) {
1417 for(
auto child : item->children) {
1418 children.push_back(child);
1421 for(
auto parent : item->parents) {
1422 parents.push_back(parent);
1426 for(
auto parent : parents) {
1430 for(
auto parent_child : parent->children) {
1431 if(parent_child->x == item->x)
1432 if(parent_child->y == item->y)
1434 temp.push_back(parent_child);
1437 for(
auto child_to_attach : children) {
1439 bool skip_child =
false;
1440 for(
auto parent_child : parent->children) {
1441 if(parent_child->x == child_to_attach->x)
1442 if(parent_child->y == child_to_attach->y) {
1451 temp.push_back(child_to_attach);
1455 parent->children.clear();
1457 for(
auto saved_item : temp) {
1458 parent->children.push_back(saved_item);
1463 for(
auto child : children) {
1467 for(
auto child_parent : child->parents) {
1468 if(child_parent->x == item->x)
1469 if(child_parent->y == item->y)
1471 temp.push_back(child_parent);
1474 for(
auto parent_to_attach : parents) {
1476 bool skip_parent =
false;
1477 for(
auto child_parent : child->parents) {
1478 if(child_parent->x == parent_to_attach->x)
1479 if(child_parent->y == parent_to_attach->y) {
1488 temp.push_back(parent_to_attach);
1492 child->parents.clear();
1494 for(
auto saved_item : temp) {
1496 child->parents.push_back(saved_item);
1500 item->children.clear();
1501 item->parents.clear();
1511 current_path.clear();
1512 std::vector<glm::vec2> vertex_stabilized_history;
1513 vertex_stabilized_history.clear();
1515 for(
auto source : sources) {
1517 if(source->children.size() == 0) {
1521 current_path.push_back(source);
1522 vertex_stabilized_history.push_back({ source->x, source->y });
1526 while(current_path.size() > 0) {
1529 bool can_start_here =
false;
1534 can_start_here =
true;
1537 while(!can_start_here) {
1538 if(current_path.size() == 0) {
1542 runner = current_path.back();
1543 current_path.pop_back();
1544 vertex_stabilized_history.pop_back();
1546 for(
auto child : runner->
children) {
1547 if(child->visited) {
1551 can_start_here =
true;
1555 if(!can_start_here) {
1566 float distance = 0.0f;
1571 glm::vec2 vertex = { runner->
x, runner->
y };
1572 glm::vec2 vertex_stabilized = vertex;
1573 if(vertex_stabilized_history.size() > 0) {
1574 vertex_stabilized = vertex_stabilized_history.back();
1576 glm::vec2 vertex_stabilized_speed = { 0.f, 0.f };
1577 float friction = 0.932f;
1579 float weight = 0.005f;
1583 bool can_continue =
true;
1584 while(can_continue) {
1587 can_continue =
false;
1592 for(
auto candidate : runner->
children) {
1593 if(candidate->visited) {
1594 can_continue =
true;
1595 next_node = candidate;
1598 next_node = candidate;
1599 can_continue =
true;
1613 if(next_node->
children.size() == 0) {
1614 can_continue =
false;
1617 auto current_point = glm::vec2(runner->
x, runner->
y);
1618 auto next_point = glm::vec2(next_node->
x, next_node->
y);
1620 auto current_tangent = glm::normalize(next_point - current_point);
1621 next_point = next_point + current_tangent * 5.f;
1622 auto current_normal = glm::vec2{ -current_tangent.y, current_tangent.x };
1623 auto next_tangent = glm::normalize(current_tangent);
1625 for(
uint8_t step = 0; step <= steps; step++) {
1626 auto t = (float(step) / float(steps));
1629 + (1.f - t) * current_point;
1630 auto width = t * next_node->
width + (1.f - t) * runner->
width;
1632 auto current_weight = weight * width;
1634 auto acceleration = (vertex - vertex_stabilized) / current_weight;
1635 vertex_stabilized_speed += acceleration;
1636 vertex_stabilized_speed *= (1.f - friction * 0.9f);
1638 auto vertex_old_opengl_coords = vertex_stabilized / glm::vec2(
size_x,
size_y);
1639 vertex_stabilized = vertex_stabilized + vertex_stabilized_speed;
1640 auto vertex_opengl_coords = vertex_stabilized / glm::vec2(
size_x,
size_y);
1641 auto speed_opengl_coords = vertex_opengl_coords - vertex_old_opengl_coords;
1642 auto normal_opengl_coords = glm::normalize(glm::vec2{ -speed_opengl_coords.y, speed_opengl_coords.x });
1643 distance += glm::length(speed_opengl_coords);
1674 auto current_point = glm::vec2(runner->
x, runner->
y);
1675 auto next_point = glm::vec2(next_node->
x, next_node->
y);
1676 auto next_next_point = glm::vec2(next_next_node->
x, next_next_node->
y);
1678 auto current_tangent = next_point - current_point;
1679 auto next_tangent = next_next_point - next_point;
1681 for(
uint8_t step = 0; step <= steps; step++) {
1682 auto t = (float(step) / float(steps));
1685 + (1.f - t) * current_point;
1686 auto width = t * next_node->
width + (1.f - t) * runner->
width;
1688 auto current_weight = weight * width;
1690 auto acceleration = (vertex - vertex_stabilized) / current_weight;
1691 vertex_stabilized_speed += acceleration;
1692 vertex_stabilized_speed *= (1.f - friction);
1694 auto vertex_old_opengl_coords = vertex_stabilized / glm::vec2(
size_x,
size_y);
1695 vertex_stabilized = vertex_stabilized + vertex_stabilized_speed;
1696 auto vertex_opengl_coords = vertex_stabilized / glm::vec2(
size_x,
size_y);
1697 auto speed_opengl_coords = vertex_opengl_coords - vertex_old_opengl_coords;
1698 auto normal_opengl_coords = glm::normalize(glm::vec2{ -speed_opengl_coords.y, speed_opengl_coords.x });
1699 distance += glm::length(speed_opengl_coords);
1727 if(count_back == 0) {
1734 current_path.push_back(runner);
1735 vertex_stabilized_history.push_back( vertex_stabilized );
1742 glm::vec2 current_pos = glm::vec2(source->x, source->y);
1743 glm::vec2 next_pos = glm::vec2(0, 0);
std::vector< textured_line_with_width_vertex > river_vertices
std::vector< GLsizei > river_counts
std::vector< GLsizei > coastal_counts
std::vector< GLint > coastal_starts
uint16_t safe_get_province(glm::ivec2 pt)
std::vector< border > borders
std::vector< GLint > river_starts
std::vector< uint16_t > province_id_map
std::vector< uint8_t > diagonal_borders
std::vector< textured_line_vertex_b > border_vertices
std::vector< textured_line_vertex_b > coastal_vertices
void make_coastal_borders(sys::state &state, std::vector< bool > &visited)
void load_border_data(parsers::scenario_building_context &context)
void make_borders(sys::state &state, std::vector< bool > &visited)
void create_curved_river_vertices(parsers::scenario_building_context &context, std::vector< uint8_t > const &river_data, std::vector< uint8_t > const &terrain_data)
#define assert(condition)
pop_satisfaction_wrapper_fat fatten(data_container const &c, pop_satisfaction_wrapper_id id) noexcept
glm::vec2 put_in_local(glm::vec2 new_point, glm::vec2 base_point, float size_x)
bool is_river_merge(uint8_t river_data)
bool is_river_source(uint8_t river_data)
int32_t river_width(uint8_t river_data)
bool check_for_river(std::vector< uint8_t > const &river_data, river_runner &runner, int32_t x, int32_t y, glm::ivec2 size)
std::vector< glm::vec2 > make_border_section(display_data &dat, sys::state &state, std::vector< bool > &visited, uint16_t prov_prim, uint16_t prov_sec, int32_t start_x, int32_t start_y)
int32_t get_border_index(uint16_t map_province_id1, uint16_t map_province_id2, parsers::scenario_building_context &context)
bool check_for_parent(river_vertex *vertex, uint32_t x, uint32_t y)
bool coastal_point(sys::state &state, uint16_t a, uint16_t b)
std::vector< glm::vec2 > make_coastal_loop(display_data &dat, sys::state &state, std::vector< bool > &visited, int32_t start_x, int32_t start_y)
bool check_for_child(river_vertex *vertex, uint32_t x, uint32_t y)
void add_border_segment_vertices(display_data &dat, std::vector< glm::vec2 > const &points)
std::vector< glm::ivec2 > check_for_potential_child(std::vector< uint8_t > const &river_data, river_runner &runner, glm::ivec2 size)
bool order_indifferent_compare(uint16_t a, uint16_t b, uint16_t c, uint16_t d)
void add_coastal_loop_vertices(display_data &dat, std::vector< glm::vec2 > const &points)
bool extend_if_possible(uint32_t x, int32_t border_id, direction dir, std::vector< border_direction > &last_row, std::vector< border_direction > ¤t_row, glm::vec2 map_size, std::vector< curved_line_vertex > &border_vertices)
void load_river_crossings(parsers::scenario_building_context &context, std::vector< uint8_t > const &river_data, glm::ivec2 map_size)
bool is_river(uint8_t river_data)
constexpr uint8_t impassible_bit
constexpr uint8_t non_adjacent_bit
constexpr uint8_t river_crossing_bit
constexpr dcon::province_id from_map_id(uint16_t id)
constexpr uint16_t to_map_id(dcon::province_id id)
std::vector< river_vertex * > parents
bool operator==(const river_vertex &other)
std::vector< river_vertex * > children
dcon::province_id first_sea_province
dcon::data_container world
province::global_provincial_state province_definitions