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.
 
 
 
 
 

11 KiB

Rendering System - Technical Reference

Overview

3D visualization system using raylib for interactive orbital mechanics simulation. Supports linear distance scaling, relative rendering with child indicators, orbit path rendering, spacecraft tracking, and maneuver planning visualization.

Core Data Structure

RenderState (renderer.h)

struct RenderState {
    Camera3D camera;
    double distance_scale;        // Scale factor for distances
    double size_scale;            // Scale factor for body sizes
    int selected_body_index;      // -1 = no selection
    int selected_craft_index;     // -1 = no selection
    int last_target_index;        // Tracks body or craft index (negative = spacecraft)
    int body_list_scroll;         // Scroll position for body list
    int body_list_active;         // Active item index in body list
    bool camera_target_enabled;   // Whether camera follows selected body/craft
    Vector3 camera_offset;        // Offset from target when following body
};

Coordinate Transformation

Simulation to Render Coordinates

The simulation uses an XY plane while rendering uses XZ plane (Y is up in raylib).

Transformation:

  • Simulation (X, Y, Z) → Render (X, Z, -Y)
  • 90-degree rotation around X-axis

Implementation:

Vector3 sim_to_render(Vec3 pos, double scale) {
    return (Vector3){
        (float)(pos.x * scale),
        (float)(pos.z * scale),
        (float)(-pos.y * scale)
    };
}

Scaling Factors

Distance Scale: 1e-9 (1 render unit = 1 billion meters)

  • Optimized for solar system scale
  • Used for both position transformations and radius scaling

Size Scale: Same as distance scale (linear scaling)

Radius Scaling:

float scale_radius(double radius, double scale) {
    return (float)(radius * scale);
}

Uses linear scaling for consistent representation at all scales.

Camera System

Camera Setup

  • Position: (0, 50, 100) initially
  • Target: Origin (0, 0, 0)
  • Up vector: (0, 1, 0)
  • FOV: 45 degrees
  • Projection: Perspective

Camera Controls

Arrow Keys:

  • Left/Right: Orbit around target (horizontal rotation)
  • Up/Down: Zoom in/out (preserve viewing angle)

Camera Follow Mode:

  • Tracks selected body or spacecraft
  • Preserves relative offset when following
  • Updates target position each frame to follow moving objects
  • Maintains camera distance when switching between bodies

Camera Rotation Logic:

  • Uses camera's up vector for horizontal orbit
  • Rotates forward vector around up axis
  • Preserves camera distance from target

Follow State Transitions:

  1. Enable follow: Store current offset from target
  2. Body switch: Recalculate offset to maintain distance
  3. Frame update: Move camera to maintain offset from moving target

Object Rendering

Celestial Bodies

Rendering:

  • Wireframe spheres (DrawSphereWires)
  • Color from body's RGB values
  • Position scaled and transformed to render coordinates
  • Radius scaled with minimum visible size

Order: All bodies rendered after orbit paths

Spacecraft

Rendering:

  • Screen-space 2D overlay using DrawTexturePro()
  • Constant screen size: 40 pixels (independent of camera zoom)
  • Cyan color (0, 255, 255)
  • Rotated to face velocity direction
  • Off-screen culling (skips rendering if outside viewport)

Purpose: UI indicator for spacecraft that remains visible at all zoom levels

Maneuver Markers

Rendering:

  • Screen-space 2D overlay using DrawTexturePro()
  • Size based on delta-v magnitude (20-60 pixels, clamped)
  • Only shown for unexecuted maneuvers
  • Off-screen culling (skips rendering if outside viewport)

Color Coding:

  • PROGRADE: Green (0, 255, 0)
  • RETROGRADE: Red (255, 0, 0)
  • NORMAL: Yellow (255, 255, 0)
  • ANTINORMAL: Orange (255, 165, 0)
  • RADIAL_IN: Magenta (255, 0, 255)
  • RADIAL_OUT: Cyan (0, 255, 255)
  • CUSTOM: White (255, 255, 255)

Render Order: Top layer, after spacecraft (rendered as 2D overlays after 3D scene)

Child Indicators

Screen-space 2D overlays for children of selected body (similar to NASA Eyes).

Rendering:

  • NASA Eyes-style hollow circles
  • Radius: 20px, Thickness: 2px
  • Text label centered inside indicator
  • White color for bodies, cyan (0, 255, 255) for spacecraft
  • Only shown when body selected (not when spacecraft selected)
  • Uses GetWorldToScreen() for 2D positioning after EndMode3D()

Purpose: Indicates location of children bodies/spacecraft that may be off-screen or hard to locate

Orbit Rendering

Orbital Basis Calculation

Components:

  • periapsis_dir: Normalized eccentricity vector (points toward periapsis)
  • normal: Normalized angular momentum vector (orbit plane normal)
  • q_vec: Cross product of normal and periapsis_dir (completes basis)

Purpose: Defines orbital plane for transforming orbital elements to Cartesian coordinates

Elliptical Orbits (e < 0.98)

Parameters:

  • Semi-major axis: a = -μ / (2 * specific_energy)
  • Semi-minor axis: b = a * sqrt(1 - e²)
  • Focus offset: c = a * e

Rendering:

  • 100 segments
  • Full orbit (0 to 2π)
  • Drawn as series of line segments in orbital basis

Parabolic Orbits (0.98 ≤ e ≤ 1.02)

Parameters:

  • Semi-latus rectum: p = h² / μ

Rendering:

  • 80 segments
  • True anomaly range: -π0.95 to π0.95 (avoid singularity at ±π)
  • Escape trajectory path

Hyperbolic Orbits (e > 1.02)

Parameters:

  • Semi-major axis: a = μ / (2 * (-specific_energy)) (negative for hyperbola)
  • Semi-latus rectum: p = a * (1 - e²)
  • Max true anomaly: acos(-1/e) * 0.95

Rendering:

  • 60 segments
  • Shows asymptotic behavior approaching true anomaly limit
  • Fast escape trajectory visualization

Orbit Color: Half-intensity body color (128 alpha)

Render Order

  1. Reference grid
  2. Orbit paths (for all bodies with parents)
  3. Bodies
  4. Spacecraft
  5. Maneuver markers
  6. Child indicators (screen-space overlays)

Relative Rendering

When a body is selected, the scene is rendered relative to that body:

  • Selected body is rendered at origin (0, 0, 0)
  • Children are rendered relative to selected body
  • Children's orbits are rendered around origin
  • Uses full float precision for small orbital distances (e.g., LEO)

When a spacecraft is selected:

  • Parent body is rendered relative to spacecraft
  • Spacecraft's orbit is rendered around parent
  • No sibling spacecraft rendered

Benefits:

  • Improved visibility of small orbits (LEO, moon orbits)
  • Better float precision for local coordinate systems
  • Automatic camera positioning based on children distances

UI System (ui_renderer + raygui)

Info Panel (Bottom-Left)

Content:

  • Simulation time (in days)
  • Body count
  • FPS
  • Controls reference
  • Config file name

Dimensions: 300×300 pixels

Objects List (Top-Left)

Content:

  • All celestial bodies (no prefix)
  • All spacecraft (🚀 prefix)
  • Scrollable list view

Interaction:

  • Clicking enables camera follow
  • Updates selected_body_index or selected_craft_index
  • Triggers camera offset calculation

Dimensions: 200×400 pixels

Info Panel (Top-Right)

Content (Body Selected):

  • Name, mass, radius
  • Position (global for root, local for children)
  • Velocity magnitude
  • Eccentricity, semi-major axis
  • Parent body name
  • SOI radius

Content (Spacecraft Selected):

  • Name, mass
  • Local position and velocity
  • Parent body name
  • Pending/Executed maneuver counts

Empty: Displays placeholder panel when nothing selected

Dimensions: 250×300 pixels

Maneuver List (Below Info Panel)

Content (Spacecraft Selected Only):

  • List of maneuvers for selected spacecraft
  • Status prefix: [PENDING] or [DONE]
  • Maneuver names

Details:

  • Next pending maneuver: name and delta-v
  • Last executed maneuver: name, delta-v, execution time
  • "No maneuvers defined" if none exist

Dimensions: 300×400 pixels Position: Y=320 (below info panel)

Rendering Pipeline

Main Loop Sequence

  1. BeginDrawing: Clear background to black
  2. BeginMode3D: Enter 3D rendering
  3. Draw Reference Grid: Subtle gray grid lines
  4. Render Orbit Paths: Calculate and draw all orbits
  5. Render Bodies: Draw all celestial bodies
  6. Render Spacecraft: Draw all spacecraft
  7. Render Maneuver Markers: Draw pending maneuver indicators
  8. EndMode3D: Exit 3D rendering
  9. Render UI Panels: Draw all raygui panels
  10. EndDrawing: Complete frame

Performance Considerations

  • 60 FPS target
  • Wireframe rendering for faster performance
  • Minimum visible size prevents tiny bodies
  • Fixed spacecraft marker size for visibility at distance
  • Clipped orbit segments to avoid infinite paths

Module Functions

Renderer Module (renderer.cpp/h)

Initialization

  • init_renderer(width, height, title) - Setup raylib window
  • close_renderer() - Cleanup raylib
  • setup_camera(render_state) - Initialize camera parameters

Camera

  • update_camera(render_state, sim) - Handle input and camera follow
  • get_initial_camera_distance(body, sim, render_state) - Auto-position camera based on children distance

Rendering

  • render_body(body, render_state) - Draw single celestial body
  • render_spacecraft_screen_space(craft, render_state) - Draw spacecraft marker as 2D overlay
  • render_maneuver_marker_screen_space(craft, maneuver, render_state) - Draw burn indicator as 2D overlay
  • render_simulation(sim, render_state) - Full scene rendering (3D + 2D overlays)

Scaling

  • scale_position(pos, scale) - Transform simulation to render position
  • scale_radius(radius, scale) - Apply size scaling with minimum

UI Renderer Module (ui_renderer.cpp/h)

UI Rendering

  • render_info(sim) - Bottom-left info panel
  • render_body_list_ui(sim, render_state, ui_state) - Objects selection panel
  • render_body_info_ui(sim, render_state) - Top-right info panel
  • render_maneuver_list_ui(sim, render_state) - Maneuver list panel

Note: UI rendering functions are called after render_simulation() to ensure UI overlays appear on top of the 3D scene.

Technical Notes

Raylib Integration

  • Header-only raygui for UI
  • raymath for vector operations
  • Perspective 3D camera
  • Wireframe sphere rendering

Color Handling

  • Body colors: float RGB (0.0-1.0) → byte RGB (0-255)
  • Orbit colors: 50% intensity, 50% alpha
  • Spacecraft: Fixed cyan
  • Maneuvers: Direction-based colors with alpha

Reference Grid

  • Subtle gray lines (20, 20, 20) for minor axes
  • Brighter axes (40, 40, 40) for X and Z zero lines
  • Extends from -500 to 500 in both directions
  • Helps orient user in 3D space

Memory Management

  • UI panels allocate temporary buffers for lists
  • List text freed after rendering
  • No persistent UI state allocation

TODO Items

  1. Distant Bodies: When body selected, show indicators for bodies that are not children (currently only shows direct children)

  2. Smooth Frame Transitions: Add interpolation when switching between different selected bodies (instant switch currently)