|
|
|
@ -70,12 +70,13 @@ void update_camera(RenderState* render_state) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Scale a position for rendering
|
|
|
|
// Transform from simulation coordinates (XY plane) to render coordinates (XZ plane)
|
|
|
|
Vector3 scale_position(Vec3 pos, double scale) { |
|
|
|
// Rotation matrix: 90 degrees around X-axis maps Y -> Z
|
|
|
|
|
|
|
|
Vector3 sim_to_render(Vec3 pos, double scale) { |
|
|
|
return (Vector3){ |
|
|
|
return (Vector3){ |
|
|
|
(float)(pos.x * scale), |
|
|
|
(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
|
|
|
|
// Render a single celestial body
|
|
|
|
void render_body(CelestialBody* body, RenderState* render_state) { |
|
|
|
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 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 = { |
|
|
|
Color color = { |
|
|
|
(unsigned char)(body->color[0] * 255), |
|
|
|
(unsigned char)(r * 255), |
|
|
|
(unsigned char)(body->color[1] * 255), |
|
|
|
(unsigned char)(g * 255), |
|
|
|
(unsigned char)(body->color[2] * 255), |
|
|
|
(unsigned char)(b * 255), |
|
|
|
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
|
|
|
|
// Render the entire simulation
|
|
|
|
@ -108,8 +168,27 @@ void render_simulation(SimulationState* sim, RenderState* render_state) { |
|
|
|
|
|
|
|
|
|
|
|
BeginMode3D(render_state->camera); |
|
|
|
BeginMode3D(render_state->camera); |
|
|
|
|
|
|
|
|
|
|
|
// Draw a reference grid
|
|
|
|
// Draw a subtle reference grid
|
|
|
|
DrawGrid(100, 10.0f); |
|
|
|
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
|
|
|
|
// Render all bodies
|
|
|
|
for (int i = 0; i < sim->body_count; i++) { |
|
|
|
for (int i = 0; i < sim->body_count; i++) { |
|
|
|
|