@ -17,10 +17,71 @@ void init_renderer(int width, int height, const char* title) {
}
// Close raylib
void close_renderer ( ) {
void close_renderer ( RenderState * render_state ) {
if ( render_state - > texture_loaded ) {
UnloadTexture ( render_state - > spacecraft_texture ) ;
for ( int i = 0 ; i < 6 ; i + + ) {
UnloadTexture ( render_state - > maneuver_textures [ i ] ) ;
}
render_state - > texture_loaded = false ;
}
CloseWindow ( ) ;
}
Texture2D generate_spacecraft_texture ( ) {
Image img = GenImageColor ( 64 , 64 , BLANK ) ;
ImageDrawCircle ( & img , 32 , 32 , 28 , ( Color ) { 0 , 255 , 255 , 255 } ) ;
ImageDrawLine ( & img , 32 , 10 , 32 , 50 , ( Color ) { 0 , 0 , 0 , 255 } ) ;
ImageDrawLine ( & img , 32 , 10 , 25 , 17 , ( Color ) { 0 , 0 , 0 , 255 } ) ;
ImageDrawLine ( & img , 32 , 10 , 39 , 17 , ( Color ) { 0 , 0 , 0 , 255 } ) ;
Texture2D tex = LoadTextureFromImage ( img ) ;
UnloadImage ( img ) ;
return tex ;
}
Texture2D generate_maneuver_marker_texture ( Color color ) {
Image img = GenImageColor ( 32 , 32 , BLANK ) ;
ImageDrawTriangle ( & img ,
( Vector2 ) { 16 , 4 } ,
( Vector2 ) { 4 , 28 } ,
( Vector2 ) { 28 , 28 } ,
color ) ;
Texture2D tex = LoadTextureFromImage ( img ) ;
UnloadImage ( img ) ;
return tex ;
}
void ensure_textures_loaded ( RenderState * render_state ) {
if ( render_state - > texture_loaded ) return ;
render_state - > spacecraft_texture = generate_spacecraft_texture ( ) ;
render_state - > maneuver_textures [ 0 ] = generate_maneuver_marker_texture ( ( Color ) { 0 , 255 , 0 , 200 } ) ;
render_state - > maneuver_textures [ 1 ] = generate_maneuver_marker_texture ( ( Color ) { 255 , 0 , 0 , 200 } ) ;
render_state - > maneuver_textures [ 2 ] = generate_maneuver_marker_texture ( ( Color ) { 255 , 255 , 0 , 200 } ) ;
render_state - > maneuver_textures [ 3 ] = generate_maneuver_marker_texture ( ( Color ) { 255 , 165 , 0 , 200 } ) ;
render_state - > maneuver_textures [ 4 ] = generate_maneuver_marker_texture ( ( Color ) { 255 , 0 , 255 , 200 } ) ;
render_state - > maneuver_textures [ 5 ] = generate_maneuver_marker_texture ( ( Color ) { 0 , 255 , 255 , 200 } ) ;
render_state - > texture_loaded = true ;
}
float calculate_spacecraft_angle ( Vec3 velocity , Camera3D camera ) {
if ( vec3_magnitude ( velocity ) < 0.01 ) return 0.0f ;
Vector3 render_vel = sim_to_render ( velocity , 1.0 ) ;
Vector2 vel_2d = ( Vector2 ) { render_vel . x , render_vel . z } ;
Vector2 cam_2d = ( Vector2 ) { camera . position . x , camera . position . z } ;
return Vector2Angle ( vel_2d , cam_2d ) ;
}
// Setup the 3D camera
void setup_camera ( RenderState * render_state ) {
render_state - > camera . position = ( Vector3 ) { 0.0f , 50.0f , 100.0f } ;
@ -29,9 +90,14 @@ void setup_camera(RenderState* render_state) {
render_state - > camera . fovy = 45.0f ;
render_state - > camera . projection = CAMERA_PERSPECTIVE ;
// Set scaling factors (same scale for distances and sizes)
render_state - > distance_scale = 1e-9 ; // Meters to scaled units (1 unit = 1 billion meters)
render_state - > size_scale = 1e-9 ; // Same scale for body sizes (minimum size still applies)
render_state - > distance_scale = 1e-9 ;
render_state - > size_scale = 1e-9 ;
render_state - > texture_loaded = false ;
render_state - > spacecraft_texture = ( Texture2D ) { 0 , 0 , 0 , 0 , 0 } ;
for ( int i = 0 ; i < 6 ; i + + ) {
render_state - > maneuver_textures [ i ] = ( Texture2D ) { 0 , 0 , 0 , 0 , 0 } ;
}
}
// Update camera with keyboard/mouse controls
@ -206,57 +272,67 @@ void render_body(CelestialBody* body, RenderState* render_state) {
DrawSphereWires ( position , radius , 16 , 16 , color ) ;
}
// Render a single spacecraft as a simple geometric marker
void render_spacecraft ( Spacecraft * craft , RenderState * render_state ) {
Vector3 position = sim_to_render ( craft - > position , render_state - > distance_scal e) ;
ensure_textures_loaded ( render_stat e) ;
// Fixed size for visibility at solar system distances
float marker_radius = 5.0f ;
Color spacecraft_color = { 0 , 255 , 255 , 255 } ; // Cyan
DrawSphereWires ( position , marker_radius , 8 , 8 , spacecraft_color ) ;
Vector3 position = sim_to_render ( craft - > position , render_state - > distance_scale ) ;
float billboard_size = 20.0f ;
Color spacecraft_color = { 0 , 255 , 255 , 255 } ;
float angle = calculate_spacecraft_angle ( craft - > local_velocity , render_state - > camera ) ;
DrawBillboardPro ( render_state - > camera ,
render_state - > spacecraft_texture ,
( Rectangle ) { 0 , 0 , 64 , 64 } ,
position ,
( Vector3 ) { 0 , 1 , 0 } ,
( Vector2 ) { billboard_size , billboard_size } ,
( Vector2 ) { billboard_size / 2 , billboard_size / 2 } ,
angle ,
spacecraft_color ) ;
}
// Render a maneuver marker for a spacecraft
void render_maneuver_marker ( Spacecraft * craft , Maneuver * maneuver , RenderState * render_state ) {
if ( maneuver - > executed ) {
return ; // Don't show markers for executed maneuvers
return ;
}
Vector3 position = sim_to_render ( craft - > position , render_state - > distance_scale ) ;
ensure_textures_loaded ( render_stat e) ;
// Size based on delta-v magnitude
float marker_size = ( float ) ( maneuver - > delta_v / 100.0f ) ; // Scale by delta-v
if ( marker_size < 2 .0f) marker_size = 2 .0f;
if ( marker_size > 10 .0f ) marker_size = 10 .0f ;
Vector3 position = sim_to_render ( craft - > position , render_state - > distance_scale ) ;
float marker_size = ( float ) ( maneuver - > delta_v / 100.0f ) ;
if ( marker_size < 4 .0f) marker_size = 4 .0f;
if ( marker_size > 12 .0f ) marker_size = 12 .0f ;
// Color based on direction
Color marker_color ;
int texture_index ;
switch ( maneuver - > direction ) {
case BURN_PROGRADE :
marker_color = ( Color ) { 0 , 255 , 0 , 200 } ; // Green
texture_index = 0 ;
break ;
case BURN_RETROGRADE :
marker_color = ( Color ) { 255 , 0 , 0 , 200 } ; // Red
texture_index = 1 ;
break ;
case BURN_NORMAL :
marker_color = ( Color ) { 255 , 255 , 0 , 200 } ; // Yellow
texture_index = 2 ;
break ;
case BURN_ANTINORMAL :
marker_color = ( Color ) { 255 , 165 , 0 , 200 } ; // Orange
texture_index = 3 ;
break ;
case BURN_RADIAL_IN :
marker_color = ( Color ) { 255 , 0 , 255 , 200 } ; // Magenta
texture_index = 4 ;
break ;
case BURN_RADIAL_OUT :
marker_color = ( Color ) { 0 , 255 , 255 , 200 } ; // Cyan
texture_index = 5 ;
break ;
default :
marker_color = ( Color ) { 255 , 255 , 255 , 200 } ; // White
texture_index = 0 ;
break ;
}
DrawCube ( position , marker_size , marker_size , marker_size , marker_color ) ;
DrawBillboard ( render_state - > camera ,
render_state - > maneuver_textures [ texture_index ] ,
position ,
marker_size ,
WHITE ) ;
}
struct OrbitalBasis {