From f1d6bf64346ba889285b1755d3613a4427bea088 Mon Sep 17 00:00:00 2001 From: chelsea Date: Tue, 2 Dec 2025 22:27:43 -0600 Subject: [PATCH] Wire trail prepass into generation --- worldgen-c/bin/worldgen | Bin 135968 -> 140064 bytes worldgen-c/src/worldgen.c | 98 +++++++++++++++++++++++++------------- 2 files changed, 65 insertions(+), 33 deletions(-) diff --git a/worldgen-c/bin/worldgen b/worldgen-c/bin/worldgen index 809b626cdc4d77982119ec16bdea66b12e077888..20daa4bdb0a994c34e9bf0ae682944c9a0947c1d 100755 GIT binary patch delta 27635 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 diff --git a/worldgen-c/src/worldgen.c b/worldgen-c/src/worldgen.c index 9a38c92..1cf9bd7 100644 --- a/worldgen-c/src/worldgen.c +++ b/worldgen-c/src/worldgen.c @@ -218,7 +218,7 @@ void worldgen_prepass(worldgen_ctx *ctx, int min_x, int max_x, int min_z, int ma ctx->trail_segment_cap = 0; const int step = 64; - const int max_points = 48; + const int max_points = 64; const double min_spacing = 96.0; int cap = max_points; int count = 0; @@ -227,7 +227,7 @@ void worldgen_prepass(worldgen_ctx *ctx, int min_x, int max_x, int min_z, int ma double *pv = (double *)malloc((size_t)cap * sizeof(double)); if (!px || !pz || !pv) { free(px); free(pz); free(pv); - goto done; + return; } for (int z = min_z; z <= max_z; z += step) { for (int x = min_x; x <= max_x; x += step) { @@ -259,58 +259,90 @@ void worldgen_prepass(worldgen_ctx *ctx, int min_x, int max_x, int min_z, int ma pv = (double *)realloc(pv, sizeof(double)); if (!px || !pz || !pv) { free(px); free(pz); free(pv); - goto done; + return; } px[0] = (min_x + max_x) / 2; pz[0] = (min_z + max_z) / 2; pv[0] = 1.0; count = 1; } - int root = 0; + + /* Select hubs: pick top valued, then farthest from existing hubs */ + const int max_hubs = 3; + int hub_indices[3] = {0, 0, 0}; + int hub_count = 0; + int first = 0; for (int i = 1; i < count; ++i) { - if (pv[i] > pv[root]) root = i; + if (pv[i] > pv[first]) first = i; } - unsigned char *connected = (unsigned char *)calloc((size_t)count, 1); - if (!connected) { - free(px); free(pz); free(pv); - goto done; - } - connected[root] = 1; - int connected_count = 1; - while (connected_count < count) { - int best_u = -1, best_v = -1; - double best_d2 = DBL_MAX; - for (int u = 0; u < count; ++u) { - if (!connected[u]) continue; - for (int v = 0; v < count; ++v) { - if (connected[v]) continue; - double dx = (double)(px[u] - px[v]); - double dz = (double)(pz[u] - pz[v]); + hub_indices[hub_count++] = first; + for (int h = 1; h < max_hubs && hub_count < count; ++h) { + int best = -1; + double best_d2 = -1.0; + for (int i = 0; i < count; ++i) { + int already_hub = 0; + for (int k = 0; k < hub_count; ++k) if (hub_indices[k] == i) { already_hub = 1; break; } + if (already_hub) continue; + double min_d2 = DBL_MAX; + for (int k = 0; k < hub_count; ++k) { + double dx = (double)(px[i] - px[hub_indices[k]]); + double dz = (double)(pz[i] - pz[hub_indices[k]]); double d2 = dx * dx + dz * dz; - if (d2 < best_d2) { - best_d2 = d2; - best_u = u; - best_v = v; - } + if (d2 < min_d2) min_d2 = d2; + } + if (min_d2 > best_d2) { + best_d2 = min_d2; + best = i; + } + } + if (best >= 0) { + hub_indices[hub_count++] = best; + } + } + + /* Connect hubs together */ + for (int i = 0; i < hub_count; ++i) { + for (int j = i + 1; j < hub_count; ++j) { + int *pts = NULL; + int path_count = 0; + if (build_trail_path(ctx, (double)px[hub_indices[i]], (double)pz[hub_indices[i]], + (double)px[hub_indices[j]], (double)pz[hub_indices[j]], &pts, &path_count) && pts && path_count >= 2) { + append_trail_segment(ctx, px[hub_indices[i]], pz[hub_indices[i]], px[hub_indices[j]], pz[hub_indices[j]], pts, path_count); + } else { + free(pts); + } + } + } + + /* Connect every non-hub point to nearest hub */ + for (int i = 0; i < count; ++i) { + int is_hub = 0; + for (int k = 0; k < hub_count; ++k) if (hub_indices[k] == i) { is_hub = 1; break; } + if (is_hub) continue; + int nearest_hub = hub_indices[0]; + double best_d2 = DBL_MAX; + for (int k = 0; k < hub_count; ++k) { + double dx = (double)(px[i] - px[hub_indices[k]]); + double dz = (double)(pz[i] - pz[hub_indices[k]]); + double d2 = dx * dx + dz * dz; + if (d2 < best_d2) { + best_d2 = d2; + nearest_hub = hub_indices[k]; } } - if (best_u == -1 || best_v == -1) break; int *pts = NULL; int path_count = 0; - if (build_trail_path(ctx, (double)px[best_u], (double)pz[best_u], (double)px[best_v], (double)pz[best_v], &pts, &path_count) && pts && path_count >= 2) { - append_trail_segment(ctx, px[best_u], pz[best_u], px[best_v], pz[best_v], pts, path_count); + if (build_trail_path(ctx, (double)px[i], (double)pz[i], (double)px[nearest_hub], (double)pz[nearest_hub], &pts, &path_count) && pts && path_count >= 2) { + append_trail_segment(ctx, px[i], pz[i], px[nearest_hub], pz[nearest_hub], pts, path_count); } else { free(pts); } - connected[best_v] = 1; - connected_count++; } - free(connected); + free(px); free(pz); free(pv); -done: ctx->prepass_done = 1; ctx->prepass_min_x = min_x; ctx->prepass_max_x = max_x;