- Change scale_radius() from logarithmic to linear scaling
- Add get_initial_camera_distance() for auto camera positioning
- Implement selected-body-relative rendering (body at origin)
- Add child indicators with hollow circles and text labels
- Restructure render_simulation() with conditional logic
- Fix zoom camera min_distance check for both directions
- Camera automatically positioned based on average child distance
- Changed scale_radius() from linear to logarithmic: scale * log10(radius)
- Adjusted size_scale from 1e-9 to 0.02 for better visual hierarchy
- Lowered min_radius from 0.5f to 0.01f for fine-grained visibility
- Updated rendering documentation with new scaling values
This handles extreme radius ranges (1.5M to 700M meters) while maintaining
visible size differences between Sun, planets, and moons.
Added test case validating prograde motion in simulation frame.
Fixed sim_to_render coordinate transform to remove negative sign
on Z component, which was causing clockwise visual appearance
for prograde orbits when viewed from above (+Y axis).
- Rename CelestialBody/Spacecraft position/velocity to global_*
- Add OrbitalElements struct to both bodies and spacecraft
- Rename old OrbitalElements to OrbitalMetrics (for output/analysis)
- Update all references throughout codebase
- Preserve parent_index in outer structs (not in OrbitalElements)
- Build succeeds with only unused variable warning
Replace 3D billboard rendering with 2D screen-space overlays using
GetWorldToScreen() and DrawTexturePro() for constant visibility.
Changes:
- Rename render functions to *_screen_space suffix
- Use GetWorldToScreen() to transform 3D positions to screen coordinates
- Replace DrawBillboard/DrawBillboardPro() with DrawTexturePro() for 2D rendering
- Use constant pixel sizes (40px spacecraft, 20-60px markers)
- Add off-screen culling to skip rendering outside viewport
- Update render order: 3D scene first, then 2D overlays
- Update documentation to reflect screen-space approach
Benefits:
- Markers remain visible at all zoom levels (constant screen size)
- Simplified sizing with pixel values instead of world-space math
- Better performance with off-screen culling
- Clearer separation: 3D scene vs UI indicators
- Create ui_renderer.cpp/h with all raygui UI panel rendering functions
- Remove UI rendering code from renderer.cpp (421 lines moved)
- Remove UI state fields from RenderState, create separate UIState struct
- Remove raygui dependency from renderer module
- Update main.cpp to initialize UIState and call UI render functions
- Update documentation to reflect new module structure
- Improve separation of concerns between 3D rendering and UI overlays
- Replace wireframe spheres with proper billboard textures
- Spacecraft rendered as cyan circle with arrow (64x64 texture)
- Maneuver markers as directional arrow billboards
- Spacecraft billboards rotate to show velocity direction
- Programmatic texture generation (no external assets)
- Lazy texture loading when spacecraft/maneuvers present
- Proper texture cleanup on renderer shutdown
- Spacecraft rendered as cyan wireframe spheres (fixed size for visibility)
- Maneuver markers as colored cubes (direction-based colors: green=prograde, red=retrograde, etc.)
- Object list now includes spacecraft with '🚀 ' prefix
- Camera follow extended to support spacecraft tracking
- Spacecraft info panel displays local coordinates and maneuver counts
- Maneuver list panel shows pending/executed status with details
- Panel renamed from 'Bodies' to 'Objects'
Changes:
- Add previous_selected_body to RenderState
- Detect when selected_body_index changes
- Recalculate camera_offset when switching to new body
- Maintains same camera distance/orientation to new body
Technical details:
- Body selection change detected via previous_selected_body comparison
- When switching to new body:
* Calculate new body position
* Set camera target to new body
* Use existing camera_offset (maintains distance)
* Update camera.position = body_pos + offset
- Allows seamless transitions between bodies at same zoom level
Result: Camera maintains perspective when switching between
celestial bodies, no jarring distance changes.
Changes:
1. Remove all keyboard shortcuts (B, I, F keys)
2. UI panels always shown (body list, info, simulation info)
3. Selecting a body automatically enables camera follow
4. render_info() now uses GuiWindowBox style matching other UI
UI improvements:
- render_info() now uses GuiWindowBox for consistent styling
- Positioned at bottom-left with smaller window (200x280)
- Window close buttons disabled (panels always shown)
- Updated help text to reflect new workflow
User experience:
- Simpler interaction - just select body from list to follow it
- All information always visible
- Consistent UI styling across all panels
Fixes:
1. Camera now orbits horizontally (not vertically)
2. Uses camera.up instead of hardcoded global up vector
Technical changes:
- Remove hardcoded global up vector
- Use render_state->camera.up for rotation axis
- Rotate forward vector around camera's up vector
- This creates proper horizontal orbit around target
Rotation formula:
new_forward = forward * cos(angle) + cross(up, forward) * sin(angle)
Result: Camera orbits horizontally around target at any
camera position, using the camera's own up vector
for proper orientation-aware rotation.
Problems fixed:
1. Camera now maintains fixed distance to followed body
2. Camera uses proper up vector and cross products for rotation
Technical changes:
- Added camera_offset and was_following_body to RenderState
- Store offset when follow is first enabled
- Update camera position = body_pos + offset each frame
- Use cross products for proper orbital camera rotation:
- Calculate right vector from up x forward
- Rotate forward vector around right axis
- Update camera offset after each movement
- Zoom controls also update offset when following
Result: Camera maintains consistent perspective and distance
while tracking moving celestial bodies.
Features:
- Add camera_follow_body flag to RenderState
- Update update_camera() to follow selected body when enabled
- F key toggles camera follow (requires body selected)
- Camera still rotates and zooms around followed body
- Removed old focus_camera() function (superseded by new implementation)
- Updated help text to show F key for camera follow toggle
Technical details:
- Camera target updates to body position each frame when following
- Existing rotation/zoom controls work relative to new target position
- Maintains orbital camera control pattern
Issue: GuiListView() always returns 0 (known raygui bug), causing
body selection to never work.
Fix:
- Added body_list_scroll and body_list_active to RenderState for persistence
- Check body_list_active parameter changes instead of return value
- Initialize active state to -1 in main.cpp
Reference: https://github.com/raysan5/raygui/issues/448
- Convert body names array to semicolon-separated string format
- Fix GuiListView parameter usage with proper format
- Ensure proper memory management for body list text
- Add raygui as git submodule in ext/raygui/
- Update Makefile to include raygui headers
- Extend RenderState with UI fields (selected_body_index, show_body_list, show_body_info)
- Implement render_body_list_ui() for scrollable body list panel
- Implement render_body_info_ui() for detailed body information panel
- Add 'B' key toggle for body list panel
- Integrate UI rendering into main render loop
- Initialize UI state in main()
- Add render_parabolic_orbit() with true anomaly range -π*0.95 to π*0.95
- Use 80 segments for smooth parabolic curve visualization
- Update render_orbit() branching to handle parabolic (0.98 <= e <= 1.02)
- Calculate semi-latus rectum p = h²/μ for parabolic orbits
- Maintain existing elliptical/hyperbolic orbit rendering
Claude
- Calculate orbital elements dynamically from current state and parent
- Orbits now update automatically when parent body changes
- Add support for parabolic trajectories (e ≈ 1)
- Add support for hyperbolic trajectories (e > 1) with limited extent
- Properly orient orbits in 3D space using eccentricity vector
- Limit hyperbolic/parabolic drawing to avoid infinite vertices
Refactored for code reuse and separation of concerns:
- calculate_orbital_basis(): Computes orbital reference frame
- orbital_to_cartesian(): Transforms orbital coords to 3D space
- draw_orbit_segment(): Handles rendering of individual segments
- render_elliptical_orbit(): Draws closed elliptical paths
- render_hyperbolic_orbit(): Draws open hyperbolic/parabolic paths
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Orbital mechanics simulation with 2-body physics and SOI transitions.
Core Features:
- 2-body gravitational physics with sphere of influence transitions
- Real-time 3D visualization using raylib
- Configurable star systems via text files
- Interactive controls (camera, pause, speed)
Technical Implementation:
- C-style C++ (structs and functions, no classes)
- Modular architecture (physics, bodies, config loader, renderer)
- Euler integration for orbital mechanics
- SOI detection using Hill sphere approximation
Configuration System:
- Solar system with realistic data (Sun, 8 planets, 5 major moons)
- Binary star system example
- Easy to create custom systems via simple text format
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>