Wire trail prepass into generation

This commit is contained in:
chelsea
2025-12-02 22:27:43 -06:00
parent 483200363e
commit f1d6bf6434
2 changed files with 65 additions and 33 deletions

View File

@@ -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;