diff --git a/src/bodies.cpp b/src/bodies.cpp index 3161066..976d9bc 100644 --- a/src/bodies.cpp +++ b/src/bodies.cpp @@ -26,7 +26,8 @@ void destroy_simulation(SimulationState* sim) { // Add a celestial body to the simulation void add_body(SimulationState* sim, const char* name, double mass, double radius, - Vec3 pos, Vec3 vel, int parent_index, float r, float g, float b) { + Vec3 pos, Vec3 vel, int parent_index, float r, float g, float b, + double eccentricity, double semi_major_axis) { if (sim->body_count >= sim->max_bodies) { return; // No more space } @@ -43,6 +44,8 @@ void add_body(SimulationState* sim, const char* name, double mass, double radius body->color[0] = r; body->color[1] = g; body->color[2] = b; + body->eccentricity = eccentricity; + body->semi_major_axis = semi_major_axis; sim->body_count++; } diff --git a/src/bodies.h b/src/bodies.h index 2266bfc..648ad1a 100644 --- a/src/bodies.h +++ b/src/bodies.h @@ -13,6 +13,8 @@ struct CelestialBody { double soi_radius; // sphere of influence radius (meters) int parent_index; // index of gravitational parent (-1 for root body like Sun) float color[3]; // RGB color for rendering + double eccentricity; // orbital eccentricity (0 = circular, <1 = elliptical) + double semi_major_axis; // meters }; // Simulation state @@ -28,7 +30,8 @@ struct SimulationState { SimulationState* create_simulation(int max_bodies, double time_step); void destroy_simulation(SimulationState* sim); void add_body(SimulationState* sim, const char* name, double mass, double radius, - Vec3 pos, Vec3 vel, int parent_index, float r, float g, float b); + Vec3 pos, Vec3 vel, int parent_index, float r, float g, float b, + double eccentricity, double semi_major_axis); // SOI and simulation update functions int find_dominant_body(SimulationState* sim, int body_index); diff --git a/src/config_loader.cpp b/src/config_loader.cpp index c29abb7..f754d26 100644 --- a/src/config_loader.cpp +++ b/src/config_loader.cpp @@ -50,7 +50,8 @@ bool load_system_config(SimulationState* sim, const char* filepath) { if (parse_body_line(line, name, &mass, &radius, &pos, &parent_index, &r, &g, &b, &eccentricity, &semi_major_axis)) { Vec3 vel = {0.0, 0.0, 0.0}; - add_body(sim, name, mass, radius, pos, vel, parent_index, r, g, b); + add_body(sim, name, mass, radius, pos, vel, parent_index, r, g, b, + eccentricity, semi_major_axis); orbit_params[sim->body_count - 1].eccentricity = eccentricity; orbit_params[sim->body_count - 1].semi_major_axis = semi_major_axis; diff --git a/src/renderer.cpp b/src/renderer.cpp index be0a0c5..54b61ae 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -70,12 +70,13 @@ void update_camera(RenderState* render_state) { } } -// Scale a position for rendering -Vector3 scale_position(Vec3 pos, double scale) { +// Transform from simulation coordinates (XY plane) to render coordinates (XZ plane) +// Rotation matrix: 90 degrees around X-axis maps Y -> Z +Vector3 sim_to_render(Vec3 pos, double scale) { return (Vector3){ (float)(pos.x * scale), - (float)(pos.y * scale), - (float)(pos.z * scale) + (float)(-pos.z * scale), + (float)(pos.y * scale) }; } @@ -88,17 +89,76 @@ float scale_radius(double radius, double scale) { // Render a single celestial body void render_body(CelestialBody* body, RenderState* render_state) { - Vector3 position = scale_position(body->position, render_state->distance_scale); + Vector3 position = sim_to_render(body->position, render_state->distance_scale); float radius = scale_radius(body->radius, render_state->size_scale); + float r = body->color[0]; + float g = body->color[1]; + float b = body->color[2]; + + if (body->parent_index == -1) { + float gray = (r + g + b) / 3.0f * 0.3f; + r = g = b = gray; + } + Color color = { - (unsigned char)(body->color[0] * 255), - (unsigned char)(body->color[1] * 255), - (unsigned char)(body->color[2] * 255), + (unsigned char)(r * 255), + (unsigned char)(g * 255), + (unsigned char)(b * 255), 255 }; - DrawSphere(position, radius, color); + DrawSphereWires(position, radius, 16, 16, color); +} + +// Render orbit path for a body +void render_orbit(CelestialBody* body, CelestialBody* parent, RenderState* render_state) { + if (body->parent_index == -1 || parent == NULL) { + return; + } + + double a = body->semi_major_axis; + double e = body->eccentricity; + + if (a <= 0.0) { + return; + } + + double b = a * sqrt(1.0 - e * e); + double c = a * e; + + Vector3 parent_pos = sim_to_render(parent->position, render_state->distance_scale); + + Color orbit_color = { + (unsigned char)(body->color[0] * 128), + (unsigned char)(body->color[1] * 128), + (unsigned char)(body->color[2] * 128), + 128 + }; + + int segments = 100; + for (int i = 0; i < segments; i++) { + float theta1 = (float)i / segments * 2.0f * PI; + float theta2 = (float)(i + 1) / segments * 2.0f * PI; + + float x1 = (float)(a * cos(theta1) - c); + float y1 = (float)(b * sin(theta1)); + float x2 = (float)(a * cos(theta2) - c); + float y2 = (float)(b * sin(theta2)); + + Vector3 p1 = { + parent_pos.x + x1 * (float)render_state->distance_scale, + parent_pos.y, + parent_pos.z + y1 * (float)render_state->distance_scale + }; + Vector3 p2 = { + parent_pos.x + x2 * (float)render_state->distance_scale, + parent_pos.y, + parent_pos.z + y2 * (float)render_state->distance_scale + }; + + DrawLine3D(p1, p2, orbit_color); + } } // Render the entire simulation @@ -108,8 +168,27 @@ void render_simulation(SimulationState* sim, RenderState* render_state) { BeginMode3D(render_state->camera); - // Draw a reference grid - DrawGrid(100, 10.0f); + // Draw a subtle reference grid + for (int i = -50; i <= 50; i++) { + if (i == 0) continue; + DrawLine3D((Vector3){(float)i * 10.0f, 0, -500.0f}, + (Vector3){(float)i * 10.0f, 0, 500.0f}, + (Color){20, 20, 20, 255}); + DrawLine3D((Vector3){-500.0f, 0, (float)i * 10.0f}, + (Vector3){500.0f, 0, (float)i * 10.0f}, + (Color){20, 20, 20, 255}); + } + DrawLine3D((Vector3){0, 0, -500.0f}, (Vector3){0, 0, 500.0f}, (Color){40, 40, 40, 255}); + DrawLine3D((Vector3){-500.0f, 0, 0}, (Vector3){500.0f, 0, 0}, (Color){40, 40, 40, 255}); + + // Render orbit paths first + for (int i = 0; i < sim->body_count; i++) { + CelestialBody* body = &sim->bodies[i]; + if (body->parent_index >= 0 && body->parent_index < sim->body_count) { + CelestialBody* parent = &sim->bodies[body->parent_index]; + render_orbit(body, parent, render_state); + } + } // Render all bodies for (int i = 0; i < sim->body_count; i++) {