vibe coding an orbital mechanics simulation to try out claude code
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.3 KiB

#include "bodies.h"
#include <cstdlib>
#include <cstring>
#include <cmath>
// Create a new simulation
SimulationState* create_simulation(int max_bodies, double time_step) {
SimulationState* sim = (SimulationState*)malloc(sizeof(SimulationState));
sim->bodies = (CelestialBody*)malloc(sizeof(CelestialBody) * max_bodies);
sim->body_count = 0;
sim->max_bodies = max_bodies;
sim->time = 0.0;
sim->dt = time_step;
return sim;
}
// Destroy simulation and free memory
void destroy_simulation(SimulationState* sim) {
if (sim) {
if (sim->bodies) {
free(sim->bodies);
}
free(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,
double eccentricity, double semi_major_axis) {
if (sim->body_count >= sim->max_bodies) {
return; // No more space
}
CelestialBody* body = &sim->bodies[sim->body_count];
strncpy(body->name, name, 63);
body->name[63] = '\0';
body->mass = mass;
body->radius = radius;
body->position = pos;
body->velocity = vel;
body->soi_radius = 0.0; // Will be calculated later
body->parent_index = parent_index;
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++;
}
// Find which body is gravitationally dominant for the given body
int find_dominant_body(SimulationState* sim, int body_index) {
if (body_index < 0 || body_index >= sim->body_count) {
return -1;
}
CelestialBody* body = &sim->bodies[body_index];
int dominant = body->parent_index;
// Check all other bodies to see if we're within their SOI
for (int i = 0; i < sim->body_count; i++) {
if (i == body_index) continue;
CelestialBody* potential_parent = &sim->bodies[i];
double distance = vec3_distance(body->position, potential_parent->position);
// If we're within this body's SOI and it's not our current parent
if (distance < potential_parent->soi_radius && i != dominant) {
// Check if this body is more dominant (closer or more massive)
if (dominant == -1) {
dominant = i;
} else {
CelestialBody* current_parent = &sim->bodies[dominant];
double dist_to_current = vec3_distance(body->position, current_parent->position);
// Switch if this potential parent is significantly closer
if (distance < dist_to_current * 0.5) {
dominant = i;
}
}
}
}
return dominant;
}
// Update sphere of influence radius using Hill sphere approximation
// r_soi = a * (m/M)^(2/5) where a = semi-major axis, m = body mass, M = parent mass
void update_soi(CelestialBody* body, CelestialBody* parent, double semi_major_axis) {
if (parent == NULL || parent->mass <= 0.0) {
// Root body (like Sun) has infinite SOI, use a large value
body->soi_radius = 1e15; // 1000 AU in meters
return;
}
double mass_ratio = body->mass / parent->mass;
body->soi_radius = semi_major_axis * pow(mass_ratio, 0.4); // 2/5 = 0.4
}
void update_simulation(SimulationState* sim) {
for (int i = 0; i < sim->body_count; i++) {
CelestialBody* body = &sim->bodies[i];
if (body->parent_index == -1) {
AccelerationContext ctx;
ctx.sim = sim;
ctx.current_body = body;
ctx.body_index = i;
rk4_step(body, &ctx, sim->dt);
}
}
for (int i = 0; i < sim->body_count; i++) {
CelestialBody* body = &sim->bodies[i];
if (body->parent_index == -1) {
continue;
}
int new_parent = find_dominant_body(sim, i);
if (new_parent != body->parent_index && new_parent != -1) {
body->parent_index = new_parent;
}
if (body->parent_index >= 0 && body->parent_index < sim->body_count) {
AccelerationContext ctx;
ctx.sim = sim;
ctx.current_body = body;
ctx.body_index = i;
rk4_step(body, &ctx, sim->dt);
}
}
sim->time += sim->dt;
}