diff --git a/worldgen-c/bin/worldgen b/worldgen-c/bin/worldgen index 809b626..20daa4b 100755 Binary files a/worldgen-c/bin/worldgen and b/worldgen-c/bin/worldgen differ 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;