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 = [&](glm::ivec2 prev, glm::ivec2 shift, glm::ivec2 prev_shift,
bool& next_found,
bool corner_candidate) {
284 return glm::ivec2(0, 0);
286 auto i = prev.x + shift.x;
287 auto j = prev.y + shift.y;
288 auto prev_i = prev.x;
289 auto prev_j = prev.y;
291 bool corner = corner_candidate && (shift.x != prev_shift.x) && (shift.y != prev_shift.y) && !(prev_shift.y == 0 && prev_shift.x == 0);
293 if(visited[i + j * dat.
size_x])
294 return glm::ivec2(0, 0);
297 visited[i + j * dat.
size_x] =
true;
300 float prev_x = float(prev_i) + 0.5f;
301 float prev_y = 0.5f + float(prev_j) / 2.0f;
303 float next_x = float(i);
304 float next_y = 0.5f + float(j) / 2.0f;
306 points.push_back(glm::vec2((prev_x + next_x) / 2.f, prev_y));
307 points.push_back(glm::vec2(next_x, (prev_y + next_y) / 2.f));
310 points.push_back(glm::vec2(
float(i), 0.5f +
float(j) / 2.0f));
312 return glm::ivec2(i, j);
316 visited[i + j * dat.
size_x] =
true;
319 float prev_x = float(prev_i);
320 float prev_y = 0.5f + float(prev_j) / 2.0f;
322 float next_x = float(i) + 0.5f;
323 float next_y = 0.5f + float(j) / 2.0f;
325 points.push_back(glm::vec2(prev_x, (prev_y + next_y) / 2.f));
326 points.push_back(glm::vec2((prev_x + next_x) / 2.f, next_y));
329 points.push_back(glm::vec2(
float(i) + 0.5f, 0.5f +
float(j) / 2.0f));
331 return glm::ivec2(i, j);
335 return glm::ivec2(0, 0);
339 points.push_back(glm::vec2(
float(start_x) + (start_y % 2 == 0 ? 0.0f : 0.5f), 0.5f +
float(start_y) / 2.0f));
340 visited[start_x + start_y * dat.
size_x] =
true;
342 glm::ivec2 current{ start_x, start_y };
343 glm::ivec2 prev_direction{ 0, 0 };
345 bool progress =
false;
349 glm::ivec2 temp{ 0, 0 };
351 if(current.y % 2 == 0) {
352 bool left_is_s = dat.
safe_get_province(glm::ivec2(current.x - 1, current.y / 2)) == prov_sec;
354 temp += add_next(current, { 0, 1 }, prev_direction, progress,
true);
355 temp += add_next(current, { 0, 2 }, prev_direction, progress,
false);
356 temp += add_next(current, { -1, 1 }, prev_direction, progress,
true);
358 temp += add_next(current, { -1, -1}, prev_direction, progress,
true);
359 temp += add_next(current, { 0, -2}, prev_direction, progress,
false);
360 temp += add_next(current, { 0, -1}, prev_direction, progress,
true);
363 bool top_is_s = dat.
safe_get_province(glm::ivec2(current.x, current.y / 2)) == prov_sec;
365 temp += add_next(current, { 0, 1 }, prev_direction, progress,
true);
366 temp += add_next(current, { -1, 0 }, prev_direction, progress,
false);
367 temp += add_next(current, { 0, -1}, prev_direction, progress,
true);
369 temp += add_next(current, { +1, -1}, prev_direction, progress,
true);
370 temp += add_next(current, { +1, 0}, prev_direction, progress,
false);
371 temp += add_next(current, { +1, +1}, prev_direction, progress,
true);
375 prev_direction = temp - current;
381 if(current.y % 2 == 0) {
382 bool left_is_s = dat.
safe_get_province(glm::ivec2(current.x - 1, current.y / 2)) == prov_sec;
384 points.push_back(glm::vec2(
float(current.x), 1.0f +
float(current.y) / 2.0f));
386 points.push_back(glm::vec2(
float(current.x), 0.0f +
float(current.y) / 2.0f));
389 bool top_is_s = dat.
safe_get_province(glm::ivec2(current.x, current.y / 2)) == prov_sec;
391 points.push_back(glm::vec2(
float(current.x), 0.5f +
float(current.y) / 2.0f));
393 points.push_back(glm::vec2(1.0f +
float(current.x), 0.5f +
float(current.y) / 2.0f));
399 prev_direction.x = 0;
400 prev_direction.y = 0;
402 std::reverse(points.begin(), points.end());
407 glm::ivec2 temp{ 0, 0 };
409 if(current.y % 2 == 0) {
410 bool left_is_s = dat.
safe_get_province(glm::ivec2(current.x - 1, current.y / 2)) == prov_sec;
412 temp += add_next(current, { 0, 1 }, prev_direction, progress,
true);
413 temp += add_next(current, { 0, 2 }, prev_direction, progress,
false);
414 temp += add_next(current, { -1, 1 }, prev_direction, progress,
true);
416 temp += add_next(current, { -1, -1 }, prev_direction, progress,
true);
417 temp += add_next(current, { 0, -2 }, prev_direction, progress,
false);
418 temp += add_next(current, { 0, -1 }, prev_direction, progress,
true);
421 bool top_is_s = dat.
safe_get_province(glm::ivec2(current.x, current.y / 2)) == prov_sec;
423 temp += add_next(current, { 0, 1 }, prev_direction, progress,
true);
424 temp += add_next(current, { -1, 0 }, prev_direction, progress,
false);
425 temp += add_next(current, { 0, -1 }, prev_direction, progress,
true);
427 temp += add_next(current, { +1, -1 }, prev_direction, progress,
true);
428 temp += add_next(current, { +1, 0 }, prev_direction, progress,
false);
429 temp += add_next(current, { +1, +1 }, prev_direction, progress,
true);
433 prev_direction = temp - current;
439 if(current.y % 2 == 0) {
440 bool left_is_s = dat.
safe_get_province(glm::ivec2(current.x - 1, current.y / 2)) == prov_sec;
442 points.push_back(glm::vec2(
float(current.x), 1.0f +
float(current.y) / 2.0f));
444 points.push_back(glm::vec2(
float(current.x), 0.0f +
float(current.y) / 2.0f));
447 bool top_is_s = dat.
safe_get_province(glm::ivec2(current.x, current.y / 2)) == prov_sec;
449 points.push_back(glm::vec2(
float(current.x), 0.5f +
float(current.y) / 2.0f));
451 points.push_back(glm::vec2(1.0f +
float(current.x), 0.5f +
float(current.y) / 2.0f));
459 if(points.size() < 3)
464 glm::vec2 current_pos = glm::vec2(points.back().x, points.back().y);
465 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));
467 float distance = 0.0f;
470 auto norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
473 old_pos = 2.0f * current_pos - next_pos;
478 raw_dist = (current_pos - next_pos) / glm::vec2(dat.
size_x, dat.
size_y);
480 distance += 0.5f * glm::length(raw_dist);
483 for(
auto i = points.size() - 1; i-- > 1; ) {
484 old_pos = current_pos;
485 current_pos = glm::vec2(points[i].x, points[i].y);
487 next_pos =
put_in_local(glm::vec2(points[i - 1].x, points[i - 1].y), current_pos,
float(dat.
size_x));
488 auto next_direction = glm::normalize(next_pos - current_pos);
490 norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
495 raw_dist = (current_pos - next_pos) / glm::vec2(dat.
size_x, dat.
size_y);
497 distance += 0.5f * glm::length(raw_dist);
502 old_pos = current_pos;
503 current_pos = glm::vec2(points[0].x, points[0].y);
505 next_pos = 2.0f * current_pos - old_pos;
507 auto next_direction = glm::normalize(next_pos - current_pos);
509 norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
514 raw_dist = (current_pos - next_pos) / glm::vec2(dat.
size_x, dat.
size_y);
516 distance += 0.5f * glm::length(raw_dist);
523 borders.resize(state.world.province_adjacency_size());
524 for(
auto adj : state.world.in_province_adjacency) {
525 borders[adj.id.index()].adj = adj;
528 for(int32_t j = 0; j < int32_t(
size_y); ++j) {
529 for(int32_t i = 0; i < int32_t(
size_x); ++i) {
532 bool was_visited = visited[i + (j * 2) *
size_x];
537 if(!was_visited && prim != sec && prim && sec) {
538 auto adj = state.world.get_province_adjacency_by_province_pair(prim, sec);
540 int32_t border_index = adj.index();
541 if(
borders[border_index].count != 0) {
542 border_index = int32_t(
borders.size());
557 if(j < int32_t(
size_y) - 1) {
558 bool was_visited = visited[i + (j * 2 + 1) *
size_x];
562 if(!was_visited && prim != sec && prim && sec) {
563 auto adj = state.world.get_province_adjacency_by_province_pair(prim, sec);
565 int32_t border_index = adj.index();
566 if(
borders[border_index].count != 0) {
567 border_index = int32_t(
borders.size());
585 std::vector<glm::vec2> points;
587 int32_t dropped_points_counter = 0;
588 constexpr int32_t dropped_points_max = 64;
590 auto add_next = [&](int32_t i, int32_t j,
bool& next_found, int32_t prev_i, int32_t prev_j,
bool corner) {
592 return glm::ivec2(0, 0);
593 if(visited[i + j * dat.
size_x])
594 return glm::ivec2(0, 0);
597 visited[i + j * dat.
size_x] =
true;
602 if(points.size() > 2 && !corner) {
603 auto l = points[points.size() - 1];
604 auto n = points[points.size() - 2];
605 if(dropped_points_counter < dropped_points_max &&
606 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))
607 == 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))) {
608 ++dropped_points_counter;
611 dropped_points_counter = 0;
616 float prev_x = float(prev_i) + 0.5f;
617 float prev_y = 0.5f + float(prev_j) / 2.0f;
619 float next_x = float(i);
620 float next_y = 0.5f + float(j) / 2.0f;
622 points.push_back(glm::vec2((prev_x + next_x) / 2.f, prev_y));
623 points.push_back(glm::vec2(next_x, (prev_y + next_y) / 2.f));
626 points.push_back(glm::vec2(
float(i), 0.5f +
float(j) / 2.0f));
628 return glm::ivec2(i, j);
632 visited[i + j * dat.
size_x] =
true;
637 if(points.size() > 2 && !corner) {
638 auto l = points[points.size() - 1];
639 auto n = points[points.size() - 2];
640 if(dropped_points_counter < dropped_points_max &&
641 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))
642 == 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))) {
643 ++dropped_points_counter;
646 dropped_points_counter = 0;
651 float prev_x = float(prev_i);
652 float prev_y = 0.5f + float(prev_j) / 2.0f;
654 float next_x = float(i) + 0.5f;
655 float next_y = 0.5f + float(j) / 2.0f;
657 points.push_back(glm::vec2(prev_x, (prev_y + next_y) / 2.f));
658 points.push_back(glm::vec2((prev_x + next_x) / 2.f, next_y));
661 points.push_back(glm::vec2(
float(i) + 0.5f, 0.5f +
float(j) / 2.0f));
663 return glm::ivec2(i, j);
667 return glm::ivec2(0, 0);
670 points.push_back(glm::vec2(
float(start_x) + (start_y % 2 == 0 ? 0.0f : 0.5f), 0.5f +
float(start_y) / 2.0f));
671 visited[start_x + start_y * dat.
size_x] =
true;
673 bool progress =
false;
676 glm::ivec2 temp{ 0, 0 };
678 if(start_y % 2 == 0) {
681 temp += add_next(start_x, start_y + 1, progress, start_x, start_y,
true);
682 temp += add_next(start_x, start_y + 2, progress, start_x, start_y,
false);
683 temp += add_next(start_x - 1, start_y + 1, progress, start_x, start_y,
true);
685 temp += add_next(start_x - 1, start_y - 1, progress, start_x, start_y,
true);
686 temp += add_next(start_x, start_y - 2, progress, start_x, start_y,
false);
687 temp += add_next(start_x, start_y - 1, progress, start_x, start_y,
true);
692 temp += add_next(start_x, start_y + 1, progress, start_x, start_y,
true);
693 temp += add_next(start_x - 1, start_y, progress, start_x, start_y,
false);
694 temp += add_next(start_x, start_y - 1, progress, start_x, start_y,
true);
696 temp += add_next(start_x + 1, start_y - 1, progress, start_x, start_y,
true);
697 temp += add_next(start_x + 1, start_y, progress, start_x, start_y,
false);
698 temp += add_next(start_x + 1, start_y + 1, progress, start_x, start_y,
true);
711 if(points.size() < 3)
717 glm::vec2 current_pos = glm::vec2(points.back().x, points.back().y);
718 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));
719 glm::vec2 prev_direction = glm::normalize(next_pos - current_pos);
720 float distance = 0.0f;
722 auto norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
723 auto old_pos = glm::vec2{ 0,0 };
728 auto raw_dist = (current_pos - next_pos) / glm::vec2(dat.
size_x, dat.
size_y);
730 distance += glm::length(raw_dist);
732 for(
auto i = points.size() - 1; i-- > 1; ) {
733 old_pos = current_pos;
734 current_pos = glm::vec2(points[i].x, points[i].y);
736 next_pos =
put_in_local(glm::vec2(points[i - 1].x, points[i - 1].y), current_pos,
float(dat.
size_x));
737 auto next_direction = glm::normalize(next_pos - current_pos);
739 norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
744 raw_dist = (current_pos - next_pos) / glm::vec2(dat.
size_x, dat.
size_y);
746 distance += glm::length(raw_dist);
751 old_pos = current_pos;
752 current_pos = glm::vec2(points[0].x, points[0].y);
754 next_pos =
put_in_local(glm::vec2(points.back().x, points.back().y), current_pos,
float(dat.
size_x));
755 auto next_direction = glm::normalize(next_pos - current_pos);
757 norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
762 raw_dist = (current_pos - next_pos) / glm::vec2(dat.
size_x, dat.
size_y);
764 distance += glm::length(raw_dist);
769 old_pos = current_pos;
770 current_pos = glm::vec2(points.back().x, points.back().y);
772 next_pos =
put_in_local(glm::vec2(points[points.size() - 2].x, points[points.size() - 2].y), current_pos,
float(dat.
size_x));
773 auto next_direction = glm::normalize(next_pos - current_pos);
774 auto next_normal = glm::vec2(-next_direction.y, next_direction.x);
776 norm_pos = current_pos / glm::vec2(dat.
size_x, dat.
size_y);
789 for(int32_t j = 0; j < int32_t(
size_y); ++j) {
790 for(int32_t i = 0; i < int32_t(
size_x); ++i) {
793 bool was_visited = visited[i + (j * 2) *
size_x];
801 if(j < int32_t(
size_y) - 1) {
802 bool was_visited = visited[i + (j * 2 + 1) *
size_x];
817 world.for_each_province_adjacency([&](dcon::province_adjacency_id
id) {
819 auto prov_a = frel.get_connected_provinces(0);
820 auto prov_b = frel.get_connected_provinces(1);
822 if(!prov_a || !prov_b)
825 glm::vec2 mid_point_a = world.province_get_mid_point(prov_a.id);
826 glm::vec2 mid_point_b = world.province_get_mid_point(prov_b.id);
827 glm::ivec2 tile_pos_a = glm::round(mid_point_a);
828 glm::ivec2 tile_pos_b = glm::round(mid_point_b);
829 glm::ivec2 diff = glm::abs(tile_pos_a - tile_pos_b);
831 bool is_river_crossing =
false;
832 if(diff.x > diff.y) {
833 if(tile_pos_a.x > tile_pos_b.x)
835 int x_difference = std::max(tile_pos_b.x - tile_pos_a.x, 1);
836 int y_difference = tile_pos_a.y - tile_pos_b.y;
837 int min_y = std::min(tile_pos_a.y, tile_pos_b.y);
838 int max_y = std::max(tile_pos_a.y, tile_pos_b.y);
839 for(
int x = tile_pos_a.x; x <= tile_pos_b.x; x++) {
840 float t = float(x - tile_pos_a.x) / x_difference;
841 for(
int k = -2; k <= 2; k++) {
842 int y = tile_pos_b.y + int(y_difference * t) + k;
843 y = std::clamp(y, min_y, max_y);
846 is_river_crossing |=
is_river(river_data[x + y * map_size.x]);
848 if(is_river_crossing)
852 if(tile_pos_a.y > tile_pos_b.y)
854 int y_difference = std::max(tile_pos_b.y - tile_pos_a.y, 1);
855 int x_difference = tile_pos_a.x - tile_pos_b.x;
856 int min_x = std::min(tile_pos_a.x, tile_pos_b.x);
857 int max_x = std::max(tile_pos_a.x, tile_pos_b.x);
858 for(
int y = tile_pos_a.y; y <= tile_pos_b.y; y++) {
859 float t = float(y - tile_pos_a.y) / y_difference;
860 for(
int k = -2; k <= 2; k++) {
861 int x = tile_pos_b.x + int(x_difference * t) + k;
862 x = std::clamp(x, min_x, max_x);
865 is_river_crossing |=
is_river(river_data[x + y * map_size.x]);
867 if(is_river_crossing)
872 uint8_t& buffer = world.province_adjacency_get_type(
id);
873 if(is_river_crossing)
888 return x == other.x &&
y == other.y;
902 for(
uint8_t index = 0; index < vertex->children.size(); index++) {
903 auto child = vertex->children[index];
904 if((child->x -
float(x) - 0.5f) > 0.1f) {
907 if((child->y -
float(y) - 0.5f) > 0.1f) {
916 for(
uint8_t index = 0; index < vertex->parents.size(); index++) {
917 auto parent = vertex->parents[index];
918 if(abs(parent->x -
float(x) - 0.5f) > 0.1f) {
921 if(abs(parent->y -
float(y) - 0.5f) > 0.1f) {
943 if(
is_river(river_data[x + y * size.x])) {
952 std::vector<glm::ivec2> results;
954 results.push_back({ runner.
x + 1, runner.
y });
957 results.push_back({ runner.
x - 1, runner.
y });
960 results.push_back({ runner.
x, runner.
y + 1 });
963 results.push_back({ runner.
x, runner.
y - 1});
1094 std::vector<river_vertex> rivers;
1099 std::vector<river_vertex*> sources;
1100 std::vector<river_vertex*> mouths;
1101 std::map<uint32_t, river_vertex*> vertex_by_pixel_index = {};
1102 std::vector<river_runner> runners;
1103 std::vector<river_runner> new_runners;
1106 auto size = glm::ivec2(int32_t(
size_x), int32_t(
size_y));
1112 auto index = x + y *
size_x;
1115 sources.push_back(source);
1116 vertex_by_pixel_index[index] = source;
1118 runners.push_back(r);
1124 bool exists_running_runner =
true;
1128 while(exists_running_runner) {
1129 exists_running_runner =
false;
1131 for(
auto & item : new_runners) {
1132 runners.push_back(item);
1134 new_runners.clear();
1137 for(
auto & runner : runners) {
1144 if(potential_children.size() == 0) {
1147 for(int32_t i = -1; i <= 1; i++) {
1148 for(int32_t j = -1; j <= 1; j++) {
1149 auto x = (int32_t)runner.x + i;
1150 auto y = (int32_t)runner.y + j;
1165 bool is_sea = terrain_data[index] == 255;
1170 if(!vertex_by_pixel_index.contains(index)) {
1174 runner.position->
width * 2.f
1176 vertex_by_pixel_index[index] = new_river_vertex;
1177 new_river_vertex->
parents.push_back(runner.position);
1178 runner.position->children.push_back(new_river_vertex);
1188 mouths.push_back(runner.position);
1189 }
else if(runner.waiting_for_merge) {
1190 for(
auto target_coord : potential_children) {
1191 auto target_index = target_coord.x + target_coord.y *
size_x;
1192 if(vertex_by_pixel_index.contains(target_index)) {
1193 auto target_vertex = vertex_by_pixel_index[target_index];
1194 target_vertex->parents.push_back(runner.position);
1195 runner.position->children.push_back(target_vertex);
1196 runner.waiting_for_merge =
false;
1201 exists_running_runner =
true;
1203 runner.waiting_for_merge =
true;
1205 bool first_child =
true;
1210 for(
auto candidate : potential_children) {
1213 auto index = x + y *
size_x;
1214 auto width = float(
river_width(river_data[index]));
1217 if(potential_children.size() > 1) {
1220 width = runner.position->width;
1225 bool we_will_move_forward =
false;
1227 if(vertex_by_pixel_index.contains(index)) {
1228 new_river_vertex = vertex_by_pixel_index[index];
1235 vertex_by_pixel_index[index] = new_river_vertex;
1236 we_will_move_forward =
true;
1239 new_river_vertex->
parents.push_back(runner.position);
1240 runner.position->children.push_back(new_river_vertex);
1242 if(we_will_move_forward) {
1246 next_position = new_river_vertex;
1247 first_child =
false;
1249 river_runner r = { new_river_vertex, x, y,
false,
false };
1250 new_runners.push_back(r);
1257 if(next_position !=
nullptr) {
1260 runner.position = next_position;
1361 std::vector<river_vertex*> current_path = { };
1362 std::vector<river_vertex*> nodes_to_skip = { };
1364 current_path.clear();
1372 for(
auto source : sources) {
1374 if(source->children.size() == 0) {
1378 current_path.push_back(source);
1382 while(current_path.size() > 0) {
1383 auto current_node = current_path.back();
1387 bool has_confluence_further =
false;
1389 for(
auto potential_confluence : current_node->children) {
1391 potential_confluence->parents.size() > 1
1392 && potential_confluence->children.size() > 0
1394 has_confluence_further =
true;
1398 if(has_confluence_further) {
1401 auto backrunner = current_path[current_path.size() - 1];
1402 for(
int steps = 0; steps < 2; steps++) {
1403 if(current_path.size() - 1 - steps <= 0) {
1406 if(backrunner->parents.size() == 0) {
1409 nodes_to_skip.push_back(backrunner);
1410 backrunner = current_path[current_path.size() - 1 - steps];
1414 if(current_path.size() > 2) {
1415 auto prev_node = current_path[current_path.size() - 2];
1417 if(current_node->parents.size() > 1 && current_node->children.size() > 0) {
1420 skip_nodes_counter = 2;
1424 bool node_was_skipped =
false;
1425 if(current_node->children.size() == 1)
1426 if(current_node->parents.size() == 1)
1427 if(current_node->children[0]->parents.size() == 1)
1428 if(current_node->parents[0]->children.size() == 1) {
1429 assert(current_node->children[0]->parents[0] == current_node);
1430 assert(current_node->parents[0]->children[0] == current_node);
1431 if(current_path.size() % 3 == 0) {
1432 nodes_to_skip.push_back(current_node);
1433 node_was_skipped =
true;
1434 if(skip_nodes_counter > 0) {
1435 skip_nodes_counter -= 1;
1439 if(current_node->children.size() > 0)
1440 if(current_node->parents.size() > 0)
1441 if(!node_was_skipped && skip_nodes_counter > 0) {
1443 skip_nodes_counter -= 1;
1447 bool pop_back =
true;
1448 for(
auto candidate : current_node->children) {
1449 if(!candidate->skip_visited) {
1450 current_path.push_back(candidate);
1456 current_path.pop_back();
1462 std::vector<river_vertex*> parents;
1463 std::vector<river_vertex*> children;
1464 std::vector<river_vertex*> temp;
1465 for(
auto item : nodes_to_skip) {
1470 for(
auto child : item->children) {
1471 children.push_back(child);
1474 for(
auto parent : item->parents) {
1475 parents.push_back(parent);
1479 for(
auto parent : parents) {
1483 for(
auto parent_child : parent->children) {
1484 if(parent_child->x == item->x)
1485 if(parent_child->y == item->y)
1487 temp.push_back(parent_child);
1490 for(
auto child_to_attach : children) {
1492 bool skip_child =
false;
1493 for(
auto parent_child : parent->children) {
1494 if(parent_child->x == child_to_attach->x)
1495 if(parent_child->y == child_to_attach->y) {
1504 temp.push_back(child_to_attach);
1508 parent->children.clear();
1510 for(
auto saved_item : temp) {
1511 parent->children.push_back(saved_item);
1516 for(
auto child : children) {
1520 for(
auto child_parent : child->parents) {
1521 if(child_parent->x == item->x)
1522 if(child_parent->y == item->y)
1524 temp.push_back(child_parent);
1527 for(
auto parent_to_attach : parents) {
1529 bool skip_parent =
false;
1530 for(
auto child_parent : child->parents) {
1531 if(child_parent->x == parent_to_attach->x)
1532 if(child_parent->y == parent_to_attach->y) {
1541 temp.push_back(parent_to_attach);
1545 child->parents.clear();
1547 for(
auto saved_item : temp) {
1549 child->parents.push_back(saved_item);
1553 item->children.clear();
1554 item->parents.clear();
1564 current_path.clear();
1565 std::vector<glm::vec2> vertex_stabilized_history;
1566 vertex_stabilized_history.clear();
1568 for(
auto source : sources) {
1570 if(source->children.size() == 0) {
1574 current_path.push_back(source);
1575 vertex_stabilized_history.push_back({ source->x, source->y });
1579 while(current_path.size() > 0) {
1582 bool can_start_here =
false;
1587 can_start_here =
true;
1590 while(!can_start_here) {
1591 if(current_path.size() == 0) {
1595 runner = current_path.back();
1596 current_path.pop_back();
1597 vertex_stabilized_history.pop_back();
1599 for(
auto child : runner->
children) {
1600 if(child->visited) {
1604 can_start_here =
true;
1608 if(!can_start_here) {
1619 float distance = 0.0f;
1624 glm::vec2 vertex = { runner->
x, runner->
y };
1625 glm::vec2 vertex_stabilized = vertex;
1626 if(vertex_stabilized_history.size() > 0) {
1627 vertex_stabilized = vertex_stabilized_history.back();
1629 glm::vec2 vertex_stabilized_speed = { 0.f, 0.f };
1630 float friction = 0.932f;
1632 float weight = 0.005f;
1636 bool can_continue =
true;
1637 while(can_continue) {
1640 can_continue =
false;
1645 for(
auto candidate : runner->
children) {
1646 if(candidate->visited) {
1647 can_continue =
true;
1648 next_node = candidate;
1651 next_node = candidate;
1652 can_continue =
true;
1666 if(next_node->
children.size() == 0) {
1667 can_continue =
false;
1670 auto current_point = glm::vec2(runner->
x, runner->
y);
1671 auto next_point = glm::vec2(next_node->
x, next_node->
y);
1673 auto current_tangent = glm::normalize(next_point - current_point);
1674 next_point = next_point + current_tangent * 5.f;
1675 auto current_normal = glm::vec2{ -current_tangent.y, current_tangent.x };
1676 auto next_tangent = glm::normalize(current_tangent);
1678 for(
uint8_t step = 0; step <= steps; step++) {
1679 auto t = (float(step) / float(steps));
1682 + (1.f - t) * current_point;
1683 auto width = t * next_node->
width + (1.f - t) * runner->
width;
1685 auto current_weight = weight * width;
1687 auto acceleration = (vertex - vertex_stabilized) / current_weight;
1688 vertex_stabilized_speed += acceleration;
1689 vertex_stabilized_speed *= (1.f - friction * 0.9f);
1691 auto vertex_old_opengl_coords = vertex_stabilized / glm::vec2(
size_x,
size_y);
1692 vertex_stabilized = vertex_stabilized + vertex_stabilized_speed;
1693 auto vertex_opengl_coords = vertex_stabilized / glm::vec2(
size_x,
size_y);
1694 auto speed_opengl_coords = vertex_opengl_coords - vertex_old_opengl_coords;
1695 auto normal_opengl_coords = glm::normalize(glm::vec2{ -speed_opengl_coords.y, speed_opengl_coords.x });
1696 distance += glm::length(speed_opengl_coords);
1727 auto current_point = glm::vec2(runner->
x, runner->
y);
1728 auto next_point = glm::vec2(next_node->
x, next_node->
y);
1729 auto next_next_point = glm::vec2(next_next_node->
x, next_next_node->
y);
1731 auto current_tangent = next_point - current_point;
1732 auto next_tangent = next_next_point - next_point;
1734 for(
uint8_t step = 0; step <= steps; step++) {
1735 auto t = (float(step) / float(steps));
1738 + (1.f - t) * current_point;
1739 auto width = t * next_node->
width + (1.f - t) * runner->
width;
1741 auto current_weight = weight * width;
1743 auto acceleration = (vertex - vertex_stabilized) / current_weight;
1744 vertex_stabilized_speed += acceleration;
1745 vertex_stabilized_speed *= (1.f - friction);
1747 auto vertex_old_opengl_coords = vertex_stabilized / glm::vec2(
size_x,
size_y);
1748 vertex_stabilized = vertex_stabilized + vertex_stabilized_speed;
1749 auto vertex_opengl_coords = vertex_stabilized / glm::vec2(
size_x,
size_y);
1750 auto speed_opengl_coords = vertex_opengl_coords - vertex_old_opengl_coords;
1751 auto normal_opengl_coords = glm::normalize(glm::vec2{ -speed_opengl_coords.y, speed_opengl_coords.x });
1752 distance += glm::length(speed_opengl_coords);
1780 if(count_back == 0) {
1787 current_path.push_back(runner);
1788 vertex_stabilized_history.push_back( vertex_stabilized );
1795 glm::vec2 current_pos = glm::vec2(source->x, source->y);
1796 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)
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
std::vector< river_vertex * > parents
bool operator==(const river_vertex &other)
std::vector< river_vertex * > children
dcon::province_id first_sea_province
Holds important data about the game world, state, and other data regarding windowing,...
dcon::data_container world
province::global_provincial_state province_definitions