# 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) ```cpp 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 bool camera_target_enabled; // Whether camera follows selected body Vector3 camera_offset; // Offset from target when following body int last_target_index; // Tracks body index for change detection Texture2D maneuver_textures[6]; // One per burn direction bool texture_loaded; }; ``` ### UIState (ui_renderer.h) ```cpp struct UIState { int body_list_scroll; // Scroll position for body list int body_list_active; // Active item index in body list int selected_craft_index; // Selected spacecraft index (-1 = no selection) int maneuver_list_active; int maneuver_list_scroll; int selected_maneuver_index; int cached_body_count, cached_craft_count; int cached_maneuver_count, cached_executed_count; char* body_list_buffer; int body_list_buffer_size; char* craft_list_buffer; int craft_list_buffer_size; char* body_dropdown_buffer; int body_dropdown_buffer_size; char* maneuver_list_buffer; int maneuver_list_buffer_size; ManeuverDialogState maneuver_dialog; }; ``` ### ManeuverDialogState (ui_renderer.h) ```cpp struct ManeuverDialogState { bool open; ManeuverDialogTab active_tab; int craft_index, direction_active; double delta_v, trigger_value; int edit_maneuver_index; int target_body_index, current_body_index, transfer_body_index; bool show_hohmann_preview; HohmannTransfer last_calc; bool show_preview, preview_valid; OrbitalElements preview_elements; char error_message[256]; bool show_error, show_delete_confirm; }; ``` ## 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:** ```cpp 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:** ```cpp 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, CAMERA_INITIAL_POSITION_Y, CAMERA_INITIAL_POSITION_Z) initially - Target: Origin (0, 0, 0) - Up vector: (0, 1, 0) - FOV: CAMERA_INITIAL_FOV (45 degrees) - Projection: Perspective ### Camera Control Constants - **Orbit rotation speed:** CAMERA_ORBIT_ANGLE_SPEED (0.02 radians per keypress) - **Zoom percentage:** ZOOM_PERCENTAGE (7% of current distance per keypress) - **Zoom delta limits:** ZOOM_MIN_DELTA (0.05) to ZOOM_MAX_DELTA (5.0) - **Initial height factor:** CAMERA_INITIAL_HEIGHT_FACTOR (0.3) - **Minimum distance fallback:** CAMERA_MIN_DISTANCE (0.1 for no target) ### Camera Controls **Arrow Keys:** - Left/Right: Orbit around target (horizontal rotation) - Up/Down: Zoom in/out (preserve viewing angle) - Zoom speed is percentage-based: faster when far, slower when close - Zoom delta clamped to prevent too-slow or too-fast movement **Camera Follow Mode:** - Tracks selected body only (spacecraft selection handled by UI) - When spacecraft selected, camera follows spacecraft's parent body - Preserves relative offset when following - Updates target position each frame to follow moving objects - Maintains camera distance when switching between bodies - Initial camera position accounts for body size when switching targets **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 using get_initial_camera_distance() 3. **Frame update**: Move camera to maintain offset from moving target 4. **Spacecraft selection**: Camera focuses on spacecraft's parent body ## 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:** - Only visible via child indicators when parent body is selected - No separate 3D or screen-space rendering - Orbits rendered as cyan (0, 255, 255) lines **Purpose:** Spacecraft are tracked via orbit paths and child indicators only ### 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, 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. Maneuver markers 5. 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) Dropdown lists use cached buffers, rebuilt only when object counts change. ## 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 Maneuver Markers**: Draw pending maneuver indicators 7. **EndMode3D**: Exit 3D rendering 8. **Render UI Panels**: Draw all raygui panels 9. **Render Child Indicators**: Draw child overlays 10. **EndDrawing**: Complete frame ### Performance Considerations - 60 FPS target - Wireframe rendering for faster performance - Minimum visible size prevents tiny bodies - 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_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 buffers persist between frames and rebuild when object counts change. Buffers freed on shutdown via ui_state_free_buffers(). ## 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)