Browse Source

Implement barycentric orbital calculations for binary star systems

Physics Updates (bodies.cpp):
- Root bodies now apply gravitational forces to each other
- Physics loop split into: root body updates, then child body updates
- Enables binary/multiple star systems to orbit their barycenter

Config Loader Updates (config_loader.cpp):
- Detect multiple root bodies (parent_index = -1)
- Calculate system barycenter (center of mass)
- Set initial velocities for root bodies to orbit barycenter
- Add debug output showing barycenter and orbital speeds

Binary star systems now work correctly with both stars
orbiting their common center of mass.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
main
cinnaboot 6 months ago
parent
commit
ae4c31f688
  1. 29
      src/bodies.cpp
  2. 89
      src/config_loader.cpp

29
src/bodies.cpp

@ -98,11 +98,36 @@ void update_soi(CelestialBody* body, CelestialBody* parent, double semi_major_ax
// Update the entire simulation by one time step // Update the entire simulation by one time step
void update_simulation(SimulationState* sim) { void update_simulation(SimulationState* sim) {
// Update each body's physics (except the root body which is stationary) // First, update root bodies (they interact with each other)
for (int i = 0; i < sim->body_count; i++) { for (int i = 0; i < sim->body_count; i++) {
CelestialBody* body = &sim->bodies[i]; CelestialBody* body = &sim->bodies[i];
// Skip if this is a root body (parent_index == -1) if (body->parent_index == -1) {
// This is a root body - calculate forces from OTHER root bodies
Vec3 total_force = {0.0, 0.0, 0.0};
for (int j = 0; j < sim->body_count; j++) {
if (i == j) continue; // Don't apply force to itself
CelestialBody* other = &sim->bodies[j];
if (other->parent_index == -1) {
// Other is also a root body - apply gravitational force
Vec3 force = calculate_gravity_force(body, other);
total_force = vec3_add(total_force, force);
}
}
// Apply total force from all other root bodies
Vec3 acceleration = calculate_acceleration(total_force, body->mass);
euler_step(body, acceleration, sim->dt);
}
}
// Now update non-root bodies (planets, moons, etc.)
for (int i = 0; i < sim->body_count; i++) {
CelestialBody* body = &sim->bodies[i];
// Skip root bodies (already updated above)
if (body->parent_index == -1) { if (body->parent_index == -1) {
continue; continue;
} }

89
src/config_loader.cpp

@ -61,12 +61,97 @@ bool load_system_config(SimulationState* sim, const char* filepath) {
// Calculate circular orbit velocity: v = sqrt(G * M / r) // Calculate circular orbit velocity: v = sqrt(G * M / r)
// Velocity is perpendicular to position vector // Velocity is perpendicular to position vector
void calculate_initial_velocities(SimulationState* sim) { void calculate_initial_velocities(SimulationState* sim) {
// First, handle multiple root bodies (binary stars, etc.)
// Find all root bodies and calculate barycentric orbits
int root_count = 0;
int root_indices[32]; // Max 32 root bodies
Vec3 barycenter = {0.0, 0.0, 0.0};
double total_mass = 0.0;
// Find all root bodies and calculate barycenter
for (int i = 0; i < sim->body_count; i++) {
if (sim->bodies[i].parent_index == -1) {
if (root_count < 32) {
root_indices[root_count++] = i;
// Weighted sum for barycenter
Vec3 weighted_pos = vec3_scale(sim->bodies[i].position, sim->bodies[i].mass);
barycenter = vec3_add(barycenter, weighted_pos);
total_mass += sim->bodies[i].mass;
}
}
}
// Calculate barycenter position
if (total_mass > 0.0) {
barycenter = vec3_scale(barycenter, 1.0 / total_mass);
}
// Debug output for multiple root bodies
if (root_count > 1) {
printf("\nBinary/Multiple star system detected:\n");
printf(" Number of root bodies: %d\n", root_count);
printf(" Barycenter position: (%.3e, %.3e, %.3e) m\n",
barycenter.x, barycenter.y, barycenter.z);
printf(" Total system mass: %.3e kg\n", total_mass);
}
// Set velocities for root bodies to orbit barycenter
if (root_count > 1) {
for (int i = 0; i < root_count; i++) {
CelestialBody* body = &sim->bodies[root_indices[i]];
// Calculate position relative to barycenter
Vec3 r = vec3_sub(body->position, barycenter);
double distance = vec3_magnitude(r);
if (distance < 1.0) {
body->velocity = {0.0, 0.0, 0.0};
continue;
}
// Calculate total mass of OTHER root bodies
double other_mass = total_mass - body->mass;
// Calculate circular orbit speed around barycenter
// v = sqrt(G * M_other / r)
double speed = sqrt(G * other_mass / distance);
// Create velocity perpendicular to position vector (same logic as below)
Vec3 z_axis = {0.0, 0.0, 1.0};
Vec3 vel_dir = {
r.y * z_axis.z - r.z * z_axis.y,
r.z * z_axis.x - r.x * z_axis.z,
r.x * z_axis.y - r.y * z_axis.x
};
// If r is parallel to z-axis, use x-axis instead
double cross_mag = vec3_magnitude(vel_dir);
if (cross_mag < 0.01) {
Vec3 x_axis = {1.0, 0.0, 0.0};
vel_dir.x = r.y * x_axis.z - r.z * x_axis.y;
vel_dir.y = r.z * x_axis.x - r.x * x_axis.z;
vel_dir.z = r.x * x_axis.y - r.y * x_axis.x;
}
// Normalize and scale by orbital speed
vel_dir = vec3_normalize(vel_dir);
body->velocity = vec3_scale(vel_dir, speed);
// Debug output
printf(" %s: distance from barycenter = %.3e m, orbital speed = %.3e m/s\n",
body->name, distance, speed);
}
} else if (root_count == 1) {
// Single root body stays stationary
sim->bodies[root_indices[0]].velocity = {0.0, 0.0, 0.0};
}
// Now handle child bodies (planets, moons, etc.)
for (int i = 0; i < sim->body_count; i++) { for (int i = 0; i < sim->body_count; i++) {
CelestialBody* body = &sim->bodies[i]; CelestialBody* body = &sim->bodies[i];
// Skip root body (no parent) // Skip root bodies (already handled)
if (body->parent_index == -1) { if (body->parent_index == -1) {
body->velocity = {0.0, 0.0, 0.0};
continue; continue;
} }

Loading…
Cancel
Save