|
|
|
|
@ -1,6 +1,7 @@
|
|
|
|
|
#include "simulation.h" |
|
|
|
|
#include "spacecraft.h" |
|
|
|
|
#include "maneuver.h" |
|
|
|
|
#include "orbital_mechanics.h" |
|
|
|
|
#include <cassert> |
|
|
|
|
#include <cstdlib> |
|
|
|
|
#include <cstring> |
|
|
|
|
@ -167,41 +168,6 @@ void update_simulation(SimulationState* sim) {
|
|
|
|
|
sim->time += sim->dt; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Calculate orbital velocity using vis-viva equation
|
|
|
|
|
// Returns velocity vector for body relative to parent
|
|
|
|
|
static Vec3 calc_orbital_velocity(CelestialBody* body, CelestialBody* parent) { |
|
|
|
|
Vec3 r = vec3_sub(body->global_position, parent->global_position); |
|
|
|
|
double distance = vec3_magnitude(r); |
|
|
|
|
double e = body->orbit.eccentricity; |
|
|
|
|
double a = body->orbit.semi_major_axis; |
|
|
|
|
double v_squared; |
|
|
|
|
|
|
|
|
|
if (fabs(e) < 0.0001) { |
|
|
|
|
v_squared = G * parent->mass / a; |
|
|
|
|
} else if (fabs(e -1.0) < 0.0001) { |
|
|
|
|
v_squared = 2.0 * G * parent->mass / distance; |
|
|
|
|
} else { |
|
|
|
|
v_squared = G * parent->mass * (2.0 / distance - 1.0 / a); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
assert(v_squared >= 0); |
|
|
|
|
double speed = (double) sqrt(v_squared); |
|
|
|
|
|
|
|
|
|
// FIXME: this whole section is just wrong and will break with inclined orbits
|
|
|
|
|
// it's also a failure of our testing that we're not catching it
|
|
|
|
|
Vec3 z_axis = {0.0, 0.0, 1.0}; |
|
|
|
|
Vec3 vel_dir = vec3_cross(z_axis, r); |
|
|
|
|
|
|
|
|
|
if (vec3_magnitude(vel_dir) < 0.01) { |
|
|
|
|
Vec3 x_axis = {1.0, 0.0, 0.0}; |
|
|
|
|
vel_dir = vec3_cross(z_axis, r); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
vel_dir = vec3_normalize(vel_dir); |
|
|
|
|
Vec3 velocity = vec3_scale(vel_dir, speed); |
|
|
|
|
return vec3_add(velocity, parent->global_velocity); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Calculate SOI radius for a single body
|
|
|
|
|
// r_soi = a * (m/M)^(2/5) where a = semi-major axis, m = body mass, M = parent mass
|
|
|
|
|
// Returns SOI radius in meters
|
|
|
|
|
@ -211,26 +177,46 @@ double calculate_soi_radius(CelestialBody* body, CelestialBody* parent) {
|
|
|
|
|
return body->orbit.semi_major_axis * pow(mass_ratio, 0.4); // 2/5 = 0.4
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Combined initialization - sets velocities, SOI radii, and local coordinates in single loop
|
|
|
|
|
void initialize_bodies(SimulationState* sim) { |
|
|
|
|
// Initialize orbital objects from orbital elements
|
|
|
|
|
// Converts orbital elements to local position/velocity and computes global coordinates
|
|
|
|
|
void initialize_orbital_objects(SimulationState* sim) { |
|
|
|
|
for (int i = 0; i < sim->body_count; i++) { |
|
|
|
|
CelestialBody* body = &sim->bodies[i]; |
|
|
|
|
CelestialBody* parent = NULL; |
|
|
|
|
|
|
|
|
|
// Set parent pointer if not root body
|
|
|
|
|
if (body->parent_index >= 0 && body->parent_index < sim->body_count) { |
|
|
|
|
parent = &sim->bodies[body->parent_index]; |
|
|
|
|
body->global_velocity = calc_orbital_velocity(body, parent); |
|
|
|
|
body->local_position = vec3_sub(body->global_position, parent->global_position); |
|
|
|
|
body->local_velocity = vec3_sub(body->global_velocity, parent->global_velocity); |
|
|
|
|
|
|
|
|
|
Vec3 local_pos, local_vel; |
|
|
|
|
orbital_elements_to_cartesian(body->orbit, parent->mass, &local_pos, &local_vel); |
|
|
|
|
|
|
|
|
|
body->local_position = local_pos; |
|
|
|
|
body->local_velocity = local_vel; |
|
|
|
|
body->global_position = vec3_add(parent->global_position, local_pos); |
|
|
|
|
body->global_velocity = vec3_add(parent->global_velocity, local_vel); |
|
|
|
|
body->soi_radius = calculate_soi_radius(body, parent); |
|
|
|
|
} else { // root body
|
|
|
|
|
} else { |
|
|
|
|
body->local_position = {0.0, 0.0, 0.0}; |
|
|
|
|
body->local_velocity = {0.0, 0.0, 0.0}; |
|
|
|
|
body->global_position = {0.0, 0.0, 0.0}; |
|
|
|
|
body->global_velocity = {0.0, 0.0, 0.0}; |
|
|
|
|
body->local_position = body->global_position; |
|
|
|
|
body->local_velocity = body->global_velocity; |
|
|
|
|
body->soi_radius = 1e15; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int i = 0; i < sim->craft_count; i++) { |
|
|
|
|
Spacecraft* craft = &sim->spacecraft[i]; |
|
|
|
|
|
|
|
|
|
if (craft->parent_index >= 0 && craft->parent_index < sim->body_count) { |
|
|
|
|
CelestialBody* parent = &sim->bodies[craft->parent_index]; |
|
|
|
|
|
|
|
|
|
Vec3 local_pos, local_vel; |
|
|
|
|
orbital_elements_to_cartesian(craft->orbit, parent->mass, &local_pos, &local_vel); |
|
|
|
|
|
|
|
|
|
// Root body (like Sun) has infinite SOI, use a large value
|
|
|
|
|
body->soi_radius = 1e15; // 1000 AU in meters
|
|
|
|
|
craft->local_position = local_pos; |
|
|
|
|
craft->local_velocity = local_vel; |
|
|
|
|
craft->global_position = vec3_add(parent->global_position, local_pos); |
|
|
|
|
craft->global_velocity = vec3_add(parent->global_velocity, local_vel); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
@ -342,13 +328,13 @@ void compute_global_coordinates(SimulationState* sim) {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
OrbitalMetrics calculate_orbital_elements(CelestialBody* body, CelestialBody* primary, |
|
|
|
|
OrbitalAnalysis calculate_orbital_elements(CelestialBody* body, CelestialBody* primary, |
|
|
|
|
CelestialBody* optional_ref_body, double current_time) { |
|
|
|
|
const double AU = 1.496e11; |
|
|
|
|
const double SECONDS_PER_DAY = 86400.0; |
|
|
|
|
const double M_sun = primary->mass; |
|
|
|
|
|
|
|
|
|
OrbitalMetrics elem; |
|
|
|
|
OrbitalAnalysis elem; |
|
|
|
|
elem.time_days = current_time / SECONDS_PER_DAY; |
|
|
|
|
|
|
|
|
|
Vec3 r_vec = vec3_sub(body->global_position, primary->global_position); |
|
|
|
|
|