# SOI Bug Fix and Dynamic Orbital Rendering (2026-01-05) ## Changes Made ### Core Bug Fixes - Fixed SOI calculation bug: was using current distance instead of orbital semi_major_axis - Caused incorrect SOI radii for eccentric orbits (e.g., comet at perihelion vs aphelion) - Now properly uses stored orbital parameter from config file - Added parent change tracking to headless simulation mode for debugging SOI transitions ### Test Refactoring - Refactored test to use same code path as simulation via `load_system_config()` - Eliminated ~30 lines of manual body setup in test - Ensures test and simulation behave identically - Added `config_loader.cpp` to test build dependencies - Refactored verbose test output into separate functions with compile-time flag - Added `COMET_TEST_VERBOSE_OUTPUT` flag (default: 0) - Moved output to `print_orbital_snapshots()` and `print_parent_changes()` ### Graphics Enhancements - Implemented dynamic orbital rendering with real-time element calculation - Orbits now update automatically when parent body changes - Calculates orbital elements from current position/velocity relative to parent - Added support for parabolic trajectories (e ≈ 1) - Limited to ±86° from periapsis to avoid infinite vertices - Added support for hyperbolic trajectories (e > 1) - Limited to asymptotic angle to avoid infinite vertices - Properly orients orbits in 3D space using eccentricity vector and angular momentum ### Code Structure Refactored renderer for separation of concerns: - `OrbitalBasis` struct - Holds orbital reference frame - `calculate_orbital_basis()` - Computes periapsis direction, normal, and perpendicular vectors - `orbital_to_cartesian()` - Transforms 2D orbital coordinates to 3D space - `draw_orbit_segment()` - Handles rendering of individual line segments - `render_elliptical_orbit()` - Draws closed elliptical paths (100 segments) - `render_hyperbolic_orbit()` - Draws open hyperbolic/parabolic paths (60 segments) ### Test Configuration Enhanced `configs/test_simple.txt` with diverse orbit examples: - Parabolic object (e=1.0 at 0.5 AU, exactly at escape velocity) - Inclined asteroid (circular orbit with 30° inclination) - Hyperbolic visitor (e=1.5, interstellar trajectory) ## Commits - `89931c3` Fix SOI calculation and orbit direction bugs - `8e21f71` Refactor test to use same code path as simulation - `232614d` Revert cross product direction in config_loader - `4a313f8` remove extra debugging not added by claude (user commit) - `c613d21` Refactor verbose test output to separate functions - `060ff40` Add dynamic orbital rendering with hyperbolic/parabolic support - `e1df0b4` Add diverse orbit examples to test_simple config ## Results 7 files changed, +209/-106 (net +103 lines) ### Key Findings - Simulation and test now show identical behavior (parent change Sun→Mars at day 1532) - Comet enters Mars's SOI at 0.003787 AU (just within 0.003792 AU SOI radius) - Comet is ejected from solar system after Mars encounter (ends at 58.7 AU with e=1.0) - Renderer now correctly displays elliptical, parabolic, and hyperbolic trajectories - Orbits update dynamically when gravitational parent changes ### Test Results All tests passing (21 assertions in 5 test cases) ✓ ## Outstanding Issues - Comet remains Mars's child after leaving Mars's SOI - `find_dominant_body()` doesn't check if body is still within current parent's SOI - Should switch back to grandparent (Sun) when exiting child SOI - Results in comet staying as Mars-relative even after ejection