# Rendering System - Technical Reference ## Overview 3D visualization system using raylib for interactive orbital mechanics simulation. Supports logarithmic distance scaling, 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 int selected_craft_index; // -1 = no selection int previous_selected_body; // Previous selected body index int body_list_scroll; // Scroll position for body list int body_list_active; // Active item index in body list bool camera_follow_body; // Whether camera follows selected body Vector3 camera_offset; // Offset from target when following body bool was_following_body; // Previous frame follow state }; ``` ## 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 position transformations **Size Scale:** `1e-9` (same as distance scale) - Applied to body radii - Minimum visible radius: 0.5 units (ensures tiny bodies are visible) **Radius Scaling:** ```cpp float scale_radius(double radius, double scale) { float scaled = (float)(radius * scale); float min_radius = 0.5f; return (scaled > min_radius) ? scaled : min_radius; } ``` ## 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:** - Fixed-size wireframe spheres (5.0 units) - Cyan color (0, 255, 255) - Position scaled and transformed **Purpose:** Visual marker for spacecraft tracking at solar system distances ### Maneuver Markers **Rendering:** - Cubes (`DrawCube`) colored by burn direction - Size based on delta-v magnitude (2-10 units, clamped) - Only shown for unexecuted maneuvers - Positioned at spacecraft location **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 ## 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 ## UI System (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 ### 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 ### Rendering - `render_body(body, render_state)` - Draw single celestial body - `render_spacecraft(craft, render_state)` - Draw spacecraft marker - `render_maneuver_marker(craft, maneuver, render_state)` - Draw burn indicator - `render_simulation(sim, render_state)` - Full scene rendering ### UI - `render_info(sim)` - Bottom-left info panel - `render_body_list_ui(sim, render_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 ### Scaling - `scale_position(pos, scale)` - Transform simulation to render position - `scale_radius(radius, scale)` - Apply size scaling with minimum ## 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