Browse Source

add generic render_orbit function and spacecraft orbit support

main
cinnaboot 6 months ago
parent
commit
b4e3b40fb2
  1. 78
      src/renderer.cpp
  2. 2
      src/renderer.h

78
src/renderer.cpp

@ -369,18 +369,10 @@ static OrbitalBasis calculate_orbital_basis(Vec3 r_vec, Vec3 velocity, Vec3 e_ve
OrbitalBasis basis;
basis.periapsis_dir = vec3_normalize(e_vec);
Vec3 h_vec = {
r_vec.y * velocity.z - r_vec.z * velocity.y,
r_vec.z * velocity.x - r_vec.x * velocity.z,
r_vec.x * velocity.y - r_vec.y * velocity.x
};
Vec3 h_vec = vec3_cross(r_vec, velocity);
basis.normal = vec3_normalize(h_vec);
basis.q_vec = {
basis.normal.y * basis.periapsis_dir.z - basis.normal.z * basis.periapsis_dir.y,
basis.normal.z * basis.periapsis_dir.x - basis.normal.x * basis.periapsis_dir.z,
basis.normal.x * basis.periapsis_dir.y - basis.normal.y * basis.periapsis_dir.x
};
basis.q_vec = vec3_cross(basis.normal, basis.periapsis_dir);
return basis;
}
@ -466,64 +458,57 @@ static void render_parabolic_orbit(double p, OrbitalBasis basis,
}
}
// Render orbit path for a body
void render_orbit(CelestialBody* body, CelestialBody* parent, RenderState* render_state) {
if (body->parent_index == -1 || parent == NULL) {
return;
}
Color get_body_orbit_color(CelestialBody* body) {
return (Color){
(unsigned char)(body->color[0] * 128),
(unsigned char)(body->color[1] * 128),
(unsigned char)(body->color[2] * 128),
128
};
}
Vec3 r_vec = vec3_sub(body->position, parent->position);
void render_orbit(Vec3 position, Vec3 velocity, Vec3 parent_position,
double parent_mass, Color orbit_color, RenderState* render_state) {
Vec3 r_vec = vec3_sub(position, parent_position);
double r = vec3_magnitude(r_vec);
Vec3 v_vec = body->local_velocity;
double v = vec3_magnitude(v_vec);
double v = vec3_magnitude(velocity);
if (r < 1.0) return;
double mu = G * parent->mass;
double mu = G * parent_mass;
double specific_energy = (v * v) / 2.0 - mu / r;
double v_squared = v * v;
double r_dot_v = r_vec.x * v_vec.x + r_vec.y * v_vec.y + r_vec.z * v_vec.z;
double r_dot_v = vec3_dot(r_vec, velocity);
Vec3 e_vec = {
(v_squared - mu / r) * r_vec.x - r_dot_v * v_vec.x,
(v_squared - mu / r) * r_vec.y - r_dot_v * v_vec.y,
(v_squared - mu / r) * r_vec.z - r_dot_v * v_vec.z
(v_squared - mu / r) * r_vec.x - r_dot_v * velocity.x,
(v_squared - mu / r) * r_vec.y - r_dot_v * velocity.y,
(v_squared - mu / r) * r_vec.z - r_dot_v * velocity.z
};
double e = vec3_magnitude(e_vec) / mu;
Color orbit_color = {
(unsigned char)(body->color[0] * 128),
(unsigned char)(body->color[1] * 128),
(unsigned char)(body->color[2] * 128),
128
};
OrbitalBasis basis = calculate_orbital_basis(r_vec, v_vec, e_vec);
OrbitalBasis basis = calculate_orbital_basis(r_vec, velocity, e_vec);
if (e < 0.98) {
double a = -mu / (2.0 * specific_energy);
if (a <= 0.0) return;
render_elliptical_orbit(a, e, basis, parent->position, render_state, orbit_color);
render_elliptical_orbit(a, e, basis, parent_position, render_state, orbit_color);
} else if (e > 1.02) {
double a = mu / (2.0 * (-specific_energy));
double p = a * (1.0 - e * e);
if (p <= 0.0) return;
render_hyperbolic_orbit(p, e, basis, parent->position, render_state, orbit_color);
render_hyperbolic_orbit(p, e, basis, parent_position, render_state, orbit_color);
} else {
Vec3 h_vec = {
r_vec.y * v_vec.z - r_vec.z * v_vec.y,
r_vec.z * v_vec.x - r_vec.x * v_vec.z,
r_vec.x * v_vec.y - r_vec.y * v_vec.x
};
double h_squared = h_vec.x * h_vec.x + h_vec.y * h_vec.y + h_vec.z * h_vec.z;
Vec3 h_vec = vec3_cross(r_vec, velocity);
double h_squared = vec3_dot(h_vec, h_vec);
double p = h_squared / mu;
if (p <= 0.0) return;
render_parabolic_orbit(p, basis, parent->position, render_state, orbit_color);
render_parabolic_orbit(p, basis, parent_position, render_state, orbit_color);
}
}
@ -558,7 +543,18 @@ void render_simulation(SimulationState* sim, RenderState* render_state) {
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_orbit(body->position, body->local_velocity, parent->position,
parent->mass, get_body_orbit_color(body), render_state);
}
}
// Render spacecraft orbits
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];
render_orbit(craft->position, craft->local_velocity, parent->position,
parent->mass, (Color){0, 255, 255, 128}, render_state);
}
}

2
src/renderer.h

@ -45,6 +45,8 @@ void update_camera(RenderState* render_state, SimulationState* sim);
void render_body(CelestialBody* body, RenderState* render_state);
void render_spacecraft_screen_space(Spacecraft* craft, RenderState* render_state);
void render_maneuver_marker_screen_space(Spacecraft* craft, Maneuver* maneuver, RenderState* render_state);
void render_orbit(Vec3 position, Vec3 velocity, Vec3 parent_position, double parent_mass, Color orbit_color, RenderState* render_state);
Color get_body_orbit_color(CelestialBody* body);
// NOTE: needs to be called between begin_frame() and end_frame()
void render_simulation(SimulationState* sim, RenderState* render_state);
void begin_frame();

Loading…
Cancel
Save