@ -37,46 +37,107 @@ void setup_camera(RenderState* render_state) {
// Update camera with keyboard/mouse controls
void update_camera ( RenderState * render_state , SimulationState * sim ) {
// If following a body, update target to body position
float angle_speed = 0.02f ;
// Handle camera follow state transitions
if ( render_state - > camera_follow_body & & ! render_state - > was_following_body ) {
// Just started following - store current offset
if ( render_state - > selected_body_index > = 0 & & render_state - > selected_body_index < sim - > body_count ) {
CelestialBody * body = & sim - > bodies [ render_state - > selected_body_index ] ;
Vector3 body_pos = sim_to_render ( body - > position , render_state - > distance_scale ) ;
render_state - > camera . target = body_pos ;
render_state - > camera_offset = Vector3Subtract ( render_state - > camera . position , body_pos ) ;
}
}
// Update target position when following
if ( render_state - > camera_follow_body & & render_state - > selected_body_index > = 0 & &
render_state - > selected_body_index < sim - > body_count ) {
CelestialBody * body = & sim - > bodies [ render_state - > selected_body_index ] ;
Vector3 body_pos = sim_to_render ( body - > position , render_state - > distance_scale ) ;
render_state - > camera . target = body_pos ;
render_state - > camera . position = Vector3Add ( body_pos , render_state - > camera_offset ) ;
}
// Orbital camera rotation with arrow keys
float camera_distance = Vector3Distance ( render_state - > camera . position , render_state - > camera . target ) ;
float angle_speed = 0.02f ;
// Camera rotation with proper up vector
Vector3 up = ( Vector3 ) { 0.0f , 1.0f , 0.0f } ; // Global up for space
Vector3 to_camera = Vector3Subtract ( render_state - > camera . position , render_state - > camera . target ) ;
float camera_distance = Vector3Length ( to_camera ) ;
// Rotate around target
// Rotate around target using cross products
if ( IsKeyDown ( KEY_LEFT ) ) {
Vector3 pos = render_state - > camera . position ;
float angle = angle_speed ;
float x = pos . x * cosf ( angle ) - pos . z * sinf ( angle ) ;
float z = pos . x * sinf ( angle ) + pos . z * cosf ( angle ) ;
render_state - > camera . position . x = x ;
render_state - > camera . position . z = z ;
Vector3 right = Vector3Normalize ( Vector3CrossProduct ( up , to_camera ) ) ;
Vector3 forward = Vector3Normalize ( to_camera ) ;
// Rotate forward vector around right axis
float cos_a = cosf ( angle_speed ) ;
float sin_a = sinf ( angle_speed ) ;
Vector3 new_forward = Vector3Add (
Vector3Scale ( forward , cos_a ) ,
Vector3Scale ( Vector3CrossProduct ( right , forward ) , sin_a )
) ;
render_state - > camera . position = Vector3Add (
render_state - > camera . target ,
Vector3Scale ( new_forward , camera_distance )
) ;
if ( render_state - > camera_follow_body ) {
render_state - > camera_offset = Vector3Subtract (
render_state - > camera . position ,
render_state - > camera . target
) ;
}
}
if ( IsKeyDown ( KEY_RIGHT ) ) {
Vector3 pos = render_state - > camera . position ;
float angle = - angle_speed ;
float x = pos . x * cosf ( angle ) - pos . z * sinf ( angle ) ;
float z = pos . x * sinf ( angle ) + pos . z * cosf ( angle ) ;
render_state - > camera . position . x = x ;
render_state - > camera . position . z = z ;
Vector3 right = Vector3Normalize ( Vector3CrossProduct ( up , to_camera ) ) ;
Vector3 forward = Vector3Normalize ( to_camera ) ;
// Rotate forward vector around right axis
float cos_a = cosf ( - angle_speed ) ;
float sin_a = sinf ( - angle_speed ) ;
Vector3 new_forward = Vector3Add (
Vector3Scale ( forward , cos_a ) ,
Vector3Scale ( Vector3CrossProduct ( right , forward ) , sin_a )
) ;
render_state - > camera . position = Vector3Add (
render_state - > camera . target ,
Vector3Scale ( new_forward , camera_distance )
) ;
if ( render_state - > camera_follow_body ) {
render_state - > camera_offset = Vector3Subtract (
render_state - > camera . position ,
render_state - > camera . target
) ;
}
}
// Zoom in/out with up/down keys
if ( IsKeyDown ( KEY_UP ) & & camera_distance > 10.0f ) {
Vector3 direction = Vector3Subtract ( render_state - > camera . target , render_state - > camera . position ) ;
direction = Vector3Normalize ( direction ) ;
Vector3 direction = Vector3Normalize ( Vector3Subtract ( render_state - > camera . target , render_state - > camera . position ) ) ;
render_state - > camera . position = Vector3Add ( render_state - > camera . position , Vector3Scale ( direction , 2.0f ) ) ;
if ( render_state - > camera_follow_body ) {
render_state - > camera_offset = Vector3Subtract (
render_state - > camera . position ,
render_state - > camera . target
) ;
}
}
if ( IsKeyDown ( KEY_DOWN ) ) {
Vector3 direction = Vector3Subtract ( render_state - > camera . position , render_state - > camera . target ) ;
direction = Vector3Normalize ( direction ) ;
Vector3 direction = Vector3Normalize ( Vector3Subtract ( render_state - > camera . position , render_state - > camera . target ) ) ;
render_state - > camera . position = Vector3Add ( render_state - > camera . position , Vector3Scale ( direction , 2.0f ) ) ;
if ( render_state - > camera_follow_body ) {
render_state - > camera_offset = Vector3Subtract (
render_state - > camera . position ,
render_state - > camera . target
) ;
}
}
// Toggle info display with I key
@ -98,6 +159,9 @@ void update_camera(RenderState* render_state, SimulationState* sim) {
render_state - > camera_follow_body = false ;
}
}
// Store previous follow state
render_state - > was_following_body = render_state - > camera_follow_body ;
}
// Transform from simulation coordinates (XY plane) to render coordinates (XZ plane)