Browse Source

Add orbit path visualization with sim-to-render coordinate transform

🤖 Generated with Claude Code - Co-Authored-By: Claude Sonnet 4.5
main
cinnaboot 6 months ago
parent
commit
d7d49b7dce
  1. 5
      src/bodies.cpp
  2. 5
      src/bodies.h
  3. 3
      src/config_loader.cpp
  4. 101
      src/renderer.cpp

5
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++;
}

5
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);

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

101
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++) {

Loading…
Cancel
Save