You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
4.6 KiB
139 lines
4.6 KiB
#include "config_loader.h" |
|
#include <cstdio> |
|
#include <cmath> |
|
#include <cstring> |
|
|
|
static bool extract_vec3_from_table(toml_datum_t table, Vec3* pos) { |
|
toml_datum_t x = toml_get(table, "x"); |
|
toml_datum_t y = toml_get(table, "y"); |
|
toml_datum_t z = toml_get(table, "z"); |
|
|
|
// Accept both INT64 and FP64 for coordinates (TOML may parse integers as floats) |
|
if ((x.type != TOML_FP64 && x.type != TOML_INT64) || |
|
(y.type != TOML_FP64 && y.type != TOML_INT64) || |
|
(z.type != TOML_FP64 && z.type != TOML_INT64)) { |
|
return false; |
|
} |
|
|
|
pos->x = x.type == TOML_FP64 ? x.u.fp64 : (double)x.u.int64; |
|
pos->y = y.type == TOML_FP64 ? y.u.fp64 : (double)y.u.int64; |
|
pos->z = z.type == TOML_FP64 ? z.u.fp64 : (double)z.u.int64; |
|
return true; |
|
} |
|
|
|
static bool extract_color_from_table(toml_datum_t table, float* color) { |
|
toml_datum_t r = toml_get(table, "r"); |
|
toml_datum_t g = toml_get(table, "g"); |
|
toml_datum_t b = toml_get(table, "b"); |
|
|
|
// Accept both INT64 and FP64 for color components |
|
if ((r.type != TOML_FP64 && r.type != TOML_INT64) || |
|
(g.type != TOML_FP64 && g.type != TOML_INT64) || |
|
(b.type != TOML_FP64 && b.type != TOML_INT64)) { |
|
return false; |
|
} |
|
|
|
color[0] = (float)(r.type == TOML_FP64 ? r.u.fp64 : (double)r.u.int64); |
|
color[1] = (float)(g.type == TOML_FP64 ? g.u.fp64 : (double)g.u.int64); |
|
color[2] = (float)(b.type == TOML_FP64 ? b.u.fp64 : (double)b.u.int64); |
|
return true; |
|
} |
|
|
|
static bool parse_toml_body(toml_datum_t body_table, CelestialBody* body) { |
|
// Extract string fields |
|
toml_datum_t name = toml_get(body_table, "name"); |
|
if (name.type != TOML_STRING) { |
|
return false; |
|
} |
|
strncpy(body->name, name.u.s, 63); |
|
body->name[63] = '\0'; |
|
|
|
// Extract numeric fields |
|
toml_datum_t mass = toml_get(body_table, "mass"); |
|
toml_datum_t radius = toml_get(body_table, "radius"); |
|
toml_datum_t parent_idx = toml_get(body_table, "parent_index"); |
|
toml_datum_t eccentricity = toml_get(body_table, "eccentricity"); |
|
toml_datum_t semi_major = toml_get(body_table, "semi_major_axis"); |
|
|
|
if (mass.type != TOML_FP64 || radius.type != TOML_FP64 || |
|
parent_idx.type != TOML_INT64 || |
|
eccentricity.type != TOML_FP64 || |
|
semi_major.type != TOML_FP64) { |
|
return false; |
|
} |
|
|
|
body->mass = mass.u.fp64; |
|
body->radius = radius.u.fp64; |
|
body->parent_index = (int)(parent_idx.type == TOML_INT64 ? parent_idx.u.int64 : (int)parent_idx.u.fp64); |
|
body->eccentricity = eccentricity.u.fp64; |
|
body->semi_major_axis = semi_major.u.fp64; |
|
|
|
// Extract position vector |
|
toml_datum_t position = toml_get(body_table, "position"); |
|
if (position.type != TOML_TABLE || !extract_vec3_from_table(position, &body->position)) { |
|
return false; |
|
} |
|
|
|
// Extract color |
|
toml_datum_t color = toml_get(body_table, "color"); |
|
if (color.type != TOML_TABLE || !extract_color_from_table(color, body->color)) { |
|
return false; |
|
} |
|
|
|
// Initialize velocity (will be calculated later) |
|
body->velocity = {0.0, 0.0, 0.0}; |
|
body->soi_radius = 0.0; |
|
|
|
return true; |
|
} |
|
|
|
bool load_system_config(SimulationState* sim, const char* filepath) { |
|
toml_result_t result = toml_parse_file_ex(filepath); |
|
if (!result.ok) { |
|
printf("Error: Could not parse TOML config file: %s\n", filepath); |
|
printf("TOML Error: %s\n", result.errmsg); |
|
return false; |
|
} |
|
|
|
// Get bodies array |
|
toml_datum_t bodies = toml_get(result.toptab, "bodies"); |
|
if (bodies.type != TOML_ARRAY) { |
|
printf("Error: Expected 'bodies' array in config file: %s\n", filepath); |
|
toml_free(result); |
|
return false; |
|
} |
|
|
|
// Count bodies first |
|
int body_count = bodies.u.arr.size; |
|
if (body_count == 0) { |
|
printf("Error: No bodies found in config file: %s\n", filepath); |
|
toml_free(result); |
|
return false; |
|
} |
|
|
|
if (body_count > sim->max_bodies) { |
|
printf("Error: Too many bodies (%d) for simulation (max: %d)\n", |
|
body_count, sim->max_bodies); |
|
toml_free(result); |
|
return false; |
|
} |
|
|
|
for (int i = 0; i < body_count; i++) { |
|
toml_datum_t body_table = bodies.u.arr.elem[i]; |
|
if (!parse_toml_body(body_table, &sim->bodies[i])) { |
|
printf("Error: Failed to parse body at index %d\n", i); |
|
toml_free(result); |
|
return false; |
|
} |
|
} |
|
|
|
sim->body_count = body_count; |
|
toml_free(result); |
|
|
|
calculate_initial_velocities(sim); |
|
calculate_soi_radii(sim); |
|
initialize_local_coordinates(sim); |
|
|
|
printf("Loaded %d bodies from %s\n", body_count, filepath); |
|
return true; |
|
}
|
|
|